<commit_before>package statuscake

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strings"
	"strconv"

	"github.com/google/go-querystring/query"
)

//Ssl represent the data received by the API with GET
type Ssl struct {
	ID             string              `json:"id"                 url:"id,omitempty"`
	Domain         string              `json:"domain"             url:"domain,omitempty"`
	Checkrate      int                 `json:"checkrate"          url:"checkrate,omitempty"`
	ContactGroupsC string              `                          url:"contact_groups,omitempty"`
	AlertAt        string              `json:"alert_at"           url:"alert_at,omitempty"`
	AlertReminder  bool                `json:"alert_reminder"     url:"alert_expiry,omitempty"`
	AlertExpiry    bool                `json:"alert_expiry"       url:"alert_reminder,omitempty"`
	AlertBroken    bool                `json:"alert_broken"       url:"alert_broken,omitempty"`
	AlertMixed     bool                `json:"alert_mixed"        url:"alert_mixed,omitempty"`
	Paused         bool                `json:"paused"`
	IssuerCn       string              `json:"issuer_cn"`
	CertScore      string              `json:"cert_score"`
	CipherScore    string              `json:"cipher_score"`
	CertStatus     string              `json:"cert_status"`
	Cipher         string              `json:"cipher"`
	ValidFromUtc   string              `json:"valid_from_utc"`
	ValidUntilUtc  string              `json:"valid_until_utc"`
	MixedContent   []map[string]string `json:"mixed_content"`
	Flags          map[string]bool     `json:"flags"`
	ContactGroups  []string            `json:"contact_groups"`
	LastReminder   int                 `json:"last_reminder"`
	LastUpdatedUtc string              `json:"last_updated_utc"`
}

//PartialSsl represent  a ssl test creation or modification
type PartialSsl struct {
	ID             int
	Domain         string
	Checkrate      string
	ContactGroupsC string
	AlertAt        string
	AlertExpiry    bool
	AlertReminder  bool
	AlertBroken    bool
	AlertMixed     bool
}

type createSsl struct {
	ID             int    `url:"id,omitempty"`
	Domain         string `url:"domain"         json:"domain"`
	Checkrate      string `url:"checkrate"      json:"checkrate"`
	ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
	AlertAt        string `url:"alert_at"       json:"alert_at"`
	AlertExpiry    bool   `url:"alert_expiry"   json:"alert_expiry"`
	AlertReminder  bool   `url:"alert_reminder" json:"alert_reminder"`
	AlertBroken    bool   `url:"alert_broken"   json:"alert_broken"`
	AlertMixed     bool   `url:"alert_mixed"    json:"alert_mixed"`
}

type updateSsl struct {
	ID             int    `url:"id"`
	Domain         string `url:"domain"         json:"domain"`
	Checkrate      string `url:"checkrate"      json:"checkrate"`
	ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
	AlertAt        string `url:"alert_at"       json:"alert_at"`
	AlertExpiry    bool   `url:"alert_expiry"   json:"alert_expiry"`
	AlertReminder  bool   `url:"alert_reminder" json:"alert_reminder"`
	AlertBroken    bool   `url:"alert_broken"   json:"alert_broken"`
	AlertMixed     bool   `url:"alert_mixed"    json:"alert_mixed"`
}

type sslUpdateResponse struct {
	Success bool   `json:"Success"`
	Message interface{} `json:"Message"`
}

type sslCreateResponse struct {
	Success bool   `json:"Success"`
	Message interface{} `json:"Message"`
	Input createSsl `json:"Input"`
}

//Ssls represent the actions done wit the API
type Ssls interface {
	All() ([]*Ssl, error)
	completeSsl(*PartialSsl) (*Ssl, error)
	Detail(string) (*Ssl, error)
	Update(*PartialSsl) (*Ssl, error)
	UpdatePartial(*PartialSsl) (*PartialSsl, error)
	Delete(ID string) error
	CreatePartial(*PartialSsl) (*PartialSsl, error)
	Create(*PartialSsl) (*Ssl, error)
}

func consolidateSsl(s *Ssl) {
	(*s).ContactGroupsC = strings.Trim(strings.Join(strings.Fields(fmt.Sprint((*s).ContactGroups)), ","), "[]")
}

func findSsl(responses []*Ssl, id string) (*Ssl, error) {
	var response *Ssl
	for _, elem := range responses {
		if (*elem).ID == id {
			return elem, nil
		}
	}
	return response, fmt.Errorf("%s Not found", id)
}

func (tt *ssls) completeSsl(s *PartialSsl) (*Ssl, error) {
	full, err := tt.Detail(strconv.Itoa((*s).ID))
	if err != nil {
		return nil, err
	}
	(*full).ContactGroups = strings.Split((*s).ContactGroupsC,",")
	return full, nil
}

//Partial return a PartialSsl corresponding to the Ssl
func Partial(s *Ssl) (*PartialSsl,error) {
	if s==nil {
		return nil,fmt.Errorf("s is nil")
	}
	id,err:=strconv.Atoi(s.ID)
	if(err!=nil){
		return nil,err
	}
	return &PartialSsl{
		ID: id,
		Domain: s.Domain,
		Checkrate: strconv.Itoa(s.Checkrate),
		ContactGroupsC: s.ContactGroupsC,
		AlertReminder: s.AlertReminder,
		AlertExpiry: s.AlertExpiry,
		AlertBroken: s.AlertBroken,
		AlertMixed: s.AlertMixed,
		AlertAt: s.AlertAt,
	},nil

}

type ssls struct {
	client apiClient
}

//NewSsls return a new ssls
func NewSsls(c apiClient) Ssls {
	return &ssls{
		client: c,
	}
}

//All return a list of all the ssl from the API
func (tt *ssls) All() ([]*Ssl, error) {
	rawResponse, err := tt.client.get("/SSL", nil)
	if err != nil {
		return nil, fmt.Errorf("Error getting StatusCake Ssl: %s", err.Error())
	}
	var getResponse []*Ssl
	err = json.NewDecoder(rawResponse.Body).Decode(&getResponse)
	if err != nil {
		return nil, err
	}

	for ssl := range getResponse {
		consolidateSsl(getResponse[ssl])
	}

	return getResponse, err
}

//Detail return the ssl corresponding to the id
func (tt *ssls) Detail(id string) (*Ssl, error) {
	responses, err := tt.All()
	if err != nil {
		return nil, err
	}
	mySsl, errF := findSsl(responses, id)
	if errF != nil {
		return nil, errF
	}
	return mySsl, nil
}

//Update update the API with s and create one if s.ID=0 then return the corresponding Ssl
func (tt *ssls) Update(s *PartialSsl) (*Ssl, error) {
	var err error
	s, err = tt.UpdatePartial(s)
	if err!= nil {
		return nil, err
	}
	return tt.completeSsl(s)
}

//UpdatePartial update the API with s and create one if s.ID=0 then return the corresponding PartialSsl
func (tt *ssls) UpdatePartial(s *PartialSsl) (*PartialSsl, error) {

	if((*s).ID == 0){
		return tt.CreatePartial(s)
	}
	var v url.Values

	v, _ = query.Values(updateSsl(*s))

	rawResponse, err := tt.client.put("/SSL/Update", v)
	if err != nil {
		return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
	}

	var updateResponse sslUpdateResponse
	err = json.NewDecoder(rawResponse.Body).Decode(&updateResponse)
	if err != nil {
		return nil, err
	}

	if !updateResponse.Success {
		return nil, fmt.Errorf("%s", updateResponse.Message.(string))
	}

	return s, nil
}

//Delete delete the ssl which ID is id
func (tt *ssls) Delete(id string) error {
	_, err := tt.client.delete("/SSL/Update", url.Values{"id": {fmt.Sprint(id)}})
	if err != nil {
		return err
	}

	return nil
}

//Create create the ssl whith the data in s and return the Ssl created
func (tt *ssls) Create(s *PartialSsl) (*Ssl, error) {
	var err error
	s, err = tt.CreatePartial(s)
	if err!= nil {
		return nil, err
	}
	return tt.completeSsl(s)
}

//CreatePartial create the ssl whith the data in s and return the PartialSsl created
func (tt *ssls) CreatePartial(s *PartialSsl) (*PartialSsl, error) {
	(*s).ID=0
	var v url.Values
	v, _ = query.Values(createSsl(*s))

	rawResponse, err := tt.client.put("/SSL/Update", v)
	if err != nil {
		return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
	}

	var createResponse sslCreateResponse
	err = json.NewDecoder(rawResponse.Body).Decode(&createResponse)
	if err != nil {
		return nil, err
	}

	if !createResponse.Success {
		return nil, fmt.Errorf("%s", createResponse.Message.(string))
	}
	*s = PartialSsl(createResponse.Input)
	(*s).ID = int(createResponse.Message.(float64))

	return s,nil
}

<commit_msg>ssl: go fmt<commit_after>package statuscake

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strconv"
	"strings"

	"github.com/google/go-querystring/query"
)

//Ssl represent the data received by the API with GET
type Ssl struct {
	ID             string              `json:"id"                 url:"id,omitempty"`
	Domain         string              `json:"domain"             url:"domain,omitempty"`
	Checkrate      int                 `json:"checkrate"          url:"checkrate,omitempty"`
	ContactGroupsC string              `                          url:"contact_groups,omitempty"`
	AlertAt        string              `json:"alert_at"           url:"alert_at,omitempty"`
	AlertReminder  bool                `json:"alert_reminder"     url:"alert_expiry,omitempty"`
	AlertExpiry    bool                `json:"alert_expiry"       url:"alert_reminder,omitempty"`
	AlertBroken    bool                `json:"alert_broken"       url:"alert_broken,omitempty"`
	AlertMixed     bool                `json:"alert_mixed"        url:"alert_mixed,omitempty"`
	Paused         bool                `json:"paused"`
	IssuerCn       string              `json:"issuer_cn"`
	CertScore      string              `json:"cert_score"`
	CipherScore    string              `json:"cipher_score"`
	CertStatus     string              `json:"cert_status"`
	Cipher         string              `json:"cipher"`
	ValidFromUtc   string              `json:"valid_from_utc"`
	ValidUntilUtc  string              `json:"valid_until_utc"`
	MixedContent   []map[string]string `json:"mixed_content"`
	Flags          map[string]bool     `json:"flags"`
	ContactGroups  []string            `json:"contact_groups"`
	LastReminder   int                 `json:"last_reminder"`
	LastUpdatedUtc string              `json:"last_updated_utc"`
}

//PartialSsl represent  a ssl test creation or modification
type PartialSsl struct {
	ID             int
	Domain         string
	Checkrate      string
	ContactGroupsC string
	AlertAt        string
	AlertExpiry    bool
	AlertReminder  bool
	AlertBroken    bool
	AlertMixed     bool
}

type createSsl struct {
	ID             int    `url:"id,omitempty"`
	Domain         string `url:"domain"         json:"domain"`
	Checkrate      string `url:"checkrate"      json:"checkrate"`
	ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
	AlertAt        string `url:"alert_at"       json:"alert_at"`
	AlertExpiry    bool   `url:"alert_expiry"   json:"alert_expiry"`
	AlertReminder  bool   `url:"alert_reminder" json:"alert_reminder"`
	AlertBroken    bool   `url:"alert_broken"   json:"alert_broken"`
	AlertMixed     bool   `url:"alert_mixed"    json:"alert_mixed"`
}

type updateSsl struct {
	ID             int    `url:"id"`
	Domain         string `url:"domain"         json:"domain"`
	Checkrate      string `url:"checkrate"      json:"checkrate"`
	ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
	AlertAt        string `url:"alert_at"       json:"alert_at"`
	AlertExpiry    bool   `url:"alert_expiry"   json:"alert_expiry"`
	AlertReminder  bool   `url:"alert_reminder" json:"alert_reminder"`
	AlertBroken    bool   `url:"alert_broken"   json:"alert_broken"`
	AlertMixed     bool   `url:"alert_mixed"    json:"alert_mixed"`
}

type sslUpdateResponse struct {
	Success bool        `json:"Success"`
	Message interface{} `json:"Message"`
}

type sslCreateResponse struct {
	Success bool        `json:"Success"`
	Message interface{} `json:"Message"`
	Input   createSsl   `json:"Input"`
}

//Ssls represent the actions done wit the API
type Ssls interface {
	All() ([]*Ssl, error)
	completeSsl(*PartialSsl) (*Ssl, error)
	Detail(string) (*Ssl, error)
	Update(*PartialSsl) (*Ssl, error)
	UpdatePartial(*PartialSsl) (*PartialSsl, error)
	Delete(ID string) error
	CreatePartial(*PartialSsl) (*PartialSsl, error)
	Create(*PartialSsl) (*Ssl, error)
}

func consolidateSsl(s *Ssl) {
	(*s).ContactGroupsC = strings.Trim(strings.Join(strings.Fields(fmt.Sprint((*s).ContactGroups)), ","), "[]")
}

func findSsl(responses []*Ssl, id string) (*Ssl, error) {
	var response *Ssl
	for _, elem := range responses {
		if (*elem).ID == id {
			return elem, nil
		}
	}
	return response, fmt.Errorf("%s Not found", id)
}

func (tt *ssls) completeSsl(s *PartialSsl) (*Ssl, error) {
	full, err := tt.Detail(strconv.Itoa((*s).ID))
	if err != nil {
		return nil, err
	}
	(*full).ContactGroups = strings.Split((*s).ContactGroupsC, ",")
	return full, nil
}

//Partial return a PartialSsl corresponding to the Ssl
func Partial(s *Ssl) (*PartialSsl, error) {
	if s == nil {
		return nil, fmt.Errorf("s is nil")
	}
	id, err := strconv.Atoi(s.ID)
	if err != nil {
		return nil, err
	}
	return &PartialSsl{
		ID:             id,
		Domain:         s.Domain,
		Checkrate:      strconv.Itoa(s.Checkrate),
		ContactGroupsC: s.ContactGroupsC,
		AlertReminder:  s.AlertReminder,
		AlertExpiry:    s.AlertExpiry,
		AlertBroken:    s.AlertBroken,
		AlertMixed:     s.AlertMixed,
		AlertAt:        s.AlertAt,
	}, nil

}

type ssls struct {
	client apiClient
}

//NewSsls return a new ssls
func NewSsls(c apiClient) Ssls {
	return &ssls{
		client: c,
	}
}

//All return a list of all the ssl from the API
func (tt *ssls) All() ([]*Ssl, error) {
	rawResponse, err := tt.client.get("/SSL", nil)
	if err != nil {
		return nil, fmt.Errorf("Error getting StatusCake Ssl: %s", err.Error())
	}
	var getResponse []*Ssl
	err = json.NewDecoder(rawResponse.Body).Decode(&getResponse)
	if err != nil {
		return nil, err
	}

	for ssl := range getResponse {
		consolidateSsl(getResponse[ssl])
	}

	return getResponse, err
}

//Detail return the ssl corresponding to the id
func (tt *ssls) Detail(id string) (*Ssl, error) {
	responses, err := tt.All()
	if err != nil {
		return nil, err
	}
	mySsl, errF := findSsl(responses, id)
	if errF != nil {
		return nil, errF
	}
	return mySsl, nil
}

//Update update the API with s and create one if s.ID=0 then return the corresponding Ssl
func (tt *ssls) Update(s *PartialSsl) (*Ssl, error) {
	var err error
	s, err = tt.UpdatePartial(s)
	if err != nil {
		return nil, err
	}
	return tt.completeSsl(s)
}

//UpdatePartial update the API with s and create one if s.ID=0 then return the corresponding PartialSsl
func (tt *ssls) UpdatePartial(s *PartialSsl) (*PartialSsl, error) {

	if (*s).ID == 0 {
		return tt.CreatePartial(s)
	}
	var v url.Values

	v, _ = query.Values(updateSsl(*s))

	rawResponse, err := tt.client.put("/SSL/Update", v)
	if err != nil {
		return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
	}

	var updateResponse sslUpdateResponse
	err = json.NewDecoder(rawResponse.Body).Decode(&updateResponse)
	if err != nil {
		return nil, err
	}

	if !updateResponse.Success {
		return nil, fmt.Errorf("%s", updateResponse.Message.(string))
	}

	return s, nil
}

//Delete delete the ssl which ID is id
func (tt *ssls) Delete(id string) error {
	_, err := tt.client.delete("/SSL/Update", url.Values{"id": {fmt.Sprint(id)}})
	if err != nil {
		return err
	}

	return nil
}

//Create create the ssl whith the data in s and return the Ssl created
func (tt *ssls) Create(s *PartialSsl) (*Ssl, error) {
	var err error
	s, err = tt.CreatePartial(s)
	if err != nil {
		return nil, err
	}
	return tt.completeSsl(s)
}

//CreatePartial create the ssl whith the data in s and return the PartialSsl created
func (tt *ssls) CreatePartial(s *PartialSsl) (*PartialSsl, error) {
	(*s).ID = 0
	var v url.Values
	v, _ = query.Values(createSsl(*s))

	rawResponse, err := tt.client.put("/SSL/Update", v)
	if err != nil {
		return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
	}

	var createResponse sslCreateResponse
	err = json.NewDecoder(rawResponse.Body).Decode(&createResponse)
	if err != nil {
		return nil, err
	}

	if !createResponse.Success {
		return nil, fmt.Errorf("%s", createResponse.Message.(string))
	}
	*s = PartialSsl(createResponse.Input)
	(*s).ID = int(createResponse.Message.(float64))

	return s, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"regexp"
	"time"

	flag "github.com/cespare/pflag"
)

const (
	binaryDetectionBytes = 8000 // Same as git
)

var (
	dryRun  bool
	verbose bool
)

func init() {
	flag.BoolVarP(&dryRun, "dry-run", "d", false, "Print out what would be changed without changing any files.")
	flag.BoolVarP(&verbose, "verbose", "v", false, "Print out detailed information about each match.")
	flag.Usage = func() { usage(0) }
	flag.Parse()

	rand.Seed(time.Now().UnixNano())
}

func usage(status int) {
	fmt.Printf(`Usage:
		%s [OPTIONS] <FIND> <REPLACE> <FILE1> <FILE2> ...
where OPTIONS are
`, os.Args[0])
	flag.PrintDefaults()
	os.Exit(status)
}

// isBinary guesses whether a file is binary by reading the first X bytes and seeing if there are any nulls.
// Assumes the file is at the beginning.
func isBinary(file *os.File) bool {
	defer file.Seek(0, 0)
	buf := make([]byte, binaryDetectionBytes)
	for {
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			return false
		}
		if n == 0 {
			break
		}
		for i := 0; i < n; i++ {
			if buf[i] == 0x00 {
				return true
			}
		}
		buf = buf[n:]
	}
	return false
}

// isRegular determines whether the file is a regular file or not.
func isRegular(filename string) bool {
	stat, err := os.Lstat(filename)
	if err != nil {
		return false
	}
	return stat.Mode().IsRegular()
}

func main() {
	args := flag.Args()
	if len(args) < 3 {
		usage(1)
	}
	findPattern := args[0]
	replacePattern := args[1]
	files := args[2:]

	find, err := regexp.Compile(findPattern)
	if err != nil {
		fmt.Println("Bad pattern for FIND:", err)
		os.Exit(1)
	}
	replace := []byte(replacePattern)

fileLoop:
	for _, filename := range files {
		if !isRegular(filename) {
			if verbose {
				fmt.Fprintf(os.Stderr, "Skipping %s (not a regular file).\n", filename)
			}
			continue
		}
		file, err := os.Open(filename)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			continue
		}
		defer file.Close()
		if isBinary(file) {
			if verbose {
				fmt.Fprintf(os.Stderr, "Skipping %s (binary file).\n", filename)
			}
			continue
		}

		var temp *os.File
		if !dryRun {
			temp, err = ioutil.TempFile(".", filename)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
			defer temp.Close()
		}

		matched := false
		reader := bufio.NewReader(file)
		line := 0

		for {
			line++
			line, err := reader.ReadBytes('\n')
			if err != nil {
				if err != io.EOF {
					fmt.Fprintln(os.Stderr, err)
				}
				break
			}

			indices := find.FindAllIndex(line, -1)
			if indices == nil {
				if !dryRun {
					_, err := temp.Write(line)
					if err != nil {
						fmt.Fprintln(os.Stderr, err)
						continue fileLoop
					}
				}
				continue
			}
			if !matched {
				// Only print out the filename in blue if we're in verbose mode.
				if verbose {
					fmt.Println(colorize(filename, ColorBlue))
				} else {
					fmt.Println(filename)
				}
				matched = true
			}
			if verbose {
				highlighted := highlight(line, ColorRed, indices)
				replacedAndHighlighted := subAndHighlight(line, find, replace, ColorGreen, indices)

				fmt.Print(colorize("- ", ColorRed))
				os.Stdout.Write(highlighted)
				fmt.Print(colorize("+ ", ColorGreen))
				os.Stdout.Write(replacedAndHighlighted)
			}
			if !dryRun {
				replaced := substitute(line, find, replace, indices)
				_, err := temp.Write(replaced)
				if err != nil {
					fmt.Fprintln(os.Stderr, err)
					continue fileLoop
				}
			}
		}

		if !dryRun {
			// We'll .Close these twice, but that's fine.
			temp.Close()
			file.Close()
			if err := os.Rename(temp.Name(), filename); err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
		}
	}
}
<commit_msg>Handle files without ending newlines properly.<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"regexp"
	"time"

	flag "github.com/cespare/pflag"
)

const (
	binaryDetectionBytes = 8000 // Same as git
)

var (
	dryRun  bool
	verbose bool
)

func init() {
	flag.BoolVarP(&dryRun, "dry-run", "d", false, "Print out what would be changed without changing any files.")
	flag.BoolVarP(&verbose, "verbose", "v", false, "Print out detailed information about each match.")
	flag.Usage = func() { usage(0) }
	flag.Parse()

	rand.Seed(time.Now().UnixNano())
}

func usage(status int) {
	fmt.Printf(`Usage:
		%s [OPTIONS] <FIND> <REPLACE> <FILE1> <FILE2> ...
where OPTIONS are
`, os.Args[0])
	flag.PrintDefaults()
	os.Exit(status)
}

// isBinary guesses whether a file is binary by reading the first X bytes and seeing if there are any nulls.
// Assumes the file is at the beginning.
func isBinary(file *os.File) bool {
	defer file.Seek(0, 0)
	buf := make([]byte, binaryDetectionBytes)
	for {
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			return false
		}
		if n == 0 {
			break
		}
		for i := 0; i < n; i++ {
			if buf[i] == 0x00 {
				return true
			}
		}
		buf = buf[n:]
	}
	return false
}

// isRegular determines whether the file is a regular file or not.
func isRegular(filename string) bool {
	stat, err := os.Lstat(filename)
	if err != nil {
		return false
	}
	return stat.Mode().IsRegular()
}

func main() {
	args := flag.Args()
	if len(args) < 3 {
		usage(1)
	}
	findPattern := args[0]
	replacePattern := args[1]
	files := args[2:]

	find, err := regexp.Compile(findPattern)
	if err != nil {
		fmt.Println("Bad pattern for FIND:", err)
		os.Exit(1)
	}
	replace := []byte(replacePattern)

fileLoop:
	for _, filename := range files {
		if !isRegular(filename) {
			if verbose {
				fmt.Fprintf(os.Stderr, "Skipping %s (not a regular file).\n", filename)
			}
			continue
		}
		file, err := os.Open(filename)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			continue
		}
		defer file.Close()
		if isBinary(file) {
			if verbose {
				fmt.Fprintf(os.Stderr, "Skipping %s (binary file).\n", filename)
			}
			continue
		}

		var temp *os.File
		if !dryRun {
			temp, err = ioutil.TempFile(".", filename)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
			defer temp.Close()
		}

		matched := false
		reader := bufio.NewReader(file)
		line := 0
		done := false

		for !done {
			line++
			line, err := reader.ReadBytes('\n')
			if err != nil {
				if err == io.EOF {
					done = true
					if len(line) == 0 {
						fmt.Println("zero")
						break
					}
				} else {
					fmt.Fprintln(os.Stderr, err)
					break
				}
			}

			indices := find.FindAllIndex(line, -1)
			if indices == nil {
				if !dryRun {
					_, err := temp.Write(line)
					if err != nil {
						fmt.Fprintln(os.Stderr, err)
						continue fileLoop
					}
				}
				continue
			}
			if !matched {
				// Only print out the filename in blue if we're in verbose mode.
				if verbose {
					fmt.Println(colorize(filename, ColorBlue))
				} else {
					fmt.Println(filename)
				}
				matched = true
			}
			if verbose {
				highlighted := highlight(line, ColorRed, indices)
				replacedAndHighlighted := subAndHighlight(line, find, replace, ColorGreen, indices)

				fmt.Print(colorize("- ", ColorRed))
				os.Stdout.Write(highlighted)
				fmt.Print(colorize("+ ", ColorGreen))
				os.Stdout.Write(replacedAndHighlighted)
			}
			if !dryRun {
				replaced := substitute(line, find, replace, indices)
				_, err := temp.Write(replaced)
				if err != nil {
					fmt.Fprintln(os.Stderr, err)
					continue fileLoop
				}
			}
		}

		if !dryRun {
			// We'll .Close these twice, but that's fine.
			temp.Close()
			file.Close()
			if err := os.Rename(temp.Name(), filename); err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}
		}
	}
}
<|endoftext|>


<commit_before>package centrifuge

import (
	"sync"
	"time"
)

type SubscribeSuccessContext struct {
	Resubscribed bool
	Recovered    bool
}

type SubscribeErrorContext struct {
	Error string
}

type UnsubscribeContext struct{}

// MessageHandler is a function to handle messages in channels.
type MessageHandler interface {
	OnMessage(*Sub, *Message)
}

// JoinHandler is a function to handle join messages.
type JoinHandler interface {
	OnJoin(*Sub, *ClientInfo)
}

// LeaveHandler is a function to handle leave messages.
type LeaveHandler interface {
	OnLeave(*Sub, *ClientInfo)
}

// UnsubscribeHandler is a function to handle unsubscribe event.
type UnsubscribeHandler interface {
	OnUnsubscribe(*Sub, *UnsubscribeContext)
}

type SubscribeSuccessHandler interface {
	OnSubscribeSuccess(*Sub, *SubscribeSuccessContext)
}

type SubscribeErrorHandler interface {
	OnSubscribeError(*Sub, *SubscribeErrorContext)
}

// SubEventHandler contains callback functions that will be called when
// corresponding event happens with subscription to channel.
type SubEventHandler struct {
	onMessage          MessageHandler
	onJoin             JoinHandler
	onLeave            LeaveHandler
	onUnsubscribe      UnsubscribeHandler
	onSubscribeSuccess SubscribeSuccessHandler
	onSubscribeError   SubscribeErrorHandler
}

func NewSubEventHandler() *SubEventHandler {
	return &SubEventHandler{}
}

func (h *SubEventHandler) OnMessage(handler MessageHandler) {
	h.onMessage = handler
}

func (h *SubEventHandler) OnJoin(handler JoinHandler) {
	h.onJoin = handler
}

func (h *SubEventHandler) OnLeave(handler LeaveHandler) {
	h.onLeave = handler
}

func (h *SubEventHandler) OnUnsubscribe(handler UnsubscribeHandler) {
	h.onUnsubscribe = handler
}

func (h *SubEventHandler) OnSubscribeSuccess(handler SubscribeSuccessHandler) {
	h.onSubscribeSuccess = handler
}

func (h *SubEventHandler) OnSubscribeError(handler SubscribeErrorHandler) {
	h.onSubscribeError = handler
}

const (
	SUBSCRIBING = iota
	SUBSCRIBED
	SUBERROR
	UNSUBSCRIBED
)

type Sub struct {
	mu              sync.Mutex
	channel         string
	centrifuge      *Client
	status          int
	events          *SubEventHandler
	lastMessageID   *string
	lastMessageMu   sync.RWMutex
	resubscribed    bool
	recovered       bool
	err             error
	subscribeCh     chan struct{}
	needResubscribe bool
}

func (c *Client) newSub(channel string, events *SubEventHandler) *Sub {
	s := &Sub{
		centrifuge:      c,
		channel:         channel,
		events:          events,
		subscribeCh:     make(chan struct{}),
		needResubscribe: true,
	}
	return s
}

func (s *Sub) Channel() string {
	return s.channel
}

// Publish JSON encoded data.
func (s *Sub) Publish(data []byte) error {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return err
		}
		return s.centrifuge.publish(s.channel, data)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return ErrTimeout
	}
}

func (s *Sub) history() ([]Message, error) {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return nil, err
		}
		return s.centrifuge.history(s.channel)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return nil, ErrTimeout
	}
}

// Presence allows to extract presence information for channel.
func (s *Sub) presence() (map[string]ClientInfo, error) {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return nil, err
		}
		return s.centrifuge.presence(s.channel)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return nil, ErrTimeout
	}
}

// Unsubscribe allows to unsubscribe from channel.
func (s *Sub) Unsubscribe() error {
	s.centrifuge.unsubscribe(s.channel)
	s.triggerOnUnsubscribe(false)
	return nil
}

// Subscribe allows to subscribe again after unsubscribing.
func (s *Sub) Subscribe() error {
	s.mu.Lock()
	s.needResubscribe = true
	s.status = SUBSCRIBING
	s.mu.Unlock()
	return s.resubscribe()
}

func (s *Sub) triggerOnUnsubscribe(needResubscribe bool) {
	s.mu.Lock()
	if s.status != SUBSCRIBED {
		s.mu.Unlock()
		return
	}
	s.needResubscribe = needResubscribe
	s.status = UNSUBSCRIBED
	s.mu.Unlock()
	if s.events != nil && s.events.onUnsubscribe != nil {
		handler := s.events.onUnsubscribe
		handler.OnUnsubscribe(s, &UnsubscribeContext{})
	}
}

func (s *Sub) subscribeSuccess(recovered bool) {
	s.mu.Lock()
	if s.status == SUBSCRIBED {
		s.mu.Unlock()
		return
	}
	s.status = SUBSCRIBED
	close(s.subscribeCh)
	resubscribed := s.resubscribed
	s.mu.Unlock()
	if s.events != nil && s.events.onSubscribeSuccess != nil {
		handler := s.events.onSubscribeSuccess
		handler.OnSubscribeSuccess(s, &SubscribeSuccessContext{Resubscribed: resubscribed, Recovered: recovered})
	}
	s.mu.Lock()
	s.resubscribed = true
	s.mu.Unlock()
}

func (s *Sub) subscribeError(err error) {
	s.mu.Lock()
	if s.status == SUBERROR {
		s.mu.Unlock()
		return
	}
	s.err = err
	s.status = SUBERROR
	close(s.subscribeCh)
	s.mu.Unlock()
	if s.events != nil && s.events.onSubscribeError != nil {
		handler := s.events.onSubscribeError
		handler.OnSubscribeError(s, &SubscribeErrorContext{Error: err.Error()})
	}
}

func (s *Sub) handleMessage(m *Message) {
	var handler MessageHandler
	if s.events != nil && s.events.onMessage != nil {
		handler = s.events.onMessage
	}
	mid := m.UID
	s.lastMessageMu.Lock()
	s.lastMessageID = &mid
	s.lastMessageMu.Unlock()
	if handler != nil {
		handler.OnMessage(s, m)
	}
}

func (s *Sub) handleJoinMessage(info *ClientInfo) {
	var handler JoinHandler
	if s.events != nil && s.events.onJoin != nil {
		handler = s.events.onJoin
	}
	if handler != nil {
		handler.OnJoin(s, info)
	}
}

func (s *Sub) handleLeaveMessage(info *ClientInfo) {
	var handler LeaveHandler
	if s.events != nil && s.events.onLeave != nil {
		handler = s.events.onLeave
	}
	if handler != nil {
		handler.OnLeave(s, info)
	}
}

func (s *Sub) resubscribe() error {
	s.mu.Lock()
	if s.status == SUBSCRIBED {
		s.mu.Unlock()
		return nil
	}
	needResubscribe := s.needResubscribe
	s.mu.Unlock()
	if !needResubscribe {
		return nil
	}

	s.centrifuge.mutex.Lock()
	if s.centrifuge.status != CONNECTED {
		s.centrifuge.mutex.Unlock()
		return nil
	}
	s.centrifuge.mutex.Unlock()

	s.mu.Lock()
	s.subscribeCh = make(chan struct{})
	s.mu.Unlock()

	privateSign, err := s.centrifuge.privateSign(s.channel)
	if err != nil {
		return err
	}

	var msgID *string
	s.lastMessageMu.Lock()
	if s.lastMessageID != nil {
		msg := *s.lastMessageID
		msgID = &msg
	}
	s.lastMessageMu.Unlock()
	body, err := s.centrifuge.sendSubscribe(s.channel, msgID, privateSign)
	if err != nil {
		s.subscribeError(err)
		return err
	}
	if !body.Status {
		return ErrBadSubscribeStatus
	}

	if len(body.Messages) > 0 {
		for i := len(body.Messages) - 1; i >= 0; i-- {
			s.handleMessage(messageFromRaw(&body.Messages[i]))
		}
	} else {
		lastID := string(body.Last)
		s.lastMessageMu.Lock()
		s.lastMessageID = &lastID
		s.lastMessageMu.Unlock()
	}

	s.subscribeSuccess(body.Recovered)

	return nil
}
<commit_msg>comments<commit_after>package centrifuge

import (
	"sync"
	"time"
)

// SubscribeSuccessContext is a subscribe success event context passed to event callback.
type SubscribeSuccessContext struct {
	Resubscribed bool
	Recovered    bool
}

// SubscribeErrorContext is a subscribe error event context passed to event callback.
type SubscribeErrorContext struct {
	Error string
}

// UnsubscribeContext is a context passed to unsubscribe event callback.
type UnsubscribeContext struct{}

// MessageHandler is a function to handle messages in channels.
type MessageHandler interface {
	OnMessage(*Sub, *Message)
}

// JoinHandler is a function to handle join messages.
type JoinHandler interface {
	OnJoin(*Sub, *ClientInfo)
}

// LeaveHandler is a function to handle leave messages.
type LeaveHandler interface {
	OnLeave(*Sub, *ClientInfo)
}

// UnsubscribeHandler is a function to handle unsubscribe event.
type UnsubscribeHandler interface {
	OnUnsubscribe(*Sub, *UnsubscribeContext)
}

// SubscribeSuccessHandler is a function to handle subscribe success event.
type SubscribeSuccessHandler interface {
	OnSubscribeSuccess(*Sub, *SubscribeSuccessContext)
}

// SubscribeErrorHandler is a function to handle subscribe error event.
type SubscribeErrorHandler interface {
	OnSubscribeError(*Sub, *SubscribeErrorContext)
}

// SubEventHandler contains callback functions that will be called when
// corresponding event happens with subscription to channel.
type SubEventHandler struct {
	onMessage          MessageHandler
	onJoin             JoinHandler
	onLeave            LeaveHandler
	onUnsubscribe      UnsubscribeHandler
	onSubscribeSuccess SubscribeSuccessHandler
	onSubscribeError   SubscribeErrorHandler
}

// NewSubEventHandler initializes new SubEventHandler.
func NewSubEventHandler() *SubEventHandler {
	return &SubEventHandler{}
}

// OnMessage allows to set MessageHandler to SubEventHandler.
func (h *SubEventHandler) OnMessage(handler MessageHandler) {
	h.onMessage = handler
}

// OnJoin allows to set JoinHandler to SubEventHandler.
func (h *SubEventHandler) OnJoin(handler JoinHandler) {
	h.onJoin = handler
}

// OnLeave allows to set LeaveHandler to SubEventHandler.
func (h *SubEventHandler) OnLeave(handler LeaveHandler) {
	h.onLeave = handler
}

// OnUnsubscribe allows to set UnsubscribeHandler to SubEventHandler.
func (h *SubEventHandler) OnUnsubscribe(handler UnsubscribeHandler) {
	h.onUnsubscribe = handler
}

// OnSubscribeSuccess allows to set SubscribeSuccessHandler to SubEventHandler.
func (h *SubEventHandler) OnSubscribeSuccess(handler SubscribeSuccessHandler) {
	h.onSubscribeSuccess = handler
}

// OnSubscribeError allows to set SubscribeErrorHandler to SubEventHandler.
func (h *SubEventHandler) OnSubscribeError(handler SubscribeErrorHandler) {
	h.onSubscribeError = handler
}

const (
	SUBSCRIBING = iota
	SUBSCRIBED
	SUBERROR
	UNSUBSCRIBED
)

// Sub describes client subscription to channel.
type Sub struct {
	mu              sync.Mutex
	channel         string
	centrifuge      *Client
	status          int
	events          *SubEventHandler
	lastMessageID   *string
	lastMessageMu   sync.RWMutex
	resubscribed    bool
	recovered       bool
	err             error
	subscribeCh     chan struct{}
	needResubscribe bool
}

func (c *Client) newSub(channel string, events *SubEventHandler) *Sub {
	s := &Sub{
		centrifuge:      c,
		channel:         channel,
		events:          events,
		subscribeCh:     make(chan struct{}),
		needResubscribe: true,
	}
	return s
}

// Channel returns subscription channel.
func (s *Sub) Channel() string {
	return s.channel
}

// Publish allows to publish JSON encoded data to subscription channel.
func (s *Sub) Publish(data []byte) error {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return err
		}
		return s.centrifuge.publish(s.channel, data)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return ErrTimeout
	}
}

func (s *Sub) history() ([]Message, error) {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return nil, err
		}
		return s.centrifuge.history(s.channel)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return nil, ErrTimeout
	}
}

func (s *Sub) presence() (map[string]ClientInfo, error) {
	s.mu.Lock()
	subCh := s.subscribeCh
	s.mu.Unlock()
	select {
	case <-subCh:
		s.mu.Lock()
		err := s.err
		s.mu.Unlock()
		if err != nil {
			return nil, err
		}
		return s.centrifuge.presence(s.channel)
	case <-time.After(time.Duration(s.centrifuge.config.TimeoutMilliseconds) * time.Millisecond):
		return nil, ErrTimeout
	}
}

// Unsubscribe allows to unsubscribe from channel.
func (s *Sub) Unsubscribe() error {
	s.centrifuge.unsubscribe(s.channel)
	s.triggerOnUnsubscribe(false)
	return nil
}

// Subscribe allows to subscribe again after unsubscribing.
func (s *Sub) Subscribe() error {
	s.mu.Lock()
	s.needResubscribe = true
	s.status = SUBSCRIBING
	s.mu.Unlock()
	return s.resubscribe()
}

func (s *Sub) triggerOnUnsubscribe(needResubscribe bool) {
	s.mu.Lock()
	if s.status != SUBSCRIBED {
		s.mu.Unlock()
		return
	}
	s.needResubscribe = needResubscribe
	s.status = UNSUBSCRIBED
	s.mu.Unlock()
	if s.events != nil && s.events.onUnsubscribe != nil {
		handler := s.events.onUnsubscribe
		handler.OnUnsubscribe(s, &UnsubscribeContext{})
	}
}

func (s *Sub) subscribeSuccess(recovered bool) {
	s.mu.Lock()
	if s.status == SUBSCRIBED {
		s.mu.Unlock()
		return
	}
	s.status = SUBSCRIBED
	close(s.subscribeCh)
	resubscribed := s.resubscribed
	s.mu.Unlock()
	if s.events != nil && s.events.onSubscribeSuccess != nil {
		handler := s.events.onSubscribeSuccess
		handler.OnSubscribeSuccess(s, &SubscribeSuccessContext{Resubscribed: resubscribed, Recovered: recovered})
	}
	s.mu.Lock()
	s.resubscribed = true
	s.mu.Unlock()
}

func (s *Sub) subscribeError(err error) {
	s.mu.Lock()
	if s.status == SUBERROR {
		s.mu.Unlock()
		return
	}
	s.err = err
	s.status = SUBERROR
	close(s.subscribeCh)
	s.mu.Unlock()
	if s.events != nil && s.events.onSubscribeError != nil {
		handler := s.events.onSubscribeError
		handler.OnSubscribeError(s, &SubscribeErrorContext{Error: err.Error()})
	}
}

func (s *Sub) handleMessage(m *Message) {
	var handler MessageHandler
	if s.events != nil && s.events.onMessage != nil {
		handler = s.events.onMessage
	}
	mid := m.UID
	s.lastMessageMu.Lock()
	s.lastMessageID = &mid
	s.lastMessageMu.Unlock()
	if handler != nil {
		handler.OnMessage(s, m)
	}
}

func (s *Sub) handleJoinMessage(info *ClientInfo) {
	var handler JoinHandler
	if s.events != nil && s.events.onJoin != nil {
		handler = s.events.onJoin
	}
	if handler != nil {
		handler.OnJoin(s, info)
	}
}

func (s *Sub) handleLeaveMessage(info *ClientInfo) {
	var handler LeaveHandler
	if s.events != nil && s.events.onLeave != nil {
		handler = s.events.onLeave
	}
	if handler != nil {
		handler.OnLeave(s, info)
	}
}

func (s *Sub) resubscribe() error {
	s.mu.Lock()
	if s.status == SUBSCRIBED {
		s.mu.Unlock()
		return nil
	}
	needResubscribe := s.needResubscribe
	s.mu.Unlock()
	if !needResubscribe {
		return nil
	}

	s.centrifuge.mutex.Lock()
	if s.centrifuge.status != CONNECTED {
		s.centrifuge.mutex.Unlock()
		return nil
	}
	s.centrifuge.mutex.Unlock()

	s.mu.Lock()
	s.subscribeCh = make(chan struct{})
	s.mu.Unlock()

	privateSign, err := s.centrifuge.privateSign(s.channel)
	if err != nil {
		return err
	}

	var msgID *string
	s.lastMessageMu.Lock()
	if s.lastMessageID != nil {
		msg := *s.lastMessageID
		msgID = &msg
	}
	s.lastMessageMu.Unlock()
	body, err := s.centrifuge.sendSubscribe(s.channel, msgID, privateSign)
	if err != nil {
		s.subscribeError(err)
		return err
	}
	if !body.Status {
		return ErrBadSubscribeStatus
	}

	if len(body.Messages) > 0 {
		for i := len(body.Messages) - 1; i >= 0; i-- {
			s.handleMessage(messageFromRaw(&body.Messages[i]))
		}
	} else {
		lastID := string(body.Last)
		s.lastMessageMu.Lock()
		s.lastMessageID = &lastID
		s.lastMessageMu.Unlock()
	}

	s.subscribeSuccess(body.Recovered)

	return nil
}
<|endoftext|>


<commit_before>package id3v2

import (
	"bufio"
	"bytes"
	"errors"
	"github.com/bogem/id3v2/frame"
	"github.com/bogem/id3v2/util"
	"io/ioutil"
	"os"
)

type Tag struct {
	frames    map[string]frame.Framer
	commonIDs map[string]string

	File         *os.File
	OriginalSize uint32
}

func (t *Tag) SetAttachedPicture(pf frame.PictureFramer) error {
	var f frame.APICSequencer
	id := t.commonIDs["Attached Picture"]

	existingFrame := t.frames[id]
	if existingFrame == nil {
		f = frame.NewAPICSequence()
	} else {
		f = existingFrame.(frame.APICSequencer)
	}

	if err := f.AddPicture(pf); err != nil {
		return err
	}

	t.frames[id] = f
	return nil
}

func (t *Tag) SetTextFrame(id string, text string) {
	var f frame.TextFramer

	existingFrame := t.frames[id]
	if existingFrame == nil {
		f = new(frame.TextFrame)
	} else {
		f = existingFrame.(frame.TextFramer)
	}

	f.SetText(text)
	t.frames[id] = f
}

func (t *Tag) SetTitle(title string) {
	t.SetTextFrame(t.commonIDs["Title"], title)
}

func (t *Tag) SetArtist(artist string) {
	t.SetTextFrame(t.commonIDs["Artist"], artist)
}

func (t *Tag) SetAlbum(album string) {
	t.SetTextFrame(t.commonIDs["Album"], album)
}

func (t *Tag) SetYear(year string) {
	t.SetTextFrame(t.commonIDs["Year"], year)
}

func (t *Tag) SetGenre(genre string) {
	t.SetTextFrame(t.commonIDs["Genre"], genre)
}

func NewTag(file *os.File) *Tag {
	return &Tag{
		frames:    make(map[string]frame.Framer),
		commonIDs: frame.V24CommonIDs,

		File:         file,
		OriginalSize: 0,
	}
}

func ParseTag(file *os.File) (*Tag, error) {
	header, err := ParseHeader(file)
	if err != nil {
		err = errors.New("Trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header == nil {
		return NewTag(file), nil
	}
	if header.Version < 3 {
		err = errors.New("Unsupported version of ID3 tag")
		return nil, err
	}

	tag := &Tag{
		frames:    make(map[string]frame.Framer),
		commonIDs: frame.V24CommonIDs,

		File:         file,
		OriginalSize: TagHeaderSize + header.FramesSize,
	}

	return tag, nil
}

func (t *Tag) Flush() error {
	// Creating a temp file for mp3 file, which will contain new tag
	newFile, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}
	newFileBuf := bufio.NewWriter(newFile)

	// Writing to new file new tag header
	if _, err := newFileBuf.Write(FormTagHeader()); err != nil {
		return err
	}

	// Writing to new file new frames
	// And getting size of them
	frames, err := t.FormFrames()
	if err != nil {
		return err
	}
	framesSize, err := newFileBuf.Write(frames)
	if err != nil {
		return err
	}

	// Getting a music part of mp3
	// (Discarding an original tag of mp3)
	f := t.File
	defer f.Close()
	if _, err := f.Seek(0, os.SEEK_SET); err != nil {
		return err
	}
	originalFileBuf := bufio.NewReader(f)
	if _, err := originalFileBuf.Discard(int(t.OriginalSize)); err != nil {
		return err
	}

	// Writing to new file the music part
	if _, err = newFileBuf.ReadFrom(originalFileBuf); err != nil {
		return err
	}

	// Flushing the buffered data to new file
	if err = newFileBuf.Flush(); err != nil {
		return err
	}

	// Setting size of frames to new file
	if err = setSize(newFile, uint32(framesSize)); err != nil {
		return err
	}

	// Replacing original file with new file
	if err = os.Rename(newFile.Name(), f.Name()); err != nil {
		return err
	}

	// And closing it
	if err = newFile.Close(); err != nil {
		return err
	}

	return nil
}

func setSize(f *os.File, size uint32) (err error) {
	if _, err := f.Seek(0, os.SEEK_SET); err != nil {
		return err
	}

	sizeBytes, err := util.FormSize(size)
	if err != nil {
		return
	}

	if _, err = f.WriteAt(sizeBytes, 6); err != nil {
		return
	}

	return
}

func (t Tag) FormFrames() ([]byte, error) {
	b := bytesBufPool.Get().(*bytes.Buffer)
	b.Reset()

	for id, f := range t.frames {
		formedFrame := f.Form()
		frameHeader, err := formFrameHeader(id, uint32(len(formedFrame)))
		if err != nil {
			return nil, err
		}
		b.Write(frameHeader)
		b.Write(formedFrame)
	}

	bytesBufPool.Put(b)
	return b.Bytes(), nil
}

func formFrameHeader(id string, frameSize uint32) ([]byte, error) {
	b := bytesBufPool.Get().(*bytes.Buffer)
	b.Reset()

	b.WriteString(id)
	if size, err := util.FormSize(frameSize); err != nil {
		return nil, err
	} else {
		b.Write(size)
	}
	b.WriteByte(0)
	b.WriteByte(0)

	bytesBufPool.Put(b)
	return b.Bytes(), nil
}
<commit_msg>Delete errors from tag.SetAttachedPicture()<commit_after>package id3v2

import (
	"bufio"
	"bytes"
	"errors"
	"github.com/bogem/id3v2/frame"
	"github.com/bogem/id3v2/util"
	"io/ioutil"
	"os"
)

type Tag struct {
	frames    map[string]frame.Framer
	commonIDs map[string]string

	File         *os.File
	OriginalSize uint32
}

func (t *Tag) SetAttachedPicture(pf frame.PictureFramer) error {
	var f frame.APICSequencer
	id := t.commonIDs["Attached Picture"]

	existingFrame := t.frames[id]
	if existingFrame == nil {
		f = frame.NewAPICSequence()
	} else {
		f = existingFrame.(frame.APICSequencer)
	}

	f.AddPicture(pf)

	t.frames[id] = f
	return nil
}

func (t *Tag) SetTextFrame(id string, text string) {
	var f frame.TextFramer

	existingFrame := t.frames[id]
	if existingFrame == nil {
		f = new(frame.TextFrame)
	} else {
		f = existingFrame.(frame.TextFramer)
	}

	f.SetText(text)
	t.frames[id] = f
}

func (t *Tag) SetTitle(title string) {
	t.SetTextFrame(t.commonIDs["Title"], title)
}

func (t *Tag) SetArtist(artist string) {
	t.SetTextFrame(t.commonIDs["Artist"], artist)
}

func (t *Tag) SetAlbum(album string) {
	t.SetTextFrame(t.commonIDs["Album"], album)
}

func (t *Tag) SetYear(year string) {
	t.SetTextFrame(t.commonIDs["Year"], year)
}

func (t *Tag) SetGenre(genre string) {
	t.SetTextFrame(t.commonIDs["Genre"], genre)
}

func NewTag(file *os.File) *Tag {
	return &Tag{
		frames:    make(map[string]frame.Framer),
		commonIDs: frame.V24CommonIDs,

		File:         file,
		OriginalSize: 0,
	}
}

func ParseTag(file *os.File) (*Tag, error) {
	header, err := ParseHeader(file)
	if err != nil {
		err = errors.New("Trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header == nil {
		return NewTag(file), nil
	}
	if header.Version < 3 {
		err = errors.New("Unsupported version of ID3 tag")
		return nil, err
	}

	tag := &Tag{
		frames:    make(map[string]frame.Framer),
		commonIDs: frame.V24CommonIDs,

		File:         file,
		OriginalSize: TagHeaderSize + header.FramesSize,
	}

	return tag, nil
}

func (t *Tag) Flush() error {
	// Creating a temp file for mp3 file, which will contain new tag
	newFile, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}
	newFileBuf := bufio.NewWriter(newFile)

	// Writing to new file new tag header
	if _, err := newFileBuf.Write(FormTagHeader()); err != nil {
		return err
	}

	// Writing to new file new frames
	// And getting size of them
	frames, err := t.FormFrames()
	if err != nil {
		return err
	}
	framesSize, err := newFileBuf.Write(frames)
	if err != nil {
		return err
	}

	// Getting a music part of mp3
	// (Discarding an original tag of mp3)
	f := t.File
	defer f.Close()
	if _, err := f.Seek(0, os.SEEK_SET); err != nil {
		return err
	}
	originalFileBuf := bufio.NewReader(f)
	if _, err := originalFileBuf.Discard(int(t.OriginalSize)); err != nil {
		return err
	}

	// Writing to new file the music part
	if _, err = newFileBuf.ReadFrom(originalFileBuf); err != nil {
		return err
	}

	// Flushing the buffered data to new file
	if err = newFileBuf.Flush(); err != nil {
		return err
	}

	// Setting size of frames to new file
	if err = setSize(newFile, uint32(framesSize)); err != nil {
		return err
	}

	// Replacing original file with new file
	if err = os.Rename(newFile.Name(), f.Name()); err != nil {
		return err
	}

	// And closing it
	if err = newFile.Close(); err != nil {
		return err
	}

	return nil
}

func setSize(f *os.File, size uint32) (err error) {
	if _, err := f.Seek(0, os.SEEK_SET); err != nil {
		return err
	}

	sizeBytes, err := util.FormSize(size)
	if err != nil {
		return
	}

	if _, err = f.WriteAt(sizeBytes, 6); err != nil {
		return
	}

	return
}

func (t Tag) FormFrames() ([]byte, error) {
	b := bytesBufPool.Get().(*bytes.Buffer)
	b.Reset()

	for id, f := range t.frames {
		formedFrame := f.Form()
		frameHeader, err := formFrameHeader(id, uint32(len(formedFrame)))
		if err != nil {
			return nil, err
		}
		b.Write(frameHeader)
		b.Write(formedFrame)
	}

	bytesBufPool.Put(b)
	return b.Bytes(), nil
}

func formFrameHeader(id string, frameSize uint32) ([]byte, error) {
	b := bytesBufPool.Get().(*bytes.Buffer)
	b.Reset()

	b.WriteString(id)
	if size, err := util.FormSize(frameSize); err != nil {
		return nil, err
	} else {
		b.Write(size)
	}
	b.WriteByte(0)
	b.WriteByte(0)

	bytesBufPool.Put(b)
	return b.Bytes(), nil
}
<|endoftext|>


<commit_before>package tty

import (
	"os"
)

func New() (*TTY, error) {
	return open()
}

func (tty *TTY) ReadRune() (rune, error) {
	return tty.readRune()
}

func (tty *TTY) Close() error {
	return tty.close()
}

func (tty *TTY) Size() (int, int, error) {
	return tty.size()
}

func (tty *TTY) Input() *os.File {
	return tty.input()
}

func (tty *TTY) Output() *os.File {
	return tty.output()
}
<commit_msg>add ReadPassword<commit_after>package tty

import (
	"os"
	"unicode"
)

func New() (*TTY, error) {
	return open()
}

func (tty *TTY) ReadRune() (rune, error) {
	return tty.readRune()
}

func (tty *TTY) Close() error {
	return tty.close()
}

func (tty *TTY) Size() (int, int, error) {
	return tty.size()
}

func (tty *TTY) Input() *os.File {
	return tty.input()
}

func (tty *TTY) Output() *os.File {
	return tty.output()
}

func (tty *TTY) ReadPassword() (string, error) {
	rs := []rune{}
loop:
	for {
		r, err := tty.readRune()
		if err != nil {
			return "", err
		}
		switch r {
		case 13:
			break loop
		case 8:
			if len(rs) > 0 {
				rs = rs[:len(rs)-1]
				tty.Output().WriteString("\b \b")
			}
		default:
			if unicode.IsPrint(r) {
				rs = append(rs, r)
				tty.Output().WriteString("*")
			}
		}
	}
	tty.Output().WriteString("\n")
	return string(rs), nil
}
<|endoftext|>


<commit_before>package uik

import (
	"code.google.com/p/draw2d/draw2d"
	"github.com/skelterjohn/go.wde"
	"github.com/skelterjohn/go.wde/xgb"
)

var WindowGenerator func(parent wde.Window, width, height int) (window wde.Window, err error)

func init() {
	WindowGenerator = func(parent wde.Window, width, height int) (window wde.Window, err error) {
		window, err = xgb.NewWindow(width, height)
		return
	}
}

// The Block type is a basic unit that can receive events and draw itself.
type Block struct {
	Parent *Foundation

	CloseEvents     chan wde.CloseEvent
	MouseDownEvents chan MouseDownEvent
	MouseUpEvents   chan MouseUpEvent

	allEventsIn     chan<- interface{}
	allEventsOut    <-chan interface{}

	Draw            chan draw2d.GraphicContext
	Redraw          chan Bounds

	Paint func(gc draw2d.GraphicContext)

	// minimum point relative to the block's parent: only the parent should set this
	Min Coord
	// size of block
	Size Coord
}

func (b *Block) handleSplitEvents() {
	for e := range b.allEventsOut {
		switch e := e.(type) {
		case MouseDownEvent:
			b.MouseDownEvents <- e
		case MouseUpEvent:
			b.MouseUpEvents <- e
		case wde.CloseEvent:
			b.CloseEvents <- e
		}
	}
}

func (b *Block) BoundsInParent() (bounds Bounds) {
	bounds.Min = b.Min
	bounds.Max = b.Min
	bounds.Max.X += b.Size.X
	bounds.Max.Y += b.Size.Y
	return
}

func (b *Block) MakeChannels() {
	b.CloseEvents = make(chan wde.CloseEvent)
	b.MouseDownEvents = make(chan MouseDownEvent)
	b.MouseUpEvents = make(chan MouseUpEvent)
	b.allEventsIn, b.allEventsOut = QueuePipe()
	b.Draw = make(chan draw2d.GraphicContext)
	b.Redraw = make(chan Bounds)
}

// The foundation type is for channeling events to children, and passing along
// draw calls.
type Foundation struct {
	Block
	Children    []*Block

	// this block currently has keyboard priority
	KeyboardBlock    *Block
}

func (f *Foundation) AddBlock(b *Block) {
	// TODO: place the block somewhere clever
	// TODO: resize the block in a clever way
	f.Children = append(f.Children, b)
	b.Parent = f
}

func (f *Foundation) handleDrawing() {
	for {
		select {
		case gc := <-f.Draw:
			if f.Paint != nil {
				f.Paint(gc)
			}
			for _, child := range f.Children {
				gc.Save()

				// TODO: clip to child.BoundsInParent()?

				gc.Translate(child.Min.X, child.Min.Y)
				child.Draw <- gc

				gc.Restore()
			}
		case dirtyBounds := <-f.Redraw:
			dirtyBounds.Min.X -= f.Min.X
			dirtyBounds.Min.Y -= f.Min.Y
			f.Parent.Redraw <- dirtyBounds
		}
	}
}

func (f *Foundation) BlockForCoord(p Coord) (b *Block) {
	// quad-tree one day?
	for _, bl := range f.Children {
		if bl.BoundsInParent().Contains(p) {
			b = bl
			return
		}
	}
	return
}

func (f *Foundation) handleEvents() {
	for {
		select {
		case e := <-f.CloseEvents:
			for _, b := range f.Children {
				b.CloseEvents <- e
			}
		case e := <-f.MouseDownEvents:
			b := f.BlockForCoord(e.Loc)
			if b == nil {
				break
			}
			e.X -= int(b.Min.X)
			e.Y -= int(b.Min.Y)
			b.MouseDownEvents <- e
		case e := <-f.MouseUpEvents:
			b := f.BlockForCoord(e.Loc)
			if b == nil {
				break
			}
			e.X -= int(b.Min.X)
			e.Y -= int(b.Min.Y)
			b.MouseUpEvents <- e
		}
	}
}

// A foundation that wraps a wde.Window
type WindowFoundation struct {
	Foundation
	W wde.Window
}

func NewWindow(parent wde.Window, width, height int) (wf *WindowFoundation, err error) {
	wf = new(WindowFoundation)

	wf.W, err = WindowGenerator(parent, width, height)
	if err != nil {
		return
	}
	wf.MakeChannels()

	wf.Size = Coord{float64(width), float64(height)}

	go wf.handleWindowEvents()
	go wf.handleWindowDrawing()
	go wf.handleEvents()

	return
}

func (wf *WindowFoundation) Show() {
	wf.W.Show()
	wf.Redraw <- wf.BoundsInParent()
}

// wraps mouse events with float64 coordinates
func (wf *WindowFoundation) handleWindowEvents() {
	for e := range wf.W.EventChan() {
		switch e := e.(type) {
		case wde.CloseEvent:
			wf.CloseEvents <- e
			wf.W.Close()
		case wde.MouseDownEvent:
			wf.MouseDownEvents <- MouseDownEvent{
				MouseDownEvent: e,
				MouseLocator: MouseLocator {
					Loc: Coord{float64(e.X), float64(e.Y)},
				},
			}
		case wde.MouseUpEvent:
			wf.MouseUpEvents <- MouseUpEvent{
				MouseUpEvent: e,
				MouseLocator: MouseLocator {
					Loc: Coord{float64(e.X), float64(e.Y)},
				},
			}
		}
	}
}

func (wf *WindowFoundation) handleWindowDrawing() {

	for {
		select {
		case dirtyBounds := <-wf.Redraw:
			gc := draw2d.NewGraphicContext(wf.W.Screen())
			gc.Clear()
			gc.BeginPath()
			// TODO: pass dirtyBounds too, to avoid redrawing out of reach components
			_ = dirtyBounds
			if wf.Paint != nil {
				wf.Paint(gc)
			}
			for _, child := range wf.Children {
				gc.Save()

				// TODO: clip to child.BoundsInParent()?

				gc.Translate(child.Min.X, child.Min.Y)
				child.Draw <- gc

				gc.Restore()
			}

			wf.W.FlushImage()
		}
	}
}
<commit_msg>activated chan buffering<commit_after>package uik

import (
	"code.google.com/p/draw2d/draw2d"
	"github.com/skelterjohn/go.wde"
	"github.com/skelterjohn/go.wde/xgb"
)

var WindowGenerator func(parent wde.Window, width, height int) (window wde.Window, err error)

func init() {
	WindowGenerator = func(parent wde.Window, width, height int) (window wde.Window, err error) {
		window, err = xgb.NewWindow(width, height)
		return
	}
}

// The Block type is a basic unit that can receive events and draw itself.
type Block struct {
	Parent *Foundation

	CloseEvents     chan wde.CloseEvent
	MouseDownEvents chan MouseDownEvent
	MouseUpEvents   chan MouseUpEvent

	allEventsIn     chan<- interface{}
	allEventsOut    <-chan interface{}

	Draw            chan draw2d.GraphicContext
	Redraw          chan Bounds

	Paint func(gc draw2d.GraphicContext)

	// minimum point relative to the block's parent: only the parent should set this
	Min Coord
	// size of block
	Size Coord
}

func (b *Block) handleSplitEvents() {
	for e := range b.allEventsOut {
		switch e := e.(type) {
		case MouseDownEvent:
			b.MouseDownEvents <- e
		case MouseUpEvent:
			b.MouseUpEvents <- e
		case wde.CloseEvent:
			b.CloseEvents <- e
		}
	}
}

func (b *Block) BoundsInParent() (bounds Bounds) {
	bounds.Min = b.Min
	bounds.Max = b.Min
	bounds.Max.X += b.Size.X
	bounds.Max.Y += b.Size.Y
	return
}

func (b *Block) MakeChannels() {
	b.CloseEvents = make(chan wde.CloseEvent)
	b.MouseDownEvents = make(chan MouseDownEvent)
	b.MouseUpEvents = make(chan MouseUpEvent)
	b.Draw = make(chan draw2d.GraphicContext)
	b.Redraw = make(chan Bounds)
	b.allEventsIn, b.allEventsOut = QueuePipe()
	go b.handleSplitEvents()
}

// The foundation type is for channeling events to children, and passing along
// draw calls.
type Foundation struct {
	Block
	Children    []*Block

	// this block currently has keyboard priority
	KeyboardBlock    *Block
}

func (f *Foundation) AddBlock(b *Block) {
	// TODO: place the block somewhere clever
	// TODO: resize the block in a clever way
	f.Children = append(f.Children, b)
	b.Parent = f
}

func (f *Foundation) handleDrawing() {
	for {
		select {
		case gc := <-f.Draw:
			if f.Paint != nil {
				f.Paint(gc)
			}
			for _, child := range f.Children {
				gc.Save()

				// TODO: clip to child.BoundsInParent()?

				gc.Translate(child.Min.X, child.Min.Y)
				child.Draw <- gc

				gc.Restore()
			}
		case dirtyBounds := <-f.Redraw:
			dirtyBounds.Min.X -= f.Min.X
			dirtyBounds.Min.Y -= f.Min.Y
			f.Parent.Redraw <- dirtyBounds
		}
	}
}

func (f *Foundation) BlockForCoord(p Coord) (b *Block) {
	// quad-tree one day?
	for _, bl := range f.Children {
		if bl.BoundsInParent().Contains(p) {
			b = bl
			return
		}
	}
	return
}

func (f *Foundation) handleEvents() {
	for {
		select {
		case e := <-f.CloseEvents:
			for _, b := range f.Children {
				b.allEventsIn <- e
			}
		case e := <-f.MouseDownEvents:
			b := f.BlockForCoord(e.Loc)
			if b == nil {
				break
			}
			e.X -= int(b.Min.X)
			e.Y -= int(b.Min.Y)
			b.allEventsIn <- e
		case e := <-f.MouseUpEvents:
			b := f.BlockForCoord(e.Loc)
			if b == nil {
				break
			}
			e.X -= int(b.Min.X)
			e.Y -= int(b.Min.Y)
			b.allEventsIn <- e
		}
	}
}

// A foundation that wraps a wde.Window
type WindowFoundation struct {
	Foundation
	W wde.Window
}

func NewWindow(parent wde.Window, width, height int) (wf *WindowFoundation, err error) {
	wf = new(WindowFoundation)

	wf.W, err = WindowGenerator(parent, width, height)
	if err != nil {
		return
	}
	wf.MakeChannels()

	wf.Size = Coord{float64(width), float64(height)}

	go wf.handleWindowEvents()
	go wf.handleWindowDrawing()
	go wf.handleEvents()

	return
}

func (wf *WindowFoundation) Show() {
	wf.W.Show()
	wf.Redraw <- wf.BoundsInParent()
}

// wraps mouse events with float64 coordinates
func (wf *WindowFoundation) handleWindowEvents() {
	for e := range wf.W.EventChan() {
		switch e := e.(type) {
		case wde.CloseEvent:
			wf.CloseEvents <- e
			wf.W.Close()
		case wde.MouseDownEvent:
			wf.MouseDownEvents <- MouseDownEvent{
				MouseDownEvent: e,
				MouseLocator: MouseLocator {
					Loc: Coord{float64(e.X), float64(e.Y)},
				},
			}
		case wde.MouseUpEvent:
			wf.MouseUpEvents <- MouseUpEvent{
				MouseUpEvent: e,
				MouseLocator: MouseLocator {
					Loc: Coord{float64(e.X), float64(e.Y)},
				},
			}
		}
	}
}

func (wf *WindowFoundation) handleWindowDrawing() {

	for {
		select {
		case dirtyBounds := <-wf.Redraw:
			gc := draw2d.NewGraphicContext(wf.W.Screen())
			gc.Clear()
			gc.BeginPath()
			// TODO: pass dirtyBounds too, to avoid redrawing out of reach components
			_ = dirtyBounds
			if wf.Paint != nil {
				wf.Paint(gc)
			}
			for _, child := range wf.Children {
				gc.Save()

				// TODO: clip to child.BoundsInParent()?

				gc.Translate(child.Min.X, child.Min.Y)
				child.Draw <- gc

				gc.Restore()
			}

			wf.W.FlushImage()
		}
	}
}
<|endoftext|>


<commit_before>package irelate

import (
	"github.com/brentp/vcfgo"
	"github.com/brentp/xopen"
	"log"
)

type Variant struct {
	*vcfgo.Variant
	source  uint32
	related []Relatable
}

func (v *Variant) AddRelated(r Relatable) {
	v.related = append(v.related, r)
}

func (v *Variant) Related() []Relatable {
	return v.related
}

func (v *Variant) SetSource(src uint32) { v.source = src }
func (v *Variant) Source() uint32       { return v.source }

func (v *Variant) Less(o Relatable) bool {
	return Less(v, o)
}

func Vopen(f string) *vcfgo.Reader {
	rdr, err := xopen.Ropen(f)
	if err != nil {
		panic(err)
	}
	vcf, err := vcfgo.NewReader(rdr, true)
	if err != nil {
		log.Fatal(err)
	}
	return vcf
}

func StreamVCF(vcf *vcfgo.Reader) RelatableChannel {
	ch := make(RelatableChannel, 256)
	go func() {
		for {
			v := vcf.Read()
			if v == nil {
				break
			}
			ch <- &Variant{v, 0, make([]Relatable, 0, 40)}
			vcf.Clear()
		}
		close(ch)
	}()
	return ch
}
<commit_msg>remove less from variant<commit_after>package irelate

import (
	"github.com/brentp/vcfgo"
	"github.com/brentp/xopen"
	"log"
)

type Variant struct {
	*vcfgo.Variant
	source  uint32
	related []Relatable
}

func (v *Variant) AddRelated(r Relatable) {
	v.related = append(v.related, r)
}

func (v *Variant) Related() []Relatable {
	return v.related
}

func (v *Variant) SetSource(src uint32) { v.source = src }
func (v *Variant) Source() uint32       { return v.source }

func Vopen(f string) *vcfgo.Reader {
	rdr, err := xopen.Ropen(f)
	if err != nil {
		panic(err)
	}
	vcf, err := vcfgo.NewReader(rdr, true)
	if err != nil {
		log.Fatal(err)
	}
	return vcf
}

func StreamVCF(vcf *vcfgo.Reader) RelatableChannel {
	ch := make(RelatableChannel, 256)
	go func() {
		for {
			v := vcf.Read()
			if v == nil {
				break
			}
			ch <- &Variant{v, 0, make([]Relatable, 0, 40)}
			vcf.Clear()
		}
		close(ch)
	}()
	return ch
}
<|endoftext|>


<commit_before>package web

import (
    "bytes"
    "http"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path"
    "reflect"
    "regexp"
    "strings"
    "template"
)

type Request http.Request

func (r *Request) ParseForm() (err os.Error) {
    req := (*http.Request)(r)
    return req.ParseForm()
}

type Response struct {
    Status     string
    StatusCode int
    Header     map[string]string
    Body       io.Reader
}

func newResponse(statusCode int, body string) *Response {
    text := statusText[statusCode]
    resp := Response{StatusCode: statusCode,
        Status: text,
        Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
    }
    if len(body) == 0 {
        resp.Body = bytes.NewBufferString(text)
    } else {
        resp.Body = bytes.NewBufferString(body)
    }
    return &resp
}

type Context struct {
    *Request
    *Response
}

func (ctx *Context) Abort(code int, message string) {
    ctx.Response = newResponse(code, message)
}

var contextType reflect.Type
var templateDir string
var staticDir string

func init() {
    contextType = reflect.Typeof(Context{})

    cwd := os.Getenv("PWD")
    templateDir = path.Join(cwd, "templates")
    staticDir = path.Join(cwd, "static")
}

type route struct {
    r       string
    cr      *regexp.Regexp
    method  string
    handler *reflect.FuncValue
}

var routes = make(map[*regexp.Regexp]route)

func addRoute(r string, method string, handler interface{}) {
    cr, err := regexp.Compile(r)
    if err != nil {
        log.Stderrf("Error in route regex %q\n", r)
        return
    }
    fv := reflect.NewValue(handler).(*reflect.FuncValue)
    routes[cr] = route{r, cr, method, fv}
}

func httpHandler(c *http.Conn, req *http.Request) {
    path := req.URL.Path

    //try to serve a static file
    if strings.HasPrefix(path, "/static/") {
        staticFile := path[8:]
        if len(staticFile) > 0 {
            http.ServeFile(c, req, "static/"+staticFile)
            return
        }
    }

    req.ParseForm()
    resp := routeHandler((*Request)(req))
    c.WriteHeader(resp.StatusCode)
    if resp.Body != nil {
        body, _ := ioutil.ReadAll(resp.Body)
        c.Write(body)
    }
}

func routeHandler(req *Request) *Response {
    log.Stdout(req.RawURL)
    path := req.URL.Path

    ctx := Context{req, newResponse(200, "")}

    for cr, route := range routes {
        if !cr.MatchString(path) {
            continue
        }
        match := cr.MatchStrings(path)
        if len(match) > 0 {
            if len(match[0]) != len(path) {
                continue
            }
            if req.Method != route.method {
                continue
            }
            ai := 0
            handlerType := route.handler.Type().(*reflect.FuncType)
            expectedIn := handlerType.NumIn()
            args := make([]reflect.Value, expectedIn)

            if expectedIn > 0 {
                a0 := handlerType.In(0)
                ptyp, ok := a0.(*reflect.PtrType)
                if ok {
                    typ := ptyp.Elem()
                    if typ == contextType {
                        args[ai] = reflect.NewValue(&ctx)
                        ai += 1
                        expectedIn -= 1
                    }
                }
            }

            actualIn := len(match) - 1
            if expectedIn != actualIn {
                log.Stderrf("Incorrect number of arguments for %s\n", path)
                return newResponse(500, "")
            }

            for _, arg := range match[1:] {
                args[ai] = reflect.NewValue(arg)
            }
            ret := route.handler.Call(args)[0].(*reflect.StringValue).Get()
            var buf bytes.Buffer
            buf.WriteString(ret)
            resp := ctx.Response
            resp.Body = &buf
            return resp
        }
    }

    return newResponse(404, "")
}

func render(tmplString string, context interface{}) (string, os.Error) {

    var tmpl *template.Template
    var err os.Error

    if tmpl, err = template.Parse(tmplString, nil); err != nil {
        return "", err
    }

    var buf bytes.Buffer

    tmpl.Execute(context, &buf)
    return buf.String(), nil
}

func Render(filename string, context interface{}) (string, os.Error) {
    var templateBytes []uint8
    var err os.Error

    if !strings.HasPrefix(filename, "/") {
        filename = path.Join(templateDir, filename)
    }

    if templateBytes, err = ioutil.ReadFile(filename); err != nil {
        return "", err
    }

    return render(string(templateBytes), context)
}

func RenderString(tmplString string, context interface{}) (string, os.Error) {
    return render(tmplString, context)
}

func Run(addr string) {
    http.Handle("/", http.HandlerFunc(httpHandler))

    log.Stdoutf("web.go serving %s", addr)
    err := http.ListenAndServe(addr, nil)
    if err != nil {
        log.Exit("ListenAndServe:", err)
    }
}

func RunScgi(addr string) {
    log.Stdoutf("web.go serving scgi %s", addr)
    listenAndServeScgi(addr)
}

func Get(route string, handler interface{}) { addRoute(route, "GET", handler) }

func Post(route string, handler interface{}) { addRoute(route, "POST", handler) }

func Head(route string, handler interface{}) { addRoute(route, "HEAD", handler) }

func Put(route string, handler interface{}) { addRoute(route, "PUT", handler) }

func Delete(route string, handler interface{}) {
    addRoute(route, "DELETE", handler)
}

//copied from go's http package, because it's not public
var statusText = map[int]string{
    http.StatusContinue: "Continue",
    http.StatusSwitchingProtocols: "Switching Protocols",

    http.StatusOK: "OK",
    http.StatusCreated: "Created",
    http.StatusAccepted: "Accepted",
    http.StatusNonAuthoritativeInfo: "Non-Authoritative Information",
    http.StatusNoContent: "No Content",
    http.StatusResetContent: "Reset Content",
    http.StatusPartialContent: "Partial Content",

    http.StatusMultipleChoices: "Multiple Choices",
    http.StatusMovedPermanently: "Moved Permanently",
    http.StatusFound: "Found",
    http.StatusSeeOther: "See Other",
    http.StatusNotModified: "Not Modified",
    http.StatusUseProxy: "Use Proxy",
    http.StatusTemporaryRedirect: "Temporary Redirect",

    http.StatusBadRequest: "Bad Request",
    http.StatusUnauthorized: "Unauthorized",
    http.StatusPaymentRequired: "Payment Required",
    http.StatusForbidden: "Forbidden",
    http.StatusNotFound: "Not Found",
    http.StatusMethodNotAllowed: "Method Not Allowed",
    http.StatusNotAcceptable: "Not Acceptable",
    http.StatusProxyAuthRequired: "Proxy Authentication Required",
    http.StatusRequestTimeout: "Request Timeout",
    http.StatusConflict: "Conflict",
    http.StatusGone: "Gone",
    http.StatusLengthRequired: "Length Required",
    http.StatusPreconditionFailed: "Precondition Failed",
    http.StatusRequestEntityTooLarge: "Request Entity Too Large",
    http.StatusRequestURITooLong: "Request URI Too Long",
    http.StatusUnsupportedMediaType: "Unsupported Media Type",
    http.StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
    http.StatusExpectationFailed: "Expectation Failed",

    http.StatusInternalServerError: "Internal Server Error",
    http.StatusNotImplemented: "Not Implemented",
    http.StatusBadGateway: "Bad Gateway",
    http.StatusServiceUnavailable: "Service Unavailable",
    http.StatusGatewayTimeout: "Gateway Timeout",
    http.StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
}
<commit_msg>Set and check directories for static files and templates.<commit_after>package web

import (
    "bytes"
    "http"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path"
    "reflect"
    "regexp"
    "strings"
    "template"
)

type Request http.Request

func (r *Request) ParseForm() (err os.Error) {
    req := (*http.Request)(r)
    return req.ParseForm()
}

type Response struct {
    Status     string
    StatusCode int
    Header     map[string]string
    Body       io.Reader
}

func newResponse(statusCode int, body string) *Response {
    text := statusText[statusCode]
    resp := Response{StatusCode: statusCode,
        Status: text,
        Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
    }
    if len(body) == 0 {
        resp.Body = bytes.NewBufferString(text)
    } else {
        resp.Body = bytes.NewBufferString(body)
    }
    return &resp
}

type Context struct {
    *Request
    *Response
}

func (ctx *Context) Abort(code int, message string) {
    ctx.Response = newResponse(code, message)
}

var contextType reflect.Type
var templateDir string
var staticDir string

func init() {
    contextType = reflect.Typeof(Context{})

    SetTemplateDir("templates")
    SetStaticDir("static")
}

type route struct {
    r       string
    cr      *regexp.Regexp
    method  string
    handler *reflect.FuncValue
}

var routes = make(map[*regexp.Regexp]route)

func addRoute(r string, method string, handler interface{}) {
    cr, err := regexp.Compile(r)
    if err != nil {
        log.Stderrf("Error in route regex %q\n", r)
        return
    }
    fv := reflect.NewValue(handler).(*reflect.FuncValue)
    routes[cr] = route{r, cr, method, fv}
}

func httpHandler(c *http.Conn, req *http.Request) {
    requestPath := req.URL.Path

    //try to serve a static file
    if strings.HasPrefix(requestPath, "/static/") {
        staticFile := requestPath[8:]
        if len(staticFile) > 0 {
            http.ServeFile(c, req, path.Join(staticDir, staticFile))
            return
        }
    }

    req.ParseForm()
    resp := routeHandler((*Request)(req))
    c.WriteHeader(resp.StatusCode)
    if resp.Body != nil {
        body, _ := ioutil.ReadAll(resp.Body)
        c.Write(body)
    }
}

func routeHandler(req *Request) *Response {
    log.Stdout(req.RawURL)
    requestPath := req.URL.Path

    ctx := Context{req, newResponse(200, "")}

    for cr, route := range routes {
        if !cr.MatchString(requestPath) {
            continue
        }
        match := cr.MatchStrings(requestPath)
        if len(match) > 0 {
            if len(match[0]) != len(requestPath) {
                continue
            }
            if req.Method != route.method {
                continue
            }
            ai := 0
            handlerType := route.handler.Type().(*reflect.FuncType)
            expectedIn := handlerType.NumIn()
            args := make([]reflect.Value, expectedIn)

            if expectedIn > 0 {
                a0 := handlerType.In(0)
                ptyp, ok := a0.(*reflect.PtrType)
                if ok {
                    typ := ptyp.Elem()
                    if typ == contextType {
                        args[ai] = reflect.NewValue(&ctx)
                        ai += 1
                        expectedIn -= 1
                    }
                }
            }

            actualIn := len(match) - 1
            if expectedIn != actualIn {
                log.Stderrf("Incorrect number of arguments for %s\n", requestPath)
                return newResponse(500, "")
            }

            for _, arg := range match[1:] {
                args[ai] = reflect.NewValue(arg)
            }
            ret := route.handler.Call(args)[0].(*reflect.StringValue).Get()
            var buf bytes.Buffer
            buf.WriteString(ret)
            resp := ctx.Response
            resp.Body = &buf
            return resp
        }
    }

    return newResponse(404, "")
}

func render(tmplString string, context interface{}) (string, os.Error) {

    var tmpl *template.Template
    var err os.Error

    if tmpl, err = template.Parse(tmplString, nil); err != nil {
        return "", err
    }

    var buf bytes.Buffer

    tmpl.Execute(context, &buf)
    return buf.String(), nil
}

func Render(filename string, context interface{}) (string, os.Error) {
    var templateBytes []uint8
    var err os.Error

    if !strings.HasPrefix(filename, "/") {
        filename = path.Join(templateDir, filename)
    }

    if templateBytes, err = ioutil.ReadFile(filename); err != nil {
        return "", err
    }

    return render(string(templateBytes), context)
}

func RenderString(tmplString string, context interface{}) (string, os.Error) {
    return render(tmplString, context)
}

func Run(addr string) {
    http.Handle("/", http.HandlerFunc(httpHandler))

    log.Stdoutf("web.go serving %s", addr)
    err := http.ListenAndServe(addr, nil)
    if err != nil {
        log.Exit("ListenAndServe:", err)
    }
}

func RunScgi(addr string) {
    log.Stdoutf("web.go serving scgi %s", addr)
    listenAndServeScgi(addr)
}

func Get(route string, handler interface{}) { addRoute(route, "GET", handler) }

func Post(route string, handler interface{}) { addRoute(route, "POST", handler) }

func Head(route string, handler interface{}) { addRoute(route, "HEAD", handler) }

func Put(route string, handler interface{}) { addRoute(route, "PUT", handler) }

func Delete(route string, handler interface{}) {
    addRoute(route, "DELETE", handler)
}

func currentDirectory() string {
    return os.Getenv("PWD")
}

func checkDirectory(dir string) {
    d, e := os.Stat(dir)
    switch {
    case e != nil:
        log.Stderr(e)
    case !d.IsDirectory():
        log.Stderrf("%s is not a directory", dir)
    }
}

func SetTemplateDir(dir string) {
    cwd := currentDirectory()
    templateDir = path.Join(cwd, dir)
    checkDirectory(templateDir)
}

func SetStaticDir(dir string) {
    cwd := currentDirectory()
    staticDir = path.Join(cwd, dir)
    checkDirectory(staticDir)
}

//copied from go's http package, because it's not public
var statusText = map[int]string{
    http.StatusContinue: "Continue",
    http.StatusSwitchingProtocols: "Switching Protocols",

    http.StatusOK: "OK",
    http.StatusCreated: "Created",
    http.StatusAccepted: "Accepted",
    http.StatusNonAuthoritativeInfo: "Non-Authoritative Information",
    http.StatusNoContent: "No Content",
    http.StatusResetContent: "Reset Content",
    http.StatusPartialContent: "Partial Content",

    http.StatusMultipleChoices: "Multiple Choices",
    http.StatusMovedPermanently: "Moved Permanently",
    http.StatusFound: "Found",
    http.StatusSeeOther: "See Other",
    http.StatusNotModified: "Not Modified",
    http.StatusUseProxy: "Use Proxy",
    http.StatusTemporaryRedirect: "Temporary Redirect",

    http.StatusBadRequest: "Bad Request",
    http.StatusUnauthorized: "Unauthorized",
    http.StatusPaymentRequired: "Payment Required",
    http.StatusForbidden: "Forbidden",
    http.StatusNotFound: "Not Found",
    http.StatusMethodNotAllowed: "Method Not Allowed",
    http.StatusNotAcceptable: "Not Acceptable",
    http.StatusProxyAuthRequired: "Proxy Authentication Required",
    http.StatusRequestTimeout: "Request Timeout",
    http.StatusConflict: "Conflict",
    http.StatusGone: "Gone",
    http.StatusLengthRequired: "Length Required",
    http.StatusPreconditionFailed: "Precondition Failed",
    http.StatusRequestEntityTooLarge: "Request Entity Too Large",
    http.StatusRequestURITooLong: "Request URI Too Long",
    http.StatusUnsupportedMediaType: "Unsupported Media Type",
    http.StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
    http.StatusExpectationFailed: "Expectation Failed",

    http.StatusInternalServerError: "Internal Server Error",
    http.StatusNotImplemented: "Not Implemented",
    http.StatusBadGateway: "Bad Gateway",
    http.StatusServiceUnavailable: "Service Unavailable",
    http.StatusGatewayTimeout: "Gateway Timeout",
    http.StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"regexp"
	"strings"
	"time"
)

func WhoBatch(batch string) {
	ppl := strings.Split(batch, "|")
	re, err := regexp.Compile(`^\[[ ]?(\d{1,2}) ([[:alpha:]-]{3})\] ([[:alpha:]]+) .*\((.*)\)`)
	if err != nil {
		log.Fatal(err)
	}

	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// TODO: also check class change for necro->lich
	// TODO: also check for account name change
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	query := "UPDATE chars SET char_level = ?, last_seen = ? " +
		"WHERE char_name = ?"
	stmt, err := tx.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	var lvl string
	var name string
	for _, who := range ppl {
		char := re.FindAllStringSubmatch(who, -1)
		//fmt.Println(char)
		if len(char) > 0 {
			if len(char[0]) == 5 {
				lvl = char[0][1]
				name = char[0][3]
				res, err := stmt.Exec(lvl, date, name)
				if err != nil {
					log.Fatal(err)
				} else {
					affected, err := res.RowsAffected()
					if err != nil {
						log.Fatal(err)
					} else {
						if affected != 1 {
							fmt.Printf("who %s\n", name)
						}
					}
				}
			}
		}
	}

	tx.Commit()
}

func Who(char string, lvl int) {
	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	//fmt.Printf("Time: %v\n", date)

	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	query := "SELECT account_name, char_name FROM chars " +
		"WHERE LOWER(char_name) = LOWER(?)"
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err == sql.ErrNoRows {
		// if char doesn't exist, 'who char'
		fmt.Printf("who %s\n", char)
		return
	} else if err != nil {
		log.Fatal(err)
	} else {
		// if char does exist, tell the DB the time they were spotted and
		// update their level
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}
		query = "UPDATE chars SET char_level = ?, last_seen = ? " +
			"WHERE account_name = ? AND char_name = ?"
		stmt, err := tx.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(lvl, date, acc, name)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	}
}

func WhoChar(char string, lvl int, class string, race string, acct string) {
	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	query := "SELECT account_name, char_name FROM chars " +
		"WHERE LOWER(char_name) = LOWER(?)"
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err == sql.ErrNoRows {
		// if no char, check if account exists in DB, create char
		query = "SELECT account_name FROM accounts " +
			"WHERE LOWER(account_name) = LOWER(?)"
		stmt, err = db.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		err = stmt.QueryRow(char).Scan(&acc)
		if err == sql.ErrNoRows {
			//if no acct, create acccount
			tx, err := db.Begin()
			if err != nil {
				log.Fatal(err)
			}

			query = "INSERT INTO accounts (account_name) VALUES(?)"
			stmt, err := tx.Prepare(query)
			if err != nil {
				log.Fatal(err)
			}
			defer stmt.Close()

			_, err = stmt.Exec(acct)
			if err != nil {
				log.Fatal(err)
			}
			tx.Commit()
		} else if err != nil {
			log.Fatal(err)
		}
		// create character
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}

		query = "INSERT INTO chars VALUES(%s, %s, %s, %s, %s, %s, 't')"
		stmt, err := tx.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(acct, char, class, race, lvl, date)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	} else if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Trim extra crap from who batchmode string<commit_after>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"regexp"
	"strings"
	"time"
)

func WhoBatch(batch string) {
	batch = strings.Trim(batch, "| ")
	ppl := strings.Split(batch, "|")
	re, err := regexp.Compile(`^\[[ ]?(\d{1,2}) ([[:alpha:]-]{3})\] ([[:alpha:]]+) .*\((.*)\)`)
	if err != nil {
		log.Fatal(err)
	}

	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// TODO: also check class change for necro->lich
	// TODO: also check for account name change
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	query := "UPDATE chars SET char_level = ?, last_seen = ? " +
		"WHERE char_name = ?"
	stmt, err := tx.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	var lvl string
	var name string
	for _, who := range ppl {
		char := re.FindAllStringSubmatch(who, -1)
		//fmt.Println(char)
		if len(char) > 0 {
			if len(char[0]) == 5 {
				lvl = char[0][1]
				name = char[0][3]
				res, err := stmt.Exec(lvl, date, name)
				if err != nil {
					log.Fatal(err)
				} else {
					affected, err := res.RowsAffected()
					if err != nil {
						log.Fatal(err)
					} else {
						if affected != 1 {
							fmt.Printf("who %s\n", name)
						}
					}
				}
			}
		}
	}

	tx.Commit()
}

func Who(char string, lvl int) {
	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	//fmt.Printf("Time: %v\n", date)

	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	query := "SELECT account_name, char_name FROM chars " +
		"WHERE LOWER(char_name) = LOWER(?)"
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err == sql.ErrNoRows {
		// if char doesn't exist, 'who char'
		fmt.Printf("who %s\n", char)
		return
	} else if err != nil {
		log.Fatal(err)
	} else {
		// if char does exist, tell the DB the time they were spotted and
		// update their level
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}
		query = "UPDATE chars SET char_level = ?, last_seen = ? " +
			"WHERE account_name = ? AND char_name = ?"
		stmt, err := tx.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(lvl, date, acc, name)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	}
}

func WhoChar(char string, lvl int, class string, race string, acct string) {
	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Fatal(err)
	}
	date := time.Now().In(loc)
	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	query := "SELECT account_name, char_name FROM chars " +
		"WHERE LOWER(char_name) = LOWER(?)"
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err == sql.ErrNoRows {
		// if no char, check if account exists in DB, create char
		query = "SELECT account_name FROM accounts " +
			"WHERE LOWER(account_name) = LOWER(?)"
		stmt, err = db.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		err = stmt.QueryRow(char).Scan(&acc)
		if err == sql.ErrNoRows {
			//if no acct, create acccount
			tx, err := db.Begin()
			if err != nil {
				log.Fatal(err)
			}

			query = "INSERT INTO accounts (account_name) VALUES(?)"
			stmt, err := tx.Prepare(query)
			if err != nil {
				log.Fatal(err)
			}
			defer stmt.Close()

			_, err = stmt.Exec(acct)
			if err != nil {
				log.Fatal(err)
			}
			tx.Commit()
		} else if err != nil {
			log.Fatal(err)
		}
		// create character
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}

		query = "INSERT INTO chars VALUES(%s, %s, %s, %s, %s, %s, 't')"
		stmt, err := tx.Prepare(query)
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(acct, char, class, race, lvl, date)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	} else if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// +build windows

package gopass

import "syscall"
import "unsafe"
import "unicode/utf16"

// Returns password byte array read from terminal without input being echoed.
// Array of bytes does not include end-of-line characters.
func GetPasswd() []byte {
	modkernel32 := syscall.NewLazyDLL("kernel32.dll")
	procReadConsole := modkernel32.NewProc("ReadConsoleW")
	procGetConsoleMode := modkernel32.NewProc("GetConsoleMode")
	procSetConsoleMode := modkernel32.NewProc("SetConsoleMode")

	var mode uint32
	pMode := &mode
	procGetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(unsafe.Pointer(pMode)))

	var echoMode uint32
	echoMode = 4
	var newMode uint32
	newMode = mode ^ echoMode

	procSetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(newMode))

	line := make([]uint16, 300)
	pLine := &line[0]
	var n uint16
	procReadConsole.Call(uintptr(syscall.Stdin), uintptr(unsafe.Pointer(pLine)), uintptr(len(line)), uintptr(unsafe.Pointer(&n)))

    // For some reason n returned seems to big by 2 (Null terminated maybe?)
	if n > 2 {
		n -= 2
	}

	b := []byte(string(utf16.Decode(line[:n])))

	procSetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(mode))

	return b
}
<commit_msg>println for Windows too<commit_after>// +build windows

package gopass

import "syscall"
import "unsafe"
import "unicode/utf16"

// Returns password byte array read from terminal without input being echoed.
// Array of bytes does not include end-of-line characters.
func GetPasswd() []byte {
	modkernel32 := syscall.NewLazyDLL("kernel32.dll")
	procReadConsole := modkernel32.NewProc("ReadConsoleW")
	procGetConsoleMode := modkernel32.NewProc("GetConsoleMode")
	procSetConsoleMode := modkernel32.NewProc("SetConsoleMode")

	var mode uint32
	pMode := &mode
	procGetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(unsafe.Pointer(pMode)))

	var echoMode uint32
	echoMode = 4
	var newMode uint32
	newMode = mode ^ echoMode

	procSetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(newMode))

	line := make([]uint16, 300)
	pLine := &line[0]
	var n uint16
	procReadConsole.Call(uintptr(syscall.Stdin), uintptr(unsafe.Pointer(pLine)), uintptr(len(line)), uintptr(unsafe.Pointer(&n)))

    // For some reason n returned seems to big by 2 (Null terminated maybe?)
	if n > 2 {
		n -= 2
	}

	b := []byte(string(utf16.Decode(line[:n])))

	procSetConsoleMode.Call(uintptr(syscall.Stdin), uintptr(mode))

    println()

	return b
}
<|endoftext|>


<commit_before>package dns

// XfrToken is used when doing [IA]xfr with a remote server.
type XfrToken struct {
	RR    []RR  // the set of RRs in the answer section form the message of the server
	Error error // if something went wrong, this contains the error
}

// XfrReceive performs a [AI]xfr request (depends on the message's Qtype). It returns
// a channel of XfrToken on which the replies from the server are sent. At the end of
// the transfer the channel is closed.
// It panics if the Qtype does not equal TypeAXFR or TypeIXFR. The messages are TSIG checked if
// needed, no other post-processing is performed. The caller must dissect the returned
// messages.
//
// Basic use pattern for receiving an AXFR:
//
//	// m contains the AXFR request
//	t, e := client.XfrReceive(m, "127.0.0.1:53")
//	for r := range t {
//		// ... deal with r.RR or r.Error
//	}
func (c *Client) XfrReceive(q *Msg, a string) (chan *XfrToken, error) {
	w := new(reply)
	w.client = c
	w.addr = a
	w.req = q
	if err := w.dial(); err != nil {
		return nil, err
	}
	if err := w.send(q); err != nil {
		return nil, err
	}
	e := make(chan *XfrToken)
	switch q.Question[0].Qtype {
	case TypeAXFR:
		go w.axfrReceive(e)
		return e, nil
	case TypeIXFR:
		go w.ixfrReceive(e)
		return e, nil
	default:
		return nil, ErrXfrType
	}
	panic("not reached")
}

func (w *reply) axfrReceive(c chan *XfrToken) {
	first := true
	defer w.conn.Close()
	defer close(c)
	for {
		in, err := w.receive()
		if err != nil {
			c <- &XfrToken{in.Answer, err}
			return
		}
		if w.req.Id != in.Id {
			c <- &XfrToken{in.Answer, ErrId}
			return
		}
		if first {
			if !checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, ErrXfrSoa}
				return
			}
			first = !first
		}

		if !first {
			w.tsigTimersOnly = true // Subsequent envelopes use this.
			if checkXfrSOA(in, false) {
				c <- &XfrToken{in.Answer, nil}
				return
			}
			c <- &XfrToken{in.Answer, nil}
		}
	}
	panic("not reached")
}

func (w *reply) ixfrReceive(c chan *XfrToken) {
	var serial uint32 // The first serial seen is the current server serial
	first := true
	defer w.conn.Close()
	defer close(c)
	for {
		in, err := w.receive()
		if err != nil {
			c <- &XfrToken{in.Answer, err}
			return
		}
		if w.req.Id != in.Id {
			c <- &XfrToken{in.Answer, ErrId}
			return
		}
		if first {
			// A single SOA RR signals "no changes"
			if len(in.Answer) == 1 && checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, nil}
				return
			}

			// Check if the returned answer is ok
			if !checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, ErrXfrSoa}
				return
			}
			// This serial is important
			serial = in.Answer[0].(*RR_SOA).Serial
			first = !first
		}

		// Now we need to check each message for SOA records, to see what we need to do
		if !first {
			w.tsigTimersOnly = true
			// If the last record in the IXFR contains the servers' SOA,  we should quit
			if v, ok := in.Answer[len(in.Answer)-1].(*RR_SOA); ok {
				if v.Serial == serial {
					c <- &XfrToken{in.Answer, nil}
					return
				}
			}
			c <- &XfrToken{in.Answer, nil}
		}
	}
	panic("not reached")
}

// Check if he SOA record exists in the Answer section of
// the packet. If first is true the first RR must be a SOA
// if false, the last one should be a SOA.
func checkXfrSOA(in *Msg, first bool) bool {
	if len(in.Answer) > 0 {
		if first {
			return in.Answer[0].Header().Rrtype == TypeSOA
		} else {
			return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
		}
	}
	return false
}

// XfrSend performs an outgoing [IX]xfr depending on the request message. The
// caller is responsible for sending the correct sequence of RR sets through
// the channel c.

// XfrSend performs an outgoing [IX]xfr depending on the request message. As

// long as the channel c is open the transfer proceeds. Any errors when
// sending the messages to the client are signaled in the error
// pointer.
// TSIG and enveloping is handled by this function.
func XfrSend(w ResponseWriter, q *Msg, c chan *XfrToken, e *error) error {
	switch q.Question[0].Qtype {
	case TypeAXFR, TypeIXFR:
		go axfrSend(w, q, c, e)
		return nil
	default:
		return ErrXfrType
	}
	panic("not reached")
}

// TODO(mg): count the RRs and the resulting size.
// when to stop
func axfrSend(w ResponseWriter, req *Msg, c chan *XfrToken, e *error) {
	rep := new(Msg)
	rep.SetReply(req)
	rep.MsgHdr.Authoritative = true

	first := true
	w.TsigTimersOnly(false)
	for x := range c {
		// assume it fits
		rep.Answer = append(rep.Answer, x.RR...)
		if err := w.Write(rep); e != nil {
			*e = err
			return
		}
		if first {
			first = !first
			w.TsigTimersOnly(first)
		}
		rep.Answer = nil
	}
}
<commit_msg>A working outgoing axfr impl.<commit_after>package dns

// XfrToken is used when doing [IA]xfr with a remote server.
type XfrToken struct {
	RR    []RR  // the set of RRs in the answer section of the AXFR reply message
	Error error // if something went wrong, this contains the error
}

// XfrReceive performs a [AI]xfr request (depends on the message's Qtype). It returns
// a channel of XfrToken on which the replies from the server are sent. At the end of
// the transfer the channel is closed.
// It panics if the Qtype does not equal TypeAXFR or TypeIXFR. The messages are TSIG checked if
// needed, no other post-processing is performed. The caller must dissect the returned
// messages.
//
// Basic use pattern for receiving an AXFR:
//
//	// m contains the AXFR request
//	t, e := client.XfrReceive(m, "127.0.0.1:53")
//	for r := range t {
//		// ... deal with r.RR or r.Error
//	}
func (c *Client) XfrReceive(q *Msg, a string) (chan *XfrToken, error) {
	w := new(reply)
	w.client = c
	w.addr = a
	w.req = q
	if err := w.dial(); err != nil {
		return nil, err
	}
	if err := w.send(q); err != nil {
		return nil, err
	}
	e := make(chan *XfrToken)
	switch q.Question[0].Qtype {
	case TypeAXFR:
		go w.axfrReceive(e)
		return e, nil
	case TypeIXFR:
		go w.ixfrReceive(e)
		return e, nil
	default:
		return nil, ErrXfrType
	}
	panic("not reached")
}

func (w *reply) axfrReceive(c chan *XfrToken) {
	first := true
	defer w.conn.Close()
	defer close(c)
	for {
		in, err := w.receive()
		if err != nil {
			c <- &XfrToken{in.Answer, err}
			return
		}
		if w.req.Id != in.Id {
			c <- &XfrToken{in.Answer, ErrId}
			return
		}
		if first {
			if !checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, ErrXfrSoa}
				return
			}
			first = !first
		}

		if !first {
			w.tsigTimersOnly = true // Subsequent envelopes use this.
			if checkXfrSOA(in, false) {
				c <- &XfrToken{in.Answer, nil}
				return
			}
			c <- &XfrToken{in.Answer, nil}
		}
	}
	panic("not reached")
}

func (w *reply) ixfrReceive(c chan *XfrToken) {
	var serial uint32 // The first serial seen is the current server serial
	first := true
	defer w.conn.Close()
	defer close(c)
	for {
		in, err := w.receive()
		if err != nil {
			c <- &XfrToken{in.Answer, err}
			return
		}
		if w.req.Id != in.Id {
			c <- &XfrToken{in.Answer, ErrId}
			return
		}
		if first {
			// A single SOA RR signals "no changes"
			if len(in.Answer) == 1 && checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, nil}
				return
			}

			// Check if the returned answer is ok
			if !checkXfrSOA(in, true) {
				c <- &XfrToken{in.Answer, ErrXfrSoa}
				return
			}
			// This serial is important
			serial = in.Answer[0].(*RR_SOA).Serial
			first = !first
		}

		// Now we need to check each message for SOA records, to see what we need to do
		if !first {
			w.tsigTimersOnly = true
			// If the last record in the IXFR contains the servers' SOA,  we should quit
			if v, ok := in.Answer[len(in.Answer)-1].(*RR_SOA); ok {
				if v.Serial == serial {
					c <- &XfrToken{in.Answer, nil}
					return
				}
			}
			c <- &XfrToken{in.Answer, nil}
		}
	}
	panic("not reached")
}

// Check if he SOA record exists in the Answer section of
// the packet. If first is true the first RR must be a SOA
// if false, the last one should be a SOA.
func checkXfrSOA(in *Msg, first bool) bool {
	if len(in.Answer) > 0 {
		if first {
			return in.Answer[0].Header().Rrtype == TypeSOA
		} else {
			return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
		}
	}
	return false
}

// XfrSend performs an outgoing [AI]xfr depending on the request message. The
// caller is responsible for sending the correct sequence of RR sets through
// the channel c.
// Errors are signaled via the error pointer, when an error occurs the function
// sets the error and returns (it does not close the channel).
// TSIG and enveloping is handled by XfrSend.
//
// Basic use pattern for sending an AXFR:
//
//	// q contains the AXFR request
//	c := make(chan *XfrToken)
//	var e *error
//	err := XfrSend(w, q, c, e)
//	for _, rrset := range rrsets {	// rrset is a []RR
//		c <- rrset
//		if e != nil {
//			close(c)
//			break
//		}
//	}
func XfrSend(w ResponseWriter, q *Msg, c chan *XfrToken, e *error) error {
	switch q.Question[0].Qtype {
	case TypeAXFR, TypeIXFR:
		go axfrSend(w, q, c, e)
		return nil
	default:
		return ErrXfrType
	}
	panic("not reached")
}

// TODO(mg): count the RRs and the resulting size.
func axfrSend(w ResponseWriter, req *Msg, c chan *XfrToken, e *error) {
	rep := new(Msg)
	rep.SetReply(req)
	rep.MsgHdr.Authoritative = true

	first := true
	for x := range c {
		// assume it fits
		rep.Answer = append(rep.Answer, x.RR...)
		if err := w.Write(rep); e != nil {
			*e = err
			return
		}
		w.TsigTimersOnly(first)
		rep.Answer = nil
	}
}
<|endoftext|>