<commit_before>package cli

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/hcl/v2/hclparse"
	"github.com/hashicorp/hcl/v2/hclwrite"
	"github.com/mattn/go-zglob"

	"github.com/gruntwork-io/terragrunt/options"
	"github.com/gruntwork-io/terragrunt/util"
)

// runHCLFmt recursively looks for hcl files in the directory tree starting at workingDir, and formats them
// based on the language style guides provided by Hashicorp. This is done using the official hcl2 library.
func runHCLFmt(terragruntOptions *options.TerragruntOptions) error {

	workingDir := terragruntOptions.WorkingDir
	targetFile := terragruntOptions.HclFile

	// handle when option specifies a particular file
	if targetFile != "" {
		if !filepath.IsAbs(targetFile) {
			targetFile = util.JoinPath(workingDir, targetFile)
		}
		terragruntOptions.Logger.Infof("Formatting hcl file at: %s.", targetFile)
		return formatTgHCL(terragruntOptions, targetFile)
	}

	terragruntOptions.Logger.Infof("Formatting hcl files from the directory tree %s.", terragruntOptions.WorkingDir)
	// zglob normalizes paths to "/"
	tgHclFiles, err := zglob.Glob(util.JoinPath(workingDir, "**", "*.hcl"))
	if err != nil {
		return err
	}

	filteredTgHclFiles := []string{}
	for _, fname := range tgHclFiles {
		// Ignore any files that are in the .terragrunt-cache
		if !util.ListContainsElement(strings.Split(fname, "/"), ".terragrunt-cache") {
			filteredTgHclFiles = append(filteredTgHclFiles, fname)
		} else {
			terragruntOptions.Logger.Debugf("%s was ignored due to being in the terragrunt cache", fname)
		}
	}

	terragruntOptions.Logger.Debugf("Found %d hcl files", len(filteredTgHclFiles))

	var formatErrors *multierror.Error
	for _, tgHclFile := range filteredTgHclFiles {
		err := formatTgHCL(terragruntOptions, tgHclFile)
		if err != nil {
			formatErrors = multierror.Append(formatErrors, err)
		}
	}

	return formatErrors.ErrorOrNil()
}

// formatTgHCL uses the hcl2 library to format the hcl file. This will attempt to parse the HCL file first to
// ensure that there are no syntax errors, before attempting to format it.
func formatTgHCL(terragruntOptions *options.TerragruntOptions, tgHclFile string) error {
	terragruntOptions.Logger.Infof("Formatting %s", tgHclFile)

	info, err := os.Stat(tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error retrieving file info of %s", tgHclFile)
		return err
	}

	contentsStr, err := util.ReadFileAsString(tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error reading %s", tgHclFile)
		return err
	}
	contents := []byte(contentsStr)

	err = checkErrors(contents, tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error parsing %s", tgHclFile)
		return err
	}

	newContents := hclwrite.Format(contents)

	if terragruntOptions.Check {
		if !bytes.Equal(newContents, contents) {
			return fmt.Errorf("Invalid file format %s", tgHclFile)
		}
		return nil
	}

	return ioutil.WriteFile(tgHclFile, newContents, info.Mode())
}

// checkErrors takes in the contents of a hcl file and looks for syntax errors.
func checkErrors(contents []byte, tgHclFile string) error {
	parser := hclparse.NewParser()
	_, diags := parser.ParseHCL(contents, tgHclFile)
	diagWriter := util.GetDiagnosticsWriter(parser)
	diagWriter.WriteDiagnostics(diags)
	if diags.HasErrors() {
		return diags
	}
	return nil
}
<commit_msg>Only show updated files on INFO logs (#1857)<commit_after>package cli

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/hcl/v2/hclparse"
	"github.com/hashicorp/hcl/v2/hclwrite"
	"github.com/mattn/go-zglob"

	"github.com/gruntwork-io/terragrunt/options"
	"github.com/gruntwork-io/terragrunt/util"
)

// runHCLFmt recursively looks for hcl files in the directory tree starting at workingDir, and formats them
// based on the language style guides provided by Hashicorp. This is done using the official hcl2 library.
func runHCLFmt(terragruntOptions *options.TerragruntOptions) error {

	workingDir := terragruntOptions.WorkingDir
	targetFile := terragruntOptions.HclFile

	// handle when option specifies a particular file
	if targetFile != "" {
		if !filepath.IsAbs(targetFile) {
			targetFile = util.JoinPath(workingDir, targetFile)
		}
		terragruntOptions.Logger.Debugf("Formatting hcl file at: %s.", targetFile)
		return formatTgHCL(terragruntOptions, targetFile)
	}

	terragruntOptions.Logger.Debugf("Formatting hcl files from the directory tree %s.", terragruntOptions.WorkingDir)
	// zglob normalizes paths to "/"
	tgHclFiles, err := zglob.Glob(util.JoinPath(workingDir, "**", "*.hcl"))
	if err != nil {
		return err
	}

	filteredTgHclFiles := []string{}
	for _, fname := range tgHclFiles {
		// Ignore any files that are in the .terragrunt-cache
		if !util.ListContainsElement(strings.Split(fname, "/"), ".terragrunt-cache") {
			filteredTgHclFiles = append(filteredTgHclFiles, fname)
		} else {
			terragruntOptions.Logger.Debugf("%s was ignored due to being in the terragrunt cache", fname)
		}
	}

	terragruntOptions.Logger.Debugf("Found %d hcl files", len(filteredTgHclFiles))

	var formatErrors *multierror.Error
	for _, tgHclFile := range filteredTgHclFiles {
		err := formatTgHCL(terragruntOptions, tgHclFile)
		if err != nil {
			formatErrors = multierror.Append(formatErrors, err)
		}
	}

	return formatErrors.ErrorOrNil()
}

// formatTgHCL uses the hcl2 library to format the hcl file. This will attempt to parse the HCL file first to
// ensure that there are no syntax errors, before attempting to format it.
func formatTgHCL(terragruntOptions *options.TerragruntOptions, tgHclFile string) error {
	terragruntOptions.Logger.Debugf("Formatting %s", tgHclFile)

	info, err := os.Stat(tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error retrieving file info of %s", tgHclFile)
		return err
	}

	contentsStr, err := util.ReadFileAsString(tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error reading %s", tgHclFile)
		return err
	}
	contents := []byte(contentsStr)

	err = checkErrors(contents, tgHclFile)
	if err != nil {
		terragruntOptions.Logger.Errorf("Error parsing %s", tgHclFile)
		return err
	}

	newContents := hclwrite.Format(contents)

	fileUpdated := !bytes.Equal(newContents, contents)

	if terragruntOptions.Check && fileUpdated {
		return fmt.Errorf("Invalid file format %s", tgHclFile)
	}

	if fileUpdated {
		terragruntOptions.Logger.Infof("%s was updated", tgHclFile)
		return ioutil.WriteFile(tgHclFile, newContents, info.Mode())
	}

	return nil
}

// checkErrors takes in the contents of a hcl file and looks for syntax errors.
func checkErrors(contents []byte, tgHclFile string) error {
	parser := hclparse.NewParser()
	_, diags := parser.ParseHCL(contents, tgHclFile)
	diagWriter := util.GetDiagnosticsWriter(parser)
	diagWriter.WriteDiagnostics(diags)
	if diags.HasErrors() {
		return diags
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/core"
	"github.com/MG-RAST/AWE/lib/logger"
	"github.com/MG-RAST/AWE/lib/logger/event"
	"github.com/MG-RAST/AWE/lib/worker"
	"os"
	"strings"
)

func main() {

	// workstealer -> dataMover (download from Shock) -> processor -> deliverer (upload to Shock)

	if !conf.INIT_SUCCESS {
		conf.PrintClientUsage()
		os.Exit(1)
	}

	if _, err := os.Stat(conf.WORK_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.WORK_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating work_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if _, err := os.Stat(conf.DATA_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.DATA_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating data_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if _, err := os.Stat(conf.LOGS_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.LOGS_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating log_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if conf.PID_FILE_PATH != "" {
		f, err := os.Create(conf.PID_FILE_PATH)
		if err != nil {
			err_msg := "Could not create pid file: " + conf.PID_FILE_PATH + "\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		}
		defer f.Close()
		pid := os.Getpid()
		fmt.Fprintln(f, pid)
		fmt.Println("##### pidfile #####")
		fmt.Printf("pid: %d saved to file: %s\n\n", pid, conf.PID_FILE_PATH)
	}

	var logdir string
	if conf.CLIENT_NAME != "" {
		logdir = conf.CLIENT_NAME
	} else {
		logdir = "default"
	}

	logger.Initialize("client-" + logdir)

	profile, err := worker.ComposeProfile()
	if err != nil {
		fmt.Fprintf(os.Stderr, "fail to compose profile: %s\n", err.Error())
		os.Exit(1)
	}

	if conf.SERVER_URL == "" {
		fmt.Fprintf(os.Stderr, "AWE server url not configured or is empty. Please check the [Client]serverurl field in the configuration file.\n")
		os.Exit(1)
	}
	if strings.Contains(conf.SERVER_URL, "http") == false {
		fmt.Fprintf(os.Stderr, "serverurl not valid (require http://): %s \n", conf.SERVER_URL)
		os.Exit(1)
	}

	self, err := worker.RegisterWithAuth(conf.SERVER_URL, profile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "fail to register: %s\n", err.Error())
		os.Exit(1)
	}
	core.InitClientProfile(self)

	fmt.Printf("Client registered, name=%s, id=%s\n", self.Name, self.Id)
	logger.Event(event.CLIENT_REGISTRATION, "clientid="+self.Id)

	if err := worker.InitWorkers(self); err == nil {
		worker.StartClientWorkers()
	} else {
		fmt.Printf("failed to initialize and start workers:" + err.Error())
	}
}
<commit_msg>change client log location<commit_after>package main

import (
	"fmt"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/core"
	"github.com/MG-RAST/AWE/lib/logger"
	"github.com/MG-RAST/AWE/lib/logger/event"
	"github.com/MG-RAST/AWE/lib/worker"
	"os"
	"strings"
)

func main() {

	// workstealer -> dataMover (download from Shock) -> processor -> deliverer (upload to Shock)

	if !conf.INIT_SUCCESS {
		conf.PrintClientUsage()
		os.Exit(1)
	}

	if _, err := os.Stat(conf.WORK_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.WORK_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating work_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if _, err := os.Stat(conf.DATA_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.DATA_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating data_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if _, err := os.Stat(conf.LOGS_PATH); err != nil && os.IsNotExist(err) {
		if err := os.MkdirAll(conf.LOGS_PATH, 0777); err != nil {
			fmt.Fprintf(os.Stderr, "ERROR in creating log_path %s\n", err.Error())
			os.Exit(1)
		}
	}

	if conf.PID_FILE_PATH != "" {
		f, err := os.Create(conf.PID_FILE_PATH)
		if err != nil {
			err_msg := "Could not create pid file: " + conf.PID_FILE_PATH + "\n"
			fmt.Fprintf(os.Stderr, err_msg)
			logger.Error("ERROR: " + err_msg)
			os.Exit(1)
		}
		defer f.Close()
		pid := os.Getpid()
		fmt.Fprintln(f, pid)
		fmt.Println("##### pidfile #####")
		fmt.Printf("pid: %d saved to file: %s\n\n", pid, conf.PID_FILE_PATH)
	}

	logger.Initialize("client")

	profile, err := worker.ComposeProfile()
	if err != nil {
		fmt.Fprintf(os.Stderr, "fail to compose profile: %s\n", err.Error())
		os.Exit(1)
	}

	if conf.SERVER_URL == "" {
		fmt.Fprintf(os.Stderr, "AWE server url not configured or is empty. Please check the [Client]serverurl field in the configuration file.\n")
		os.Exit(1)
	}
	if strings.Contains(conf.SERVER_URL, "http") == false {
		fmt.Fprintf(os.Stderr, "serverurl not valid (require http://): %s \n", conf.SERVER_URL)
		os.Exit(1)
	}

	self, err := worker.RegisterWithAuth(conf.SERVER_URL, profile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "fail to register: %s\n", err.Error())
		os.Exit(1)
	}
	core.InitClientProfile(self)

	fmt.Printf("Client registered, name=%s, id=%s\n", self.Name, self.Id)
	logger.Event(event.CLIENT_REGISTRATION, "clientid="+self.Id)

	if err := worker.InitWorkers(self); err == nil {
		worker.StartClientWorkers()
	} else {
		fmt.Printf("failed to initialize and start workers:" + err.Error())
	}
}
<|endoftext|>


<commit_before>package stripe

import (
	"encoding/json"
)

// OrderStatus represents the statuses of an order object.
type OrderStatus string

const (
	StatusCreated   OrderStatus = "created"
	StatusPaid      OrderStatus = "paid"
	StatusCanceled  OrderStatus = "canceled"
	StatusFulfilled OrderStatus = "fulfilled"
	StatusReturned  OrderStatus = "returned"
)

type OrderParams struct {
	Params
	Currency Currency
	Customer string
	Email    string
	Items    []*OrderItemParams
	Shipping *ShippingParams
}

type ShippingParams struct {
	Name    string
	Address *AddressParams
	Phone   string
}

type OrderUpdateParams struct {
	Params
	Coupon                 string
	SelectedShippingMethod string
	Status                 OrderStatus
}

// OrderReturnParams is the set of parameters that can be used when returning
// orders. For more details, see: https://stripe.com/docs/api#return_order.
type OrderReturnParams struct {
	Params
	Items []*OrderItemParams
}

type Shipping struct {
	Name    string  `json:"name"`
	Address Address `json:"address"`
	Phone   string  `json:"phone"`
}

type ShippingMethod struct {
	ID               string            `json:"id"`
	Amount           int64             `json:"amount"`
	Currency         Currency          `json:"currency"`
	Description      string            `json:"description"`
	DeliveryEstimate *DeliveryEstimate `json:"delivery_estimate"`
}

type EstimateType string

const (
	Exact EstimateType = "exact"
	Range EstimateType = "range"
)

type DeliveryEstimate struct {
	Type EstimateType `json:"type"`
	// If Type == Range
	Earliest string `json:"earliest"`
	Latest   string `json:"latest"`
	// If Type == Exact
	Date string `json:"date"`
}

type Order struct {
	ID                     string            `json:"id"`
	Amount                 int64             `json:"amount"`
	Application            string            `json:"application"`
	ApplicationFee         int64             `json:"application_fee"`
	Charge                 Charge            `json:"charge"`
	Created                int64             `json:"created"`
	Currency               Currency          `json:"currency"`
	Customer               Customer          `json:"customer"`
	Email                  string            `json:"email"`
	Items                  []OrderItem       `json:"items"`
	Meta                   map[string]string `json:"metadata"`
	Returns                *OrderReturnList  `json:"returns"`
	SelectedShippingMethod *string           `json:"selected_shipping_method"`
	Shipping               Shipping          `json:"shipping"`
	ShippingMethods        []ShippingMethod  `json:"shipping_methods"`
	Status                 OrderStatus       `json:"status"`
	Updated                int64             `json:"updated"`
}

// OrderList is a list of orders as retrieved from a list endpoint.
type OrderList struct {
	ListMeta
	Values []*Order `json:"data"`
}

// OrderListParams is the set of parameters that can be used when
// listing orders. For more details, see:
// https://stripe.com/docs/api#list_orders.
type OrderListParams struct {
	ListParams
	IDs    []string
	Status OrderStatus
}

// OrderPayParams is the set of parameters that can be used when
// paying orders. For more details, see:
// https://stripe.com/docs/api#pay_order.
type OrderPayParams struct {
	Params
	Source         *SourceParams
	Customer       string
	ApplicationFee int64
	Email          string
}

// SetSource adds valid sources to a OrderParams object,
// returning an error for unsupported sources.
func (op *OrderPayParams) SetSource(sp interface{}) error {
	source, err := SourceParamsFor(sp)
	op.Source = source
	return err
}

// UnmarshalJSON handles deserialization of an Order.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (o *Order) UnmarshalJSON(data []byte) error {
	type order Order
	var oo order
	err := json.Unmarshal(data, &oo)
	if err == nil {
		*o = Order(oo)
		{
		}
	} else {
		// the id is surrounded by "\" characters, so strip them
		o.ID = string(data[1 : len(data)-1])
	}

	return nil
}
<commit_msg>add order status transitions field<commit_after>package stripe

import (
	"encoding/json"
)

// OrderStatus represents the statuses of an order object.
type OrderStatus string

const (
	StatusCreated   OrderStatus = "created"
	StatusPaid      OrderStatus = "paid"
	StatusCanceled  OrderStatus = "canceled"
	StatusFulfilled OrderStatus = "fulfilled"
	StatusReturned  OrderStatus = "returned"
)

type OrderParams struct {
	Params
	Currency Currency
	Customer string
	Email    string
	Items    []*OrderItemParams
	Shipping *ShippingParams
}

type ShippingParams struct {
	Name    string
	Address *AddressParams
	Phone   string
}

type OrderUpdateParams struct {
	Params
	Coupon                 string
	SelectedShippingMethod string
	Status                 OrderStatus
}

// OrderReturnParams is the set of parameters that can be used when returning
// orders. For more details, see: https://stripe.com/docs/api#return_order.
type OrderReturnParams struct {
	Params
	Items []*OrderItemParams
}

type Shipping struct {
	Name    string  `json:"name"`
	Address Address `json:"address"`
	Phone   string  `json:"phone"`
}

type ShippingMethod struct {
	ID               string            `json:"id"`
	Amount           int64             `json:"amount"`
	Currency         Currency          `json:"currency"`
	Description      string            `json:"description"`
	DeliveryEstimate *DeliveryEstimate `json:"delivery_estimate"`
}

type EstimateType string

const (
	Exact EstimateType = "exact"
	Range EstimateType = "range"
)

type DeliveryEstimate struct {
	Type EstimateType `json:"type"`
	// If Type == Range
	Earliest string `json:"earliest"`
	Latest   string `json:"latest"`
	// If Type == Exact
	Date string `json:"date"`
}

type Order struct {
	ID                     string            `json:"id"`
	Amount                 int64             `json:"amount"`
	Application            string            `json:"application"`
	ApplicationFee         int64             `json:"application_fee"`
	Charge                 Charge            `json:"charge"`
	Created                int64             `json:"created"`
	Currency               Currency          `json:"currency"`
	Customer               Customer          `json:"customer"`
	Email                  string            `json:"email"`
	Items                  []OrderItem       `json:"items"`
	Meta                   map[string]string `json:"metadata"`
	Returns                *OrderReturnList  `json:"returns"`
	SelectedShippingMethod *string           `json:"selected_shipping_method"`
	Shipping               Shipping          `json:"shipping"`
	ShippingMethods        []ShippingMethod  `json:"shipping_methods"`
	StatusTransitions      StatusTransitions `json:"status_transitions"`
	Status                 OrderStatus       `json:"status"`
	Updated                int64             `json:"updated"`
}

// OrderList is a list of orders as retrieved from a list endpoint.
type OrderList struct {
	ListMeta
	Values []*Order `json:"data"`
}

// OrderListParams is the set of parameters that can be used when
// listing orders. For more details, see:
// https://stripe.com/docs/api#list_orders.
type OrderListParams struct {
	ListParams
	IDs    []string
	Status OrderStatus
}

// StatsuTransitions are the timestamps at which the order status was updated
// https://stripe.com/docs/api#order_object
type StatusTransitions struct {
	Canceled  int64 `json:"canceled"`
	Fulfilled int64 `json:"fulfiled"`
	Paid      int64 `json:"paid"`
	Returned  int64 `json:"returned"`
}

// OrderPayParams is the set of parameters that can be used when
// paying orders. For more details, see:
// https://stripe.com/docs/api#pay_order.
type OrderPayParams struct {
	Params
	Source         *SourceParams
	Customer       string
	ApplicationFee int64
	Email          string
}

// SetSource adds valid sources to a OrderParams object,
// returning an error for unsupported sources.
func (op *OrderPayParams) SetSource(sp interface{}) error {
	source, err := SourceParamsFor(sp)
	op.Source = source
	return err
}

// UnmarshalJSON handles deserialization of an Order.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (o *Order) UnmarshalJSON(data []byte) error {
	type order Order
	var oo order
	err := json.Unmarshal(data, &oo)
	if err == nil {
		*o = Order(oo)
		{
		}
	} else {
		// the id is surrounded by "\" characters, so strip them
		o.ID = string(data[1 : len(data)-1])
	}

	return nil
}
<|endoftext|>


<commit_before>package lua

import (
	"io/ioutil"
	"os"
	"strings"
	"time"
)

var startedAt time.Time

func init() {
	startedAt = time.Now()
}

func getIntField(L *LState, tb *LTable, key string, v int) int {
	ret := tb.RawGetString(key)

	switch lv := ret.(type) {
	case LNumber:
		return int(lv)
	case LString:
		slv := string(lv)
		slv = strings.TrimLeft(slv, " ")
		if strings.HasPrefix(slv, "0") && !strings.HasPrefix(slv, "0x") && !strings.HasPrefix(slv, "0X") {
			//Standard lua interpreter only support decimal and hexadecimal
			slv = strings.TrimLeft(slv, "0")
		}
		if num, err := parseNumber(slv); err == nil {
			return int(num)
		}
	default:
		return v
	}

	return v
}

func getBoolField(L *LState, tb *LTable, key string, v bool) bool {
	ret := tb.RawGetString(key)
	if lb, ok := ret.(LBool); ok {
		return bool(lb)
	}
	return v
}

func OpenOs(L *LState) int {
	osmod := L.RegisterModule(OsLibName, osFuncs)
	L.Push(osmod)
	return 1
}

var osFuncs = map[string]LGFunction{
	"clock":     osClock,
	"difftime":  osDiffTime,
	"execute":   osExecute,
	"exit":      osExit,
	"date":      osDate,
	"getenv":    osGetEnv,
	"remove":    osRemove,
	"rename":    osRename,
	"setenv":    osSetEnv,
	"setlocale": osSetLocale,
	"time":      osTime,
	"tmpname":   osTmpname,
}

func osClock(L *LState) int {
	L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second)))
	return 1
}

func osDiffTime(L *LState) int {
	L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2)))
	return 1
}

func osExecute(L *LState) int {
	var procAttr os.ProcAttr
	procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
	cmd, args := popenArgs(L.CheckString(1))
	args = append([]string{cmd}, args...)
	process, err := os.StartProcess(cmd, args, &procAttr)
	if err != nil {
		L.Push(LNumber(1))
		return 1
	}

	ps, err := process.Wait()
	if err != nil || !ps.Success() {
		L.Push(LNumber(1))
		return 1
	}
	L.Push(LNumber(0))
	return 1
}

func osExit(L *LState) int {
	L.Close()
	os.Exit(L.OptInt(1, 0))
	return 1
}

func osDate(L *LState) int {
	t := time.Now()
	cfmt := "%c"
	if L.GetTop() >= 1 {
		cfmt = L.CheckString(1)
		if strings.HasPrefix(cfmt, "!") {
			t = time.Now().UTC()
			cfmt = strings.TrimLeft(cfmt, "!")
		}
		if L.GetTop() >= 2 {
			t = time.Unix(L.CheckInt64(2), 0)
		}
		if strings.HasPrefix(cfmt, "*t") {
			ret := L.NewTable()
			ret.RawSetString("year", LNumber(t.Year()))
			ret.RawSetString("month", LNumber(t.Month()))
			ret.RawSetString("day", LNumber(t.Day()))
			ret.RawSetString("hour", LNumber(t.Hour()))
			ret.RawSetString("min", LNumber(t.Minute()))
			ret.RawSetString("sec", LNumber(t.Second()))
			ret.RawSetString("wday", LNumber(t.Weekday()+1))
			// TODO yday & dst
			ret.RawSetString("yday", LNumber(0))
			ret.RawSetString("isdst", LFalse)
			L.Push(ret)
			return 1
		}
	}
	L.Push(LString(strftime(t, cfmt)))
	return 1
}

func osGetEnv(L *LState) int {
	v := os.Getenv(L.CheckString(1))
	if len(v) == 0 {
		L.Push(LNil)
	} else {
		L.Push(LString(v))
	}
	return 1
}

func osRemove(L *LState) int {
	err := os.Remove(L.CheckString(1))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osRename(L *LState) int {
	err := os.Rename(L.CheckString(1), L.CheckString(2))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osSetLocale(L *LState) int {
	// setlocale is not supported
	L.Push(LFalse)
	return 1
}

func osSetEnv(L *LState) int {
	err := os.Setenv(L.CheckString(1), L.CheckString(2))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osTime(L *LState) int {
	if L.GetTop() == 0 {
		L.Push(LNumber(time.Now().Unix()))
	} else {
		tbl := L.CheckTable(1)
		sec := getIntField(L, tbl, "sec", 0)
		min := getIntField(L, tbl, "min", 0)
		hour := getIntField(L, tbl, "hour", 12)
		day := getIntField(L, tbl, "day", -1)
		month := getIntField(L, tbl, "month", -1)
		year := getIntField(L, tbl, "year", -1)
		isdst := getBoolField(L, tbl, "isdst", false)
		t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local)
		// TODO dst
		if false {
			print(isdst)
		}
		L.Push(LNumber(t.Unix()))
	}
	return 1
}

func osTmpname(L *LState) int {
	file, err := ioutil.TempFile("", "")
	if err != nil {
		L.RaiseError("unable to generate a unique filename")
	}
	file.Close()
	os.Remove(file.Name()) // ignore errors
	L.Push(LString(file.Name()))
	return 1
}

//
<commit_msg>fix like "00" will be paused 12, and check nil val of os.time like os.time(nil)<commit_after>package lua

import (
	"io/ioutil"
	"os"
	"strings"
	"time"
)

var startedAt time.Time

func init() {
	startedAt = time.Now()
}

func getIntField(L *LState, tb *LTable, key string, v int) int {
	ret := tb.RawGetString(key)

	switch lv := ret.(type) {
	case LNumber:
		return int(lv)
	case LString:
		slv := string(lv)
		slv = strings.TrimLeft(slv, " ")
		if strings.HasPrefix(slv, "0") && !strings.HasPrefix(slv, "0x") && !strings.HasPrefix(slv, "0X") {
			//Standard lua interpreter only support decimal and hexadecimal
			slv = strings.TrimLeft(slv, "0")
			if slv == "" {
				return 0
			}
		}
		if num, err := parseNumber(slv); err == nil {
			return int(num)
		}
	default:
		return v
	}

	return v
}

func getBoolField(L *LState, tb *LTable, key string, v bool) bool {
	ret := tb.RawGetString(key)
	if lb, ok := ret.(LBool); ok {
		return bool(lb)
	}
	return v
}

func OpenOs(L *LState) int {
	osmod := L.RegisterModule(OsLibName, osFuncs)
	L.Push(osmod)
	return 1
}

var osFuncs = map[string]LGFunction{
	"clock":     osClock,
	"difftime":  osDiffTime,
	"execute":   osExecute,
	"exit":      osExit,
	"date":      osDate,
	"getenv":    osGetEnv,
	"remove":    osRemove,
	"rename":    osRename,
	"setenv":    osSetEnv,
	"setlocale": osSetLocale,
	"time":      osTime,
	"tmpname":   osTmpname,
}

func osClock(L *LState) int {
	L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second)))
	return 1
}

func osDiffTime(L *LState) int {
	L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2)))
	return 1
}

func osExecute(L *LState) int {
	var procAttr os.ProcAttr
	procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
	cmd, args := popenArgs(L.CheckString(1))
	args = append([]string{cmd}, args...)
	process, err := os.StartProcess(cmd, args, &procAttr)
	if err != nil {
		L.Push(LNumber(1))
		return 1
	}

	ps, err := process.Wait()
	if err != nil || !ps.Success() {
		L.Push(LNumber(1))
		return 1
	}
	L.Push(LNumber(0))
	return 1
}

func osExit(L *LState) int {
	L.Close()
	os.Exit(L.OptInt(1, 0))
	return 1
}

func osDate(L *LState) int {
	t := time.Now()
	cfmt := "%c"
	if L.GetTop() >= 1 {
		cfmt = L.CheckString(1)
		if strings.HasPrefix(cfmt, "!") {
			t = time.Now().UTC()
			cfmt = strings.TrimLeft(cfmt, "!")
		}
		if L.GetTop() >= 2 {
			t = time.Unix(L.CheckInt64(2), 0)
		}
		if strings.HasPrefix(cfmt, "*t") {
			ret := L.NewTable()
			ret.RawSetString("year", LNumber(t.Year()))
			ret.RawSetString("month", LNumber(t.Month()))
			ret.RawSetString("day", LNumber(t.Day()))
			ret.RawSetString("hour", LNumber(t.Hour()))
			ret.RawSetString("min", LNumber(t.Minute()))
			ret.RawSetString("sec", LNumber(t.Second()))
			ret.RawSetString("wday", LNumber(t.Weekday()+1))
			// TODO yday & dst
			ret.RawSetString("yday", LNumber(0))
			ret.RawSetString("isdst", LFalse)
			L.Push(ret)
			return 1
		}
	}
	L.Push(LString(strftime(t, cfmt)))
	return 1
}

func osGetEnv(L *LState) int {
	v := os.Getenv(L.CheckString(1))
	if len(v) == 0 {
		L.Push(LNil)
	} else {
		L.Push(LString(v))
	}
	return 1
}

func osRemove(L *LState) int {
	err := os.Remove(L.CheckString(1))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osRename(L *LState) int {
	err := os.Rename(L.CheckString(1), L.CheckString(2))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osSetLocale(L *LState) int {
	// setlocale is not supported
	L.Push(LFalse)
	return 1
}

func osSetEnv(L *LState) int {
	err := os.Setenv(L.CheckString(1), L.CheckString(2))
	if err != nil {
		L.Push(LNil)
		L.Push(LString(err.Error()))
		return 2
	} else {
		L.Push(LTrue)
		return 1
	}
}

func osTime(L *LState) int {
	if L.GetTop() == 0 {
		L.Push(LNumber(time.Now().Unix()))
	} else {
		lv := L.CheckAny(1)
		if lv == LNil {
			L.Push(LNumber(time.Now().Unix()))
		} else {
			tbl, ok := lv.(*LTable)
			if !ok {
				L.TypeError(1, LTTable)
			}
			sec := getIntField(L, tbl, "sec", 0)
			min := getIntField(L, tbl, "min", 0)
			hour := getIntField(L, tbl, "hour", 12)
			day := getIntField(L, tbl, "day", -1)
			month := getIntField(L, tbl, "month", -1)
			year := getIntField(L, tbl, "year", -1)
			isdst := getBoolField(L, tbl, "isdst", false)
			t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local)
			// TODO dst
			if false {
				print(isdst)
			}
			L.Push(LNumber(t.Unix()))
		}
	}
	return 1
}

func osTmpname(L *LState) int {
	file, err := ioutil.TempFile("", "")
	if err != nil {
		L.RaiseError("unable to generate a unique filename")
	}
	file.Close()
	os.Remove(file.Name()) // ignore errors
	L.Push(LString(file.Name()))
	return 1
}

//
<|endoftext|>


<commit_before>package fetch

import (
	"bytes"
	"errors"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"vip/store"
)

maxWidth, err := strconv.Atoi(os.Getenv("VIP_MAX_WIDTH"))
if err != nil {
	maxWidth = 720
}

func RequestContext(r *http.Request) *CacheContext {
	vars := mux.Vars(r)

	width, _ := strconv.Atoi(r.FormValue("s"))

	if width > maxWidth {
		width = maxWidth
	}

	return &CacheContext{
		ImageId: vars["image_id"],
		Bucket:  vars["bucket_id"],
		Width:   width,
		Crop:    strings.ToLower(r.FormValue("c")) == "true",
	}
}

func readImage(r io.Reader) ([]byte, error) {
	var b bytes.Buffer
	_, err := b.ReadFrom(r)

	return b.Bytes(), err
}

func ImageData(storage store.ImageStore, gc groupcache.Context) ([]byte, error) {
	c, ok := gc.(*CacheContext)
	if !ok {
		return nil, errors.New("invalid context")
	}

	var reader io.ReadCloser
	var err error

	defer func() {
		if reader != nil {
			reader.Close()
		}
	}()

	resp, err := storage.Head(c.Bucket, c.ImageId)
	if err != nil {
		// Don't break on an error
		log.Println(err)
	} else if resp.Header.Get("Content-Type") == "image/gif" {
		// Handle gifs exclusively
		reader, err = c.ReadOriginal(storage)
		if err != nil {
			return nil, err
		}

		return readImage(reader)
	}

	reader, err = c.ReadModified(storage)
	if err != nil {
		reader, err = c.ReadOriginal(storage)
		if err != nil {
			return nil, err
		}
	} else {
		log.Println("Retrieved resized image from S3")
		return readImage(reader)
	}

	var buf io.Reader
	if c.Width != 0 {
		buf, err = Resize(reader, c)
		if err != nil {
			return nil, err
		}
	}

	if c.Crop {
		buf, err = CenterCrop(buf, c)
		if err != nil {
			return nil, err
		}
	}

	result, err := readImage(buf)
	if err != nil {
		return nil, err
	}

	go func() {
		err = c.WriteModified(result, storage)
		if err != nil {
			log.Printf("s3 upload: %s", err.Error())
		}
	}()

	log.Println("Retrieved original and stored resized image in S3")
	return result, err
}
<commit_msg>Make sure maxWidth is calculated once<commit_after>package fetch

import (
	"bytes"
	"errors"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"vip/store"
)

var maxWidth = getMaxWidth()

func getMaxWidth() int {
	maxWidth, err := strconv.Atoi(os.Getenv("VIP_MAX_WIDTH"))
	if err != nil {
		return 720
	}

	return maxWidth
}

func RequestContext(r *http.Request) *CacheContext {
	vars := mux.Vars(r)

	width, _ := strconv.Atoi(r.FormValue("s"))

	if width > maxWidth {
		width = maxWidth
	}

	return &CacheContext{
		ImageId: vars["image_id"],
		Bucket:  vars["bucket_id"],
		Width:   width,
		Crop:    strings.ToLower(r.FormValue("c")) == "true",
	}
}

func readImage(r io.Reader) ([]byte, error) {
	var b bytes.Buffer
	_, err := b.ReadFrom(r)

	return b.Bytes(), err
}

func ImageData(storage store.ImageStore, gc groupcache.Context) ([]byte, error) {
	c, ok := gc.(*CacheContext)
	if !ok {
		return nil, errors.New("invalid context")
	}

	var reader io.ReadCloser
	var err error

	defer func() {
		if reader != nil {
			reader.Close()
		}
	}()

	resp, err := storage.Head(c.Bucket, c.ImageId)
	if err != nil {
		// Don't break on an error
		log.Println(err)
	} else if resp.Header.Get("Content-Type") == "image/gif" {
		// Handle gifs exclusively
		reader, err = c.ReadOriginal(storage)
		if err != nil {
			return nil, err
		}

		return readImage(reader)
	}

	reader, err = c.ReadModified(storage)
	if err != nil {
		reader, err = c.ReadOriginal(storage)
		if err != nil {
			return nil, err
		}
	} else {
		log.Println("Retrieved resized image from S3")
		return readImage(reader)
	}

	var buf io.Reader
	if c.Width != 0 {
		buf, err = Resize(reader, c)
		if err != nil {
			return nil, err
		}
	}

	if c.Crop {
		buf, err = CenterCrop(buf, c)
		if err != nil {
			return nil, err
		}
	}

	result, err := readImage(buf)
	if err != nil {
		return nil, err
	}

	go func() {
		err = c.WriteModified(result, storage)
		if err != nil {
			log.Printf("s3 upload: %s", err.Error())
		}
	}()

	log.Println("Retrieved original and stored resized image in S3")
	return result, err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/animenotifier/arn"
	"github.com/fatih/color"
)

type stats map[string]float64

func main() {
	color.Yellow("Generating statistics")

	userStats := getUserStats()
	animeStats := getAnimeStats()

	arn.PanicOnError(arn.DB.Set("Cache", "user statistics", &arn.StatisticsCategory{
		Name:      "Users",
		PieCharts: userStats,
	}))
	arn.PanicOnError(arn.DB.Set("Cache", "anime statistics", &arn.StatisticsCategory{
		Name:      "Anime",
		PieCharts: animeStats,
	}))

	color.Green("Finished.")
}

func getUserStats() []*arn.PieChart {
	println("Generating user statistics")

	analytics, err := arn.AllAnalytics()
	arn.PanicOnError(err)

	screenSize := stats{}
	pixelRatio := stats{}
	browser := stats{}
	country := stats{}
	gender := stats{}
	os := stats{}

	for _, info := range analytics {
		pixelRatio[fmt.Sprintf("%.1f", info.Screen.PixelRatio)]++

		size := arn.ToString(info.Screen.Width) + " x " + arn.ToString(info.Screen.Height)
		screenSize[size]++
	}

	for user := range arn.MustStreamUsers() {
		if user.Gender != "" {
			gender[user.Gender]++
		}

		if user.Browser.Name != "" {
			browser[user.Browser.Name]++
		}

		if user.Location.CountryName != "" {
			country[user.Location.CountryName]++
		}

		if user.OS.Name != "" {
			if strings.HasPrefix(user.OS.Name, "CrOS") {
				user.OS.Name = "Chrome OS"
			}

			os[user.OS.Name]++
		}
	}

	println("Finished user statistics")

	return []*arn.PieChart{
		arn.NewPieChart("OS", os),
		arn.NewPieChart("Screen size", screenSize),
		arn.NewPieChart("Browser", browser),
		arn.NewPieChart("Country", country),
		arn.NewPieChart("Gender", gender),
		arn.NewPieChart("Pixel ratio", pixelRatio),
	}
}

func getAnimeStats() []*arn.PieChart {
	println("Generating anime statistics")

	allAnime, err := arn.AllAnime()
	arn.PanicOnError(err)

	shoboi := stats{}
	anilist := stats{}
	status := stats{}
	types := stats{}
	shoboiEdits := stats{}
	anilistEdits := stats{}
	rating := stats{}

	for _, anime := range allAnime {
		for _, external := range anime.Mappings {
			if external.Service == "shoboi/anime" {
				if external.CreatedBy == "" {
					shoboiEdits["Bot"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					shoboiEdits[user.Nick]++
				}
			}

			if external.Service == "anilist/anime" {
				if external.CreatedBy == "" {
					anilistEdits["Bot"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					anilistEdits[user.Nick]++
				}
			}
		}

		if anime.GetMapping("shoboi/anime") != "" {
			shoboi["Connected with Shoboi"]++
		} else {
			shoboi["Not connected with Shoboi"]++
		}

		if anime.GetMapping("anilist/anime") != "" {
			anilist["Connected with Anilist"]++
		} else {
			anilist["Not connected with Anilist"]++
		}

		rating[arn.ToString(int(anime.Rating.Overall+0.5))]++

		status[anime.Status]++
		types[anime.Type]++
	}

	println("Finished anime statistics")

	return []*arn.PieChart{
		arn.NewPieChart("Type", types),
		arn.NewPieChart("Status", status),
		arn.NewPieChart("Rating", rating),
		arn.NewPieChart("Anilist", anilist),
		arn.NewPieChart("Shoboi", shoboi),
		arn.NewPieChart("Anilist Editors", anilistEdits),
		arn.NewPieChart("Shoboi Editors", shoboiEdits),
	}
}
<commit_msg>New statistics<commit_after>package main

import (
	"fmt"
	"strings"

	"github.com/animenotifier/arn"
	"github.com/fatih/color"
)

type stats map[string]float64

func main() {
	color.Yellow("Generating statistics")

	userStats := getUserStats()
	animeStats := getAnimeStats()

	arn.PanicOnError(arn.DB.Set("Cache", "user statistics", &arn.StatisticsCategory{
		Name:      "Users",
		PieCharts: userStats,
	}))
	arn.PanicOnError(arn.DB.Set("Cache", "anime statistics", &arn.StatisticsCategory{
		Name:      "Anime",
		PieCharts: animeStats,
	}))

	color.Green("Finished.")
}

func getUserStats() []*arn.PieChart {
	println("Generating user statistics")

	analytics, err := arn.AllAnalytics()
	arn.PanicOnError(err)

	screenSize := stats{}
	pixelRatio := stats{}
	browser := stats{}
	country := stats{}
	gender := stats{}
	os := stats{}

	for _, info := range analytics {
		pixelRatio[fmt.Sprintf("%.1f", info.Screen.PixelRatio)]++

		size := arn.ToString(info.Screen.Width) + " x " + arn.ToString(info.Screen.Height)
		screenSize[size]++
	}

	for user := range arn.MustStreamUsers() {
		if user.Gender != "" {
			gender[user.Gender]++
		}

		if user.Browser.Name != "" {
			browser[user.Browser.Name]++
		}

		if user.Location.CountryName != "" {
			country[user.Location.CountryName]++
		}

		if user.OS.Name != "" {
			if strings.HasPrefix(user.OS.Name, "CrOS") {
				user.OS.Name = "Chrome OS"
			}

			os[user.OS.Name]++
		}
	}

	println("Finished user statistics")

	return []*arn.PieChart{
		arn.NewPieChart("OS", os),
		arn.NewPieChart("Screen size", screenSize),
		arn.NewPieChart("Browser", browser),
		arn.NewPieChart("Country", country),
		arn.NewPieChart("Gender", gender),
		arn.NewPieChart("Pixel ratio", pixelRatio),
	}
}

func getAnimeStats() []*arn.PieChart {
	println("Generating anime statistics")

	allAnime, err := arn.AllAnime()
	arn.PanicOnError(err)

	shoboi := stats{}
	anilist := stats{}
	mal := stats{}
	anidb := stats{}
	status := stats{}
	types := stats{}
	shoboiEdits := stats{}
	anilistEdits := stats{}
	malEdits := stats{}
	anidbEdits := stats{}
	rating := stats{}

	for _, anime := range allAnime {
		for _, external := range anime.Mappings {
			if external.Service == "shoboi/anime" {
				if external.CreatedBy == "" {
					shoboiEdits["(auto-generated)"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					shoboiEdits[user.Nick]++
				}
			}

			if external.Service == "anilist/anime" {
				if external.CreatedBy == "" {
					anilistEdits["(auto-generated)"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					anilistEdits[user.Nick]++
				}
			}

			if external.Service == "myanimelist/anime" {
				if external.CreatedBy == "" {
					malEdits["(auto-generated)"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					malEdits[user.Nick]++
				}
			}

			if external.Service == "anidb/anime" {
				if external.CreatedBy == "" {
					anidbEdits["(auto-generated)"]++
				} else {
					user, err := arn.GetUser(external.CreatedBy)
					arn.PanicOnError(err)
					anidbEdits[user.Nick]++
				}
			}
		}

		if anime.GetMapping("shoboi/anime") != "" {
			shoboi["Connected with Shoboi"]++
		} else {
			shoboi["Not connected with Shoboi"]++
		}

		if anime.GetMapping("anilist/anime") != "" {
			anilist["Connected with AniList"]++
		} else {
			anilist["Not connected with AniList"]++
		}

		if anime.GetMapping("myanimelist/anime") != "" {
			mal["Connected with MyAnimeList"]++
		} else {
			mal["Not connected with MyAnimeList"]++
		}

		if anime.GetMapping("anidb/anime") != "" {
			anidb["Connected with AniDB"]++
		} else {
			anidb["Not connected with AniDB"]++
		}

		rating[arn.ToString(int(anime.Rating.Overall+0.5))]++

		status[anime.Status]++
		types[anime.Type]++
	}

	println("Finished anime statistics")

	return []*arn.PieChart{
		arn.NewPieChart("Type", types),
		arn.NewPieChart("Status", status),
		arn.NewPieChart("Rating", rating),
		arn.NewPieChart("MyAnimeList", mal),
		arn.NewPieChart("AniList", anilist),
		arn.NewPieChart("AniDB", anidb),
		arn.NewPieChart("Shoboi", shoboi),
		// arn.NewPieChart("MyAnimeList Editors", malEdits),
		arn.NewPieChart("AniList Editors", anilistEdits),
		// arn.NewPieChart("AniDB Editors", anidbEdits),
		arn.NewPieChart("Shoboi Editors", shoboiEdits),
	}
}
<|endoftext|>


<commit_before>package file

type Server struct {
	rw    *sync.Mutex
	stop  chan struct{}
	Files []*File
}

func (s *Server) Stop() {
	s.stop <- struct{}{}
	log.Println("Server stopping...")
	<-s.stop
	log.Println("Server stopped...")
}

func (s *Server) Start() {
	h := os.Getenv("HOST")
	if h == "" {
		h = HOST
	}
	p := os.Getenv("PORT_FILE")
	if p == "" {
		p = PORT
	}
	lis, err := net.Listen(TYPE, r+":"+p)
	if err != nil {
		log.Println("Error starting server...", err)
		return
	}

	var wg sync.WaitGroup
	sem := make(chan struct{}, 10)

	for {
		conn, err := lis.Accept()
		if err != nil {
			log.Println("Error accepting connection", err)
		}

		select {
		case <-s.stop:
			lis.Close()
			wg.Wait()
			s.stop <- struct{}{}
			return
		case sem <- struct{}{}:
			wg.Add(1)
			go s.ReceiveFile(conn, &wg, sem)
		}
	}
}

func (s *Server) ReceiveFile(conn net.Conn, wg *sync.WaitGroup, sem <-chan struct{}) {
	defer wg.Done()
	defer func() { <-sem }()

	bname := make([]byte, 64)
	bsize := make([]byte, 10)

	conn.Read(bname)
	conn.Read(bsize)

	size, err := strconv.ParseInt(strings.Trim(string(bsize), ":"), 10, 64)
	if err != nil {
		log.Println("Error parsing buffer size", err)
		return
	}
	name := strings.Trim(string(bname), ":")

	var file []byte
	var rbyt int64
	line := &File{
		Name: name,
		Size: size,
	}

	for rbyt = 0; size-rbyts > BUFFER_SIZE; rbyt = rbyt + BUFFER_SIZE {
		conn.Read(file)
	}
	conn.Read(file)
	s.AddFile(line)

}

func (s *Server) AddFile(f File) {
	defer s.rw.Unlock()
	s.rw.Lock()
	f.AddedOn = time.Now()
	s.Files = append(s.Files, &f)
}

type File struct {
	AddedOn time.Time
	Name    string
	Size    string
	Dests   []string
}
<commit_msg>file/server fixes imports<commit_after>package file

import (
	"log"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

type Server struct {
	rw    *sync.Mutex
	stop  chan struct{}
	Files []*File
}

func (s *Server) Stop() {
	s.stop <- struct{}{}
	log.Println("Server stopping...")
	<-s.stop
	log.Println("Server stopped...")
}

func (s *Server) Start() {
	h := os.Getenv("HOST")
	if h == "" {
		h = HOST
	}
	p := os.Getenv("PORT_FILE")
	if p == "" {
		p = PORT
	}
	lis, err := net.Listen(TYPE, r+":"+p)
	if err != nil {
		log.Println("Error starting server...", err)
		return
	}

	var wg sync.WaitGroup
	sem := make(chan struct{}, 10)

	for {
		conn, err := lis.Accept()
		if err != nil {
			log.Println("Error accepting connection", err)
		}

		select {
		case <-s.stop:
			lis.Close()
			wg.Wait()
			s.stop <- struct{}{}
			return
		case sem <- struct{}{}:
			wg.Add(1)
			go s.ReceiveFile(conn, &wg, sem)
		}
	}
}

func (s *Server) ReceiveFile(conn net.Conn, wg *sync.WaitGroup, sem <-chan struct{}) {
	defer wg.Done()
	defer func() { <-sem }()

	bname := make([]byte, 64)
	bsize := make([]byte, 10)

	conn.Read(bname)
	conn.Read(bsize)

	size, err := strconv.ParseInt(strings.Trim(string(bsize), ":"), 10, 64)
	if err != nil {
		log.Println("Error parsing buffer size", err)
		return
	}
	name := strings.Trim(string(bname), ":")

	var file []byte
	var rbyt int64
	line := &File{
		Name: name,
		Size: size,
	}

	for rbyt = 0; size-rbyts > BUFFER_SIZE; rbyt = rbyt + BUFFER_SIZE {
		conn.Read(file)
	}
	conn.Read(file)
	s.AddFile(line)

}

func (s *Server) AddFile(f File) {
	defer s.rw.Unlock()
	s.rw.Lock()
	f.AddedOn = time.Now()
	s.Files = append(s.Files, &f)
}

type File struct {
	AddedOn time.Time
	Name    string
	Size    string
	Dests   []string
}
<|endoftext|>


<commit_before>package gitbackend

import (
	"fmt"
	"github.com/libgit2/git2go"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"testing"
	"text/scanner"
	"time"
)

func TestNewFS(t *testing.T) {
	path := "tmp/bla/test"
	err := os.RemoveAll(path)
	checkFatal(t, err)
	fileStore, err := NewFileStore(path, true)
	checkFatal(t, err)
	fileInfo, err := os.Lstat(path)
	checkFatal(t, err)
	if !fileInfo.IsDir() {
		t.Fatalf("%s is not a directory.", path)
	}
	repo, err := git.OpenRepository(path)
	checkFatal(t, err)
	if !repo.IsBare() {
		t.Fatalf("%s is not a Bare Repository.", path)
	}

	paths, err := fileStore.ReadRoot()
	checkFatal(t, err)
	if len(paths) != 0 {
		t.Fatalf("paths should have length 0, but is %d", len(paths))
	}

	_, err = fileStore.ReadDir("foo")
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}
}

func TestReadRoot(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	paths, err := fileStore.ReadRoot()
	checkFatal(t, err)
	if len(paths) != 2 {
		t.Fatalf("paths should have length 2, but is %d\npaths contains: %v", len(paths), paths)
	}

	if paths[0].Name() != "bar" {
		t.Fatalf("First path should be bar, but is %s\npaths contains: %v", paths[0].Name(), paths)
	}
}

func TestReadDir(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	paths, err := fileStore.ReadDir("bar")
	checkFatal(t, err)
	if len(paths) != 1 {
		t.Fatalf("paths should have length 1, but is %d\npaths contains: %v", len(paths), paths)
	}

	if paths[0].Name() != "baz.txt" {
		t.Fatalf("First path should be foo.txt, but is %s\npaths contains: %v", paths[0].Name(), paths)
	}

	_, err = fileStore.ReadDir("foo")
	if err == nil {
		t.Fatalf("expected error, but nothing was returned\npaths contains: %v", paths)
	}
}

func TestReadFile(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	reader, err := fileStore.ReadFile("foo.txt")
	checkFatal(t, err)
	s := readAll(reader)
	if s != fmt.Sprintf("Hello World\n") {
		t.Fatalf("Expected: 'Hello World\n'\nactual: '%s'", s)
	}

	reader, err = fileStore.ReadFile("bar/baz.txt")
	checkFatal(t, err)
	s = readAll(reader)
	if s != fmt.Sprintf("This is Baz\n") {
		t.Fatalf("Expected: 'This is Baz\n'\nactual: '%s'", s)
	}

	reader, err = fileStore.ReadFile("boo.txt")
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}
}

func createTestRepo(t *testing.T) *git.Repository {
	// figure out where we can create the test repo
	path, err := ioutil.TempDir("", "test_repo")
	checkFatal(t, err)
	repo, err := git.InitRepository(path, false)
	checkFatal(t, err)

	return repo
}

func seedTestRepo(t *testing.T, repo *git.Repository) (*git.Oid, *git.Oid) {
	err := exec.Command("cp", "-rf", "tests/repo/", repo.Workdir()).Run()
	checkFatal(t, err)

	b, err := exec.Command("find", "tests/repo").Output()
	checkFatal(t, err)
	fmt.Println(string(b))
	b, err = exec.Command("find", repo.Workdir()).Output()
	checkFatal(t, err)
	fmt.Println(string(b))

	loc, err := time.LoadLocation("Europe/Berlin")
	checkFatal(t, err)
	sig := &git.Signature{
		Name:  "Rand Om Hacker",
		Email: "random@hacker.com",
		When:  time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
	}

	idx, err := repo.Index()
	checkFatal(t, err)
	filepath.Walk(repo.Workdir(), func(path string, info os.FileInfo, _ error) (err error) {
		if info.IsDir() {
			return
		}
		lenWorkdir := len(repo.Workdir())
		if path[lenWorkdir:lenWorkdir+4] == ".git" {
			return
		}
		err = idx.AddByPath(path[lenWorkdir:])
		checkFatal(t, err)
		return
	})
	treeId, err := idx.WriteTree()
	checkFatal(t, err)

	message := "This is a commit\n"
	tree, err := repo.LookupTree(treeId)
	checkFatal(t, err)
	commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
	checkFatal(t, err)

	return commitId, treeId
}

func checkFatal(t *testing.T, err error) {
	if err == nil {
		return
	}

	// The failure happens at wherever we were called, not here
	_, file, line, ok := runtime.Caller(1)
	if !ok {
		t.Fatal()
	}

	t.Fatalf("Fail at %v:%v; %v", file, line, err)
}

func readAll(reader io.Reader) (data string) {
	data = ""
	var s scanner.Scanner
	s.Init(reader)
	s.Whitespace = 1
	tok := s.Scan()
	for tok != scanner.EOF {
		data += s.TokenText()
		tok = s.Scan()
	}
	return
}
<commit_msg>[tests] use cp with /.<commit_after>package gitbackend

import (
	"fmt"
	"github.com/libgit2/git2go"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"testing"
	"text/scanner"
	"time"
)

func TestNewFS(t *testing.T) {
	path := "tmp/bla/test"
	err := os.RemoveAll(path)
	checkFatal(t, err)
	fileStore, err := NewFileStore(path, true)
	checkFatal(t, err)
	fileInfo, err := os.Lstat(path)
	checkFatal(t, err)
	if !fileInfo.IsDir() {
		t.Fatalf("%s is not a directory.", path)
	}
	repo, err := git.OpenRepository(path)
	checkFatal(t, err)
	if !repo.IsBare() {
		t.Fatalf("%s is not a Bare Repository.", path)
	}

	paths, err := fileStore.ReadRoot()
	checkFatal(t, err)
	if len(paths) != 0 {
		t.Fatalf("paths should have length 0, but is %d", len(paths))
	}

	_, err = fileStore.ReadDir("foo")
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}
}

func TestReadRoot(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	paths, err := fileStore.ReadRoot()
	checkFatal(t, err)
	if len(paths) != 2 {
		t.Fatalf("paths should have length 2, but is %d\npaths contains: %v", len(paths), paths)
	}

	if paths[0].Name() != "bar" {
		t.Fatalf("First path should be bar, but is %s\npaths contains: %v", paths[0].Name(), paths)
	}
}

func TestReadDir(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	paths, err := fileStore.ReadDir("bar")
	checkFatal(t, err)
	if len(paths) != 1 {
		t.Fatalf("paths should have length 1, but is %d\npaths contains: %v", len(paths), paths)
	}

	if paths[0].Name() != "baz.txt" {
		t.Fatalf("First path should be foo.txt, but is %s\npaths contains: %v", paths[0].Name(), paths)
	}

	_, err = fileStore.ReadDir("foo")
	if err == nil {
		t.Fatalf("expected error, but nothing was returned\npaths contains: %v", paths)
	}
}

func TestReadFile(t *testing.T) {
	repo := createTestRepo(t)
	seedTestRepo(t, repo)
	fileStore, err := NewFileStore(repo.Workdir(), false)
	checkFatal(t, err)

	reader, err := fileStore.ReadFile("foo.txt")
	checkFatal(t, err)
	s := readAll(reader)
	if s != fmt.Sprintf("Hello World\n") {
		t.Fatalf("Expected: 'Hello World\n'\nactual: '%s'", s)
	}

	reader, err = fileStore.ReadFile("bar/baz.txt")
	checkFatal(t, err)
	s = readAll(reader)
	if s != fmt.Sprintf("This is Baz\n") {
		t.Fatalf("Expected: 'This is Baz\n'\nactual: '%s'", s)
	}

	reader, err = fileStore.ReadFile("boo.txt")
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}
}

func createTestRepo(t *testing.T) *git.Repository {
	// figure out where we can create the test repo
	path, err := ioutil.TempDir("", "test_repo")
	checkFatal(t, err)
	repo, err := git.InitRepository(path, false)
	checkFatal(t, err)

	return repo
}

func seedTestRepo(t *testing.T, repo *git.Repository) (*git.Oid, *git.Oid) {
	err := exec.Command("cp", "-Rf", "tests/repo/.", repo.Workdir()).Run()
	checkFatal(t, err)

	b, err := exec.Command("find", "tests/repo").Output()
	checkFatal(t, err)
	fmt.Println(string(b))
	b, err = exec.Command("find", repo.Workdir()).Output()
	checkFatal(t, err)
	fmt.Println(string(b))

	loc, err := time.LoadLocation("Europe/Berlin")
	checkFatal(t, err)
	sig := &git.Signature{
		Name:  "Rand Om Hacker",
		Email: "random@hacker.com",
		When:  time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
	}

	idx, err := repo.Index()
	checkFatal(t, err)
	filepath.Walk(repo.Workdir(), func(path string, info os.FileInfo, _ error) (err error) {
		if info.IsDir() {
			return
		}
		lenWorkdir := len(repo.Workdir())
		if path[lenWorkdir:lenWorkdir+4] == ".git" {
			return
		}
		err = idx.AddByPath(path[lenWorkdir:])
		checkFatal(t, err)
		return
	})
	treeId, err := idx.WriteTree()
	checkFatal(t, err)

	message := "This is a commit\n"
	tree, err := repo.LookupTree(treeId)
	checkFatal(t, err)
	commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
	checkFatal(t, err)

	return commitId, treeId
}

func checkFatal(t *testing.T, err error) {
	if err == nil {
		return
	}

	// The failure happens at wherever we were called, not here
	_, file, line, ok := runtime.Caller(1)
	if !ok {
		t.Fatal()
	}

	t.Fatalf("Fail at %v:%v; %v", file, line, err)
}

func readAll(reader io.Reader) (data string) {
	data = ""
	var s scanner.Scanner
	s.Init(reader)
	s.Whitespace = 1
	tok := s.Scan()
	for tok != scanner.EOF {
		data += s.TokenText()
		tok = s.Scan()
	}
	return
}
<|endoftext|>


<commit_before>package files

import (
	"io"
	"time"

	"honnef.co/go/js/dom"

	"github.com/gopherjs/gopherjs/js"
)

type Blob struct {
	b *js.Object
}

func NewBlob(b *js.Object) Blob {
	return Blob{b}
}

func (b Blob) Size() int {
	return b.b.Get("size").Int()
}

func (b Blob) Type() string {
	return b.b.Get("type").String()
}

func (b Blob) Slice(i, j int) Blob {
	return NewBlob(b.b.Call("slice", i, j))
}

type File struct {
	Blob
}

func NewFile(f *dom.File) File {
	return File{NewBlob(f.Object)}
}

func (f File) LastModifiedDate() time.Time {
	return f.b.Get("lastModifiedDate").Interface().(time.Time)
}

func (f File) Name() string {
	return f.b.Get("name").String()
}

type FileReader struct {
	f            File
	fr           *js.Object
	offset, size int
}

func NewFileReader(f File) *FileReader {
	return &FileReader{
		f,
		js.Global.Get("FileReader").New(),
		0,
		f.Size(),
	}
}

func (fr *FileReader) Read(p []byte) (int, error) {
	if fr.offset == fr.size {
		return 0, io.EOF
	}
	type result struct {
		size int
		err  error
	}
	c := make(chan result)
	fr.fr.Set("onloadend", func(*js.Object) {
		arr := js.Global.Get("Uint8Array").New(fr.fr.Get("result"))
		buf := arr.Interface().([]byte)
		go func() {
			if len(buf) == 0 {
				c <- result{0, io.EOF}
			} else {
				copy(p, buf)
				c <- result{len(buf), nil}
			}
		}()
	})
	e := fr.offset + len(p)
	if e > fr.size {
		e = fr.size
	}
	blob := fr.f.b.Call("slice", fr.offset, e)
	fr.fr.Call("readAsArrayBuffer", blob)
	res := <-c
	fr.offset = e
	return res.size, res.err
}
<commit_msg>Added Seek, Close and ReadAt methods<commit_after>package files

import (
	"errors"
	"io"
	"time"

	"honnef.co/go/js/dom"

	"github.com/gopherjs/gopherjs/js"
)

type Blob struct {
	b *js.Object
}

func NewBlob(b *js.Object) Blob {
	return Blob{b}
}

func (b Blob) Size() int {
	return b.b.Get("size").Int()
}

func (b Blob) Type() string {
	return b.b.Get("type").String()
}

func (b Blob) Slice(i, j int) Blob {
	return NewBlob(b.b.Call("slice", i, j))
}

type File struct {
	Blob
}

func NewFile(f *dom.File) File {
	return File{NewBlob(f.Object)}
}

func (f File) LastModifiedDate() time.Time {
	return f.b.Get("lastModifiedDate").Interface().(time.Time)
}

func (f File) Name() string {
	return f.b.Get("name").String()
}

type FileReader struct {
	f            File
	fr           *js.Object
	offset, size int64
}

func NewFileReader(f File) *FileReader {
	return &FileReader{
		f,
		js.Global.Get("FileReader").New(),
		0,
		int64(f.Size()),
	}
}

func (fr *FileReader) Close() error {
	fr.fr = nil
	return nil
}

func (fr *FileReader) Read(b []byte) (int, error) {
	n, err := fr.ReadAt(b, int64(fr.offset))
	fr.offset += int64(n)
	return n, err
}

func (fr *FileReader) ReadAt(b []byte, off int64) (int, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	if off >= fr.size {
		return 0, io.EOF
	}

	type readResult struct {
		size int
		err  error
	}

	c := make(chan readResult)
	fr.fr.Set("onloadend", func(*js.Object) {
		arr := js.Global.Get("Uint8Array").New(fr.fr.Get("result"))
		buf := arr.Interface().([]byte)
		go func() {
			if len(buf) == 0 {
				c <- readResult{0, io.EOF}
			} else {
				copy(b, buf)
				c <- readResult{len(buf), nil}
			}
		}()
	})
	e := off + int64(len(b))
	if e > fr.size {
		e = fr.size
	}
	blob := fr.f.b.Call("slice", fr.offset, e)
	fr.fr.Call("readAsArrayBuffer", blob)
	r := <-c
	return r.size, r.err
}

func (fr *FileReader) Seek(offset int64, whence int) (int64, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	switch whence {
	case 0:
		fr.offset = offset
	case 1:
		fr.offset += offset
	case 2:
		fr.offset = fr.size + offset
	}
	if fr.offset < 0 {
		fr.offset = 0
	}
	return fr.offset, nil
}

// Errors
var (
	ErrClosed = errors.New("file closed")
)
<|endoftext|>


<commit_before>package garvis

import (
	"regexp"
	"strings"

	"golang.org/x/net/context"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type CapsFilter struct {
	bot  *tgbotapi.BotAPI
	ctx  context.Context
	done chan bool
}

func (filter CapsFilter) Run(update tgbotapi.Update) error {
	m := update.Message.Text

	if checkCapsFilter(m) {
		filter.Trigger(update)
	}

	filter.done <- true
	return nil
}

func (filter CapsFilter) GetCommands(map[string]Filter) {

}

func (filter CapsFilter) RunCommand(string, CommandArguments) {

}

func (filter CapsFilter) Trigger(update tgbotapi.Update) {
	msg := tgbotapi.NewMessage(update.Message.Chat.ID, "SHUT THE FUCK UP MATE")
	filter.bot.Send(msg)
}

func checkCapsFilter(m string) bool {
	var emojiRx = regexp.MustCompile(`[\x{1F600}-\x{1F6FF}|[\x{2600}-\x{26FF}]`)
	m = emojiRx.ReplaceAllString(m, ``)
	var symbolRx = regexp.MustCompile(`[^\pL\s]`)
	m = symbolRx.ReplaceAllString(m, ``)
	if m == strings.ToUpper(m) && len(m) > 5 {
		return true
	}

	return false
}
<commit_msg>Refine caps filter to exclude laughing<commit_after>package garvis

import (
	"regexp"
	"strings"

	"golang.org/x/net/context"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type CapsFilter struct {
	bot  *tgbotapi.BotAPI
	ctx  context.Context
	done chan bool
}

func (filter CapsFilter) Run(update tgbotapi.Update) error {
	m := update.Message.Text

	if checkCapsFilter(m) {
		filter.Trigger(update)
	}

	filter.done <- true
	return nil
}

func (filter CapsFilter) GetCommands(map[string]Filter) {

}

func (filter CapsFilter) RunCommand(string, CommandArguments) {

}

func (filter CapsFilter) Trigger(update tgbotapi.Update) {
	msg := tgbotapi.NewMessage(update.Message.Chat.ID, "SHUT THE FUCK UP MATE")
	filter.bot.Send(msg)
}

func checkCapsFilter(m string) bool {
	// Strip emojis and symbols
	emojiRx := regexp.MustCompile(`[\x{1F600}-\x{1F6FF}|[\x{2600}-\x{26FF}]|[^\pL\s]`)
	m = emojiRx.ReplaceAllString(m, ``)

	// Exclude laughing
	laughingRx := regexp.MustCompile(`((H|X)A)+`)
	m = laughingRx.ReplaceAllString(m, ``)

	if m == strings.ToUpper(m) && len(m) > 5 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"net/textproto"
	"os"

	"golang.org/x/crypto/openpgp"
	"golang.org/x/crypto/openpgp/armor"
)

// PGPTransformer provides support for converting arbitrary plain messages to PGP/MIME
// messages in a way which allows for bit-perfect reversal of the operation.
type PGPTransformer struct {
	pgpBuffer     *bytes.Buffer
	outBuffer     *bytes.Buffer
	plainBuffer   *bytes.Buffer
	pgpWriter     io.WriteCloser
	asciiWriter   io.WriteCloser
	encryptionKey *openpgp.Entity
	signingKey    *openpgp.Entity
	keepHeaders   []string
}

// NewPGPTransformer returns a new PGPTransformer instance.
func NewPGPTransformer(keepHeaders []string) *PGPTransformer {
	return &PGPTransformer{keepHeaders: keepHeaders}
}

// LoadEncryptionKey loads the keyring from the given path and tries to set up the
// first and only public key found there as the encryption target.
func (w *PGPTransformer) LoadEncryptionKey(path string) error {
	logger.Debugf("loading encryption key from %s", path)
	var err error
	w.encryptionKey, err = w.loadKey(path)
	return err
}

// LoadSigningKey loads the keyring from the given path and tries to so set up
// the first and only private key found there as the signing key, optionally
// decrypting it with the given passphrase first.
func (w *PGPTransformer) LoadSigningKey(path, passphrase string) error {
	logger.Debugf("loading signing key from %s", path)
	var err error
	w.signingKey, err = w.loadKey(path)
	if err != nil {
		return err
	}
	priv := w.signingKey.PrivateKey
	if priv == nil {
		return errors.New("signing key lacks private key")
	}
	if priv.Encrypted {
		err := priv.Decrypt([]byte(passphrase))
		if err != nil {
			return fmt.Errorf("failed to decrypt private key: %s", err)
		}
	}
	return nil
}

// loadKey is the internal method which contains the common key loading and
// parsing functionality.
func (w *PGPTransformer) loadKey(path string) (*openpgp.Entity, error) {
	keyringReader, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer keyringReader.Close()
	keyring, err := openpgp.ReadArmoredKeyRing(keyringReader)
	if err != nil {
		return nil, err
	}
	if len(keyring) != 1 {
		logger.Errorf("encryption key ring contains %d keys; expected 1", len(keyring))
		return nil, errors.New("encryption key ring must contain exactly one key")
	}
	return keyring[0], nil
}

// Reset configures the PGPTransformer to be ready for the first or next message
// transformation.
// Call this method before initially passing the transformer data or before passing
// it any new data after finishing handling of the previous item.
func (w *PGPTransformer) Reset() error {
	w.pgpBuffer = &bytes.Buffer{}
	w.plainBuffer = &bytes.Buffer{}
	var err error
	w.asciiWriter, err = armor.Encode(w.pgpBuffer, "PGP MESSAGE", nil)
	if err != nil {
		return err
	}
	if w.encryptionKey == nil {
		return errors.New("missing encryption key")
	}
	w.pgpWriter, err = openpgp.Encrypt(w.asciiWriter,
		[]*openpgp.Entity{w.encryptionKey}, w.signingKey,
		&openpgp.FileHints{IsBinary: true}, nil)
	return err
}

// Write passes the given data to the underlying PGP encryptor.
func (w *PGPTransformer) Write(data []byte) (int, error) {
	_, err := w.plainBuffer.Write(data)
	if err != nil {
		return 0, err
	}
	return w.pgpWriter.Write(data)
}

// GetBytes returns the encrypted message as a byte array.
func (w *PGPTransformer) GetBytes() ([]byte, error) {
	w.finalizePGP()
	err := w.finalizeMIME()
	if err != nil {
		return nil, err
	}
	return w.outBuffer.Bytes(), nil
}

// finalizePGP ends the PGP encryption process and ascii-encoding process.
func (w *PGPTransformer) finalizePGP() {
	w.pgpWriter.Close()
	w.asciiWriter.Close()
}

// finalizeMIME finally encodes the PGP ascii-armored data in a MIME message.
func (w *PGPTransformer) finalizeMIME() error {
	w.outBuffer = &bytes.Buffer{}
	err := w.writePlainHeaders()
	if err != nil {
		return err
	}
	return w.writeMIMEStructure()
}

// writePlainHeaders generates Message-Id and copies all the plain headers which are
// configured to be copied up from the original message to the output buffer.
func (w *PGPTransformer) writePlainHeaders() error {
	plainReader := bufio.NewReader(w.plainBuffer)
	mimeReader := textproto.NewReader(plainReader)
	headers, err := mimeReader.ReadMIMEHeader()
	if err != nil {
		return err
	}
	msgid := headers.Get("Message-Id")
	if msgid != "" {
		prefix := "lemoncrypt."
		if len(msgid) > 1 && msgid[0] == '<' {
			msgid = msgid[0:1] + prefix + msgid[1:]
		} else {
			msgid += prefix + msgid[1:]
		}
	}
	w.outBuffer.WriteString("Message-Id: " + msgid + "\n")
	for _, key := range w.keepHeaders {
		val := headers.Get(key)
		if val == "" {
			// don't attempt to copy empty headers
			continue
		}
		//FIXME proper line wrapping; not obvious how go does it
		w.outBuffer.WriteString(key + ": " + val + "\n")
	}
	return nil
}

// writeMIMEStructure writes the basic MIME structure and the encrypted content
// to the output buffer.
func (w *PGPTransformer) writeMIMEStructure() error {
	boundary, err := generateBoundary()
	if err != nil {
		return err
	}
	w.outBuffer.WriteString(
		"MIME-Version: 1.0\n" +
			"Content-Type: multipart/encrypted;\n" +
			" protocol=\"application/pgp-encrypted\";\n" +
			" boundary=\"" + boundary + "\"\n\n" +
			"OpenPGP/MIME\n" +
			"--" + boundary + "\n" +
			"Content-Type: application/pgp-encrypted\n\n" +
			"Version: 1\n\n" +
			"--" + boundary + "\n" +
			"Content-Type: application/octet-stream; name=\"encrypted.asc\"\n" +
			"Content-Disposition: inline; filename=\"encrypted.asc\"\n\n" +
			string(w.pgpBuffer.Bytes()) + "\n--" + boundary + "--")
	return nil
}

// generateBoundary creates a random boundary string suitable for
// MIME part separation.
func generateBoundary() (string, error) {
	tmp := make([]byte, 30)
	_, err := io.ReadFull(rand.Reader, tmp)
	if err != nil {
		return "", err
	}
	boundary := fmt.Sprintf("%x", tmp)
	return boundary, nil
}
<commit_msg>pgp: properly catch errors in finalization<commit_after>package main

import (
	"bufio"
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"net/textproto"
	"os"

	"golang.org/x/crypto/openpgp"
	"golang.org/x/crypto/openpgp/armor"
)

// PGPTransformer provides support for converting arbitrary plain messages to PGP/MIME
// messages in a way which allows for bit-perfect reversal of the operation.
type PGPTransformer struct {
	pgpBuffer     *bytes.Buffer
	outBuffer     *bytes.Buffer
	plainBuffer   *bytes.Buffer
	pgpWriter     io.WriteCloser
	asciiWriter   io.WriteCloser
	encryptionKey *openpgp.Entity
	signingKey    *openpgp.Entity
	keepHeaders   []string
}

// NewPGPTransformer returns a new PGPTransformer instance.
func NewPGPTransformer(keepHeaders []string) *PGPTransformer {
	return &PGPTransformer{keepHeaders: keepHeaders}
}

// LoadEncryptionKey loads the keyring from the given path and tries to set up the
// first and only public key found there as the encryption target.
func (w *PGPTransformer) LoadEncryptionKey(path string) error {
	logger.Debugf("loading encryption key from %s", path)
	var err error
	w.encryptionKey, err = w.loadKey(path)
	return err
}

// LoadSigningKey loads the keyring from the given path and tries to so set up
// the first and only private key found there as the signing key, optionally
// decrypting it with the given passphrase first.
func (w *PGPTransformer) LoadSigningKey(path, passphrase string) error {
	logger.Debugf("loading signing key from %s", path)
	var err error
	w.signingKey, err = w.loadKey(path)
	if err != nil {
		return err
	}
	priv := w.signingKey.PrivateKey
	if priv == nil {
		return errors.New("signing key lacks private key")
	}
	if priv.Encrypted {
		err := priv.Decrypt([]byte(passphrase))
		if err != nil {
			return fmt.Errorf("failed to decrypt private key: %s", err)
		}
	}
	return nil
}

// loadKey is the internal method which contains the common key loading and
// parsing functionality.
func (w *PGPTransformer) loadKey(path string) (*openpgp.Entity, error) {
	keyringReader, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer keyringReader.Close()
	keyring, err := openpgp.ReadArmoredKeyRing(keyringReader)
	if err != nil {
		return nil, err
	}
	if len(keyring) != 1 {
		logger.Errorf("encryption key ring contains %d keys; expected 1", len(keyring))
		return nil, errors.New("encryption key ring must contain exactly one key")
	}
	return keyring[0], nil
}

// Reset configures the PGPTransformer to be ready for the first or next message
// transformation.
// Call this method before initially passing the transformer data or before passing
// it any new data after finishing handling of the previous item.
func (w *PGPTransformer) Reset() error {
	w.pgpBuffer = &bytes.Buffer{}
	w.plainBuffer = &bytes.Buffer{}
	var err error
	w.asciiWriter, err = armor.Encode(w.pgpBuffer, "PGP MESSAGE", nil)
	if err != nil {
		return err
	}
	if w.encryptionKey == nil {
		return errors.New("missing encryption key")
	}
	w.pgpWriter, err = openpgp.Encrypt(w.asciiWriter,
		[]*openpgp.Entity{w.encryptionKey}, w.signingKey,
		&openpgp.FileHints{IsBinary: true}, nil)
	return err
}

// Write passes the given data to the underlying PGP encryptor.
func (w *PGPTransformer) Write(data []byte) (int, error) {
	_, err := w.plainBuffer.Write(data)
	if err != nil {
		return 0, err
	}
	return w.pgpWriter.Write(data)
}

// GetBytes returns the encrypted message as a byte array.
func (w *PGPTransformer) GetBytes() ([]byte, error) {
	err := w.finalizePGP()
	if err != nil {
		return nil, err
	}
	err = w.finalizeMIME()
	if err != nil {
		return nil, err
	}
	return w.outBuffer.Bytes(), nil
}

// finalizePGP ends the PGP encryption process and ascii-encoding process.
func (w *PGPTransformer) finalizePGP() error {
	err := w.pgpWriter.Close()
	if err != nil {
		return err
	}
	return w.asciiWriter.Close()
}

// finalizeMIME finally encodes the PGP ascii-armored data in a MIME message.
func (w *PGPTransformer) finalizeMIME() error {
	w.outBuffer = &bytes.Buffer{}
	err := w.writePlainHeaders()
	if err != nil {
		return err
	}
	return w.writeMIMEStructure()
}

// writePlainHeaders generates Message-Id and copies all the plain headers which are
// configured to be copied up from the original message to the output buffer.
func (w *PGPTransformer) writePlainHeaders() error {
	plainReader := bufio.NewReader(w.plainBuffer)
	mimeReader := textproto.NewReader(plainReader)
	headers, err := mimeReader.ReadMIMEHeader()
	if err != nil {
		return err
	}
	msgid := headers.Get("Message-Id")
	if msgid != "" {
		prefix := "lemoncrypt."
		if len(msgid) > 1 && msgid[0] == '<' {
			msgid = msgid[0:1] + prefix + msgid[1:]
		} else {
			msgid += prefix + msgid[1:]
		}
	}
	w.outBuffer.WriteString("Message-Id: " + msgid + "\n")
	for _, key := range w.keepHeaders {
		val := headers.Get(key)
		if val == "" {
			// don't attempt to copy empty headers
			continue
		}
		//FIXME proper line wrapping; not obvious how go does it
		w.outBuffer.WriteString(key + ": " + val + "\n")
	}
	return nil
}

// writeMIMEStructure writes the basic MIME structure and the encrypted content
// to the output buffer.
func (w *PGPTransformer) writeMIMEStructure() error {
	boundary, err := generateBoundary()
	if err != nil {
		return err
	}
	w.outBuffer.WriteString(
		"MIME-Version: 1.0\n" +
			"Content-Type: multipart/encrypted;\n" +
			" protocol=\"application/pgp-encrypted\";\n" +
			" boundary=\"" + boundary + "\"\n\n" +
			"OpenPGP/MIME\n" +
			"--" + boundary + "\n" +
			"Content-Type: application/pgp-encrypted\n\n" +
			"Version: 1\n\n" +
			"--" + boundary + "\n" +
			"Content-Type: application/octet-stream; name=\"encrypted.asc\"\n" +
			"Content-Disposition: inline; filename=\"encrypted.asc\"\n\n" +
			string(w.pgpBuffer.Bytes()) + "\n--" + boundary + "--")
	return nil
}

// generateBoundary creates a random boundary string suitable for
// MIME part separation.
func generateBoundary() (string, error) {
	tmp := make([]byte, 30)
	_, err := io.ReadFull(rand.Reader, tmp)
	if err != nil {
		return "", err
	}
	boundary := fmt.Sprintf("%x", tmp)
	return boundary, nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/valve"
)

func main() {

	// Our graceful valve shut-off package to manage code preemption and
	// shutdown signaling.
	valv := valve.New()
	baseCtx := valv.Context()

	// Example of a long running background worker thing..
	go func(ctx context.Context) {
		for {
			<-time.After(1 * time.Second)

			func() {
				valve.Lever(ctx).Open()
				defer valve.Lever(ctx).Close()

				// actual code doing stuff..
				fmt.Println("tick..")
				time.Sleep(2 * time.Second)
				// end-logic

				// signal control..
				select {
				case <-valve.Lever(ctx).Stop():
					fmt.Println("valve is closed")
					return

				case <-ctx.Done():
					fmt.Println("context is cancelled, go home.")
					return
				default:
				}
			}()

		}
	}(baseCtx)

	// HTTP service running in this program as well. The valve context is set
	// as a base context on the server listener at the point where we instantiate
	// the server - look lower.
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	r.Use(middleware.Logger)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("sup"))
	})

	r.Get("/slow", func(w http.ResponseWriter, r *http.Request) {

		valve.Lever(r.Context()).Open()
		defer valve.Lever(r.Context()).Close()

		select {
		case <-valve.Lever(r.Context()).Stop():
			fmt.Println("valve is closed. finish up..")

		case <-time.After(5 * time.Second):
			// The above channel simulates some hard work.
			// We want this handler to complete successfully during a shutdown signal,
			// so consider the work here as some background routine to fetch a long running
			// search query to find as many results as possible, but, instead we cut it short
			// and respond with what we have so far. How a shutdown is handled is entirely
			// up to the developer, as some code blocks are preemptable, and others are not.
			time.Sleep(5 * time.Second)
		}

		w.Write([]byte(fmt.Sprintf("all done.\n")))
	})

	srv := http.Server{Addr: ":3333", Handler: r}
	srv.BaseContext = func(_ net.Listener) context.Context {
		return baseCtx
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c {
			// sig is a ^C, handle it
			fmt.Println("shutting down..")

			// first valv
			valv.Shutdown(20 * time.Second)

			// create context with timeout
			ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
			defer cancel()

			// start http shutdown
			srv.Shutdown(ctx)

			// verify, in worst case call cancel via defer
			select {
			case <-time.After(21 * time.Second):
				fmt.Println("not all connections done")
			case <-ctx.Done():

			}
		}
	}()
	srv.ListenAndServe()
}
<commit_msg>_examples: new graceful example, better<commit_after>package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

func main() {
	// The HTTP Server
	server := &http.Server{Addr: "0.0.0.0:3333", Handler: service()}

	// Server run context
	serverCtx, serverStopCtx := context.WithCancel(context.Background())

	// Listen for syscall signals for process to interrupt/quit
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	go func() {
		<-sig

		// Shutdown signal with grace period of 30 seconds
		shutdownCtx, _ := context.WithTimeout(serverCtx, 30*time.Second)

		go func() {
			<-shutdownCtx.Done()
			if shutdownCtx.Err() == context.DeadlineExceeded {
				log.Fatal("graceful shutdown timed out.. forcing exit.")
			}
		}()

		// Trigger graceful shutdown
		err := server.Shutdown(shutdownCtx)
		if err != nil {
			log.Fatal(err)
		}
		serverStopCtx()
	}()

	// Run the server
	err := server.ListenAndServe()
	if err != nil && err != http.ErrServerClosed {
		log.Fatal(err)
	}

	// Wait for server context to be stopped
	<-serverCtx.Done()
}

func service() http.Handler {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.Logger)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("sup"))
	})

	r.Get("/slow", func(w http.ResponseWriter, r *http.Request) {
		// Simulates some hard work.
		//
		// We want this handler to complete successfully during a shutdown signal,
		// so consider the work here as some background routine to fetch a long running
		// search query to find as many results as possible, but, instead we cut it short
		// and respond with what we have so far. How a shutdown is handled is entirely
		// up to the developer, as some code blocks are preemptable, and others are not.
		time.Sleep(5 * time.Second)

		w.Write([]byte(fmt.Sprintf("all done.\n")))
	})

	return r
}
<|endoftext|>


<commit_before>/*
TODO
*/
package client
<commit_msg>Added initial doc.go, and mentioned that KalaClient is thread-safe.<commit_after>/*

KalaClient in the official Go client library for interfacing with the Kala HTTP API.

It is a simple wrapper around the Sling library, and it is thread-safe.

*/
package client
<|endoftext|>


<commit_before>package main

import (
	"github.com/cwchiu/go-winapi"
	"os"
	"sync"
	"unsafe"
	"syscall"
	"errors"
)

const (
	WINDOW_CLASS = "dacko"
)

const (
	MOD_ALT = 1
	MOD_CONTROL = 2
	MOD_SHIFT = 4
	MOD_WIN = 8
)

const (
	SYNCHRONIZE = 0x00100000
)

const (
	CREATE_NEW_CONSOLE = 0x00000010
)

const (
	WAIT_OBJECT_0 = 0x00000000
	WAIT_ABANDONED = 0x00000080
	WAIT_timeout = 0x00000102
	WAIT_FAILED = 0xFFFFFFFF
)

var (
	user32, _         = syscall.LoadLibrary("user32.dll")
	registerHotkey, _ = syscall.GetProcAddress(user32, "RegisterHotKey")
	getWindowThreadProcessId, _ = syscall.GetProcAddress(user32, "GetWindowThreadProcessId")
	enumWindows, _ = syscall.GetProcAddress(user32, "EnumWindows")
	procReplyMessage = syscall.NewLazyDLL("user32.dll").NewProc("ReplyMessage")
	getForegroundWindow,_ = syscall.GetProcAddress(user32, "GetForegroundWindow")
	setForegroundWindow,_ = syscall.GetProcAddress(user32, "SetForegroundWindow")

	kernel32, _            = syscall.LoadLibrary("kernel32.dll")
	waitForSingleObject, _ = syscall.GetProcAddress(kernel32, "WaitForSingleObject")
	dwProcessId uint32 = 0
	zeroProcAttr syscall.ProcAttr
	zeroSysProcAttr syscall.SysProcAttr
	ForkLock sync.RWMutex
)

func RegisterHotKey(hWnd winapi.HWND, id int, fsModifiers, vk uint) bool {
	ret, _, _ := syscall.Syscall6(uintptr(registerHotkey), 4,
		uintptr(hWnd),
		uintptr(id),
		uintptr(fsModifiers),
		uintptr(vk),0,0)

	return ret != 0
}

func GetWindowThreadProcessId(hWnd syscall.Handle) (winapi.HANDLE, uint32) {
	var id int
	ret, _, _ := syscall.Syscall(uintptr(getWindowThreadProcessId), 2,
		uintptr(hWnd),
		uintptr(unsafe.Pointer(&id)),
		0)

	return winapi.HANDLE(ret), uint32(id)
}

func EnumWindows(f func(syscall.Handle, uintptr) uintptr, lParam uint32) bool {
	ret, _, _ := syscall.Syscall(uintptr(enumWindows), 2,
		uintptr(syscall.NewCallback(f)),
		uintptr(lParam),
		0)

	return ret != 0
}

func GetForegroundWindow() syscall.Handle {
	ret,_,_ := syscall.Syscall(uintptr(getForegroundWindow), 0, 0, 0, 0)
	return syscall.Handle(ret)
}

func SetForegroundWindow(hnd syscall.Handle) syscall.Handle {
	ret,_,_ := syscall.Syscall(uintptr(setForegroundWindow), 1,
		uintptr(hnd), 0, 0,
	)

	return syscall.Handle(ret)
}

func createProcess(attr *syscall.ProcAttr) (pid int, handle uintptr, err error) {
	if attr == nil {
		attr = &zeroProcAttr
	}
	sys := attr.Sys
	if sys == nil {
		sys = &zeroSysProcAttr
	}

	if len(attr.Files) > 3 {
		return 0, 0, syscall.EWINDOWS
	}
	if len(attr.Files) < 3 {
		return 0, 0, syscall.EINVAL
	}

	var cmdline string
	// Windows CreateProcess takes the command line as a single string:
	// use attr.CmdLine if set, else build the command line by escaping
	// and joining each argument with spaces
	if sys.CmdLine != "" {
		cmdline = sys.CmdLine
	} else {
		return 0, 0, errors.New("sys.CmdLine is empty")
	}

	var argvp *uint16
	if len(cmdline) != 0 {
		argvp, err = syscall.UTF16PtrFromString(cmdline)
		if err != nil {
			return 0, 0, err
		}
	}

	var dirp *uint16
	if len(attr.Dir) != 0 {
		dirp, err = syscall.UTF16PtrFromString(attr.Dir)
		if err != nil {
			return 0, 0, err
		}
	}

	// Acquire the fork lock so that no other threads
	// create new fds that are not yet close-on-exec
	// before we fork.
	ForkLock.Lock()
	defer ForkLock.Unlock()

	p, _ := syscall.GetCurrentProcess()
	fd := make([]syscall.Handle, len(attr.Files))
	for i := range attr.Files {
		if attr.Files[i] > 0 {
			err := syscall.DuplicateHandle(p, syscall.Handle(attr.Files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS)
			if err != nil {
				return 0, 0, err
			}
			defer syscall.CloseHandle(syscall.Handle(fd[i]))
		}
	}
	si := new(syscall.StartupInfo)
	si.Cb = uint32(unsafe.Sizeof(*si))

	pi := new(syscall.ProcessInformation)

	flags := sys.CreationFlags | syscall.CREATE_UNICODE_ENVIRONMENT
	err = syscall.CreateProcess(nil, argvp, nil, nil, false, flags, nil, dirp, si, pi)
	if err != nil {
		return 0, 0, err
	}
	defer syscall.CloseHandle(syscall.Handle(pi.Thread))

	return int(pi.ProcessId), uintptr(pi.Process), nil
}

func showErrorMessage(hWnd winapi.HWND, msg string) {
	s, _ := syscall.UTF16PtrFromString(msg)
	t, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)
	winapi.MessageBox(hWnd, s, t, winapi.MB_ICONWARNING|winapi.MB_OK)
}

func run() int {
	hInstance := winapi.GetModuleHandle(nil)

	if registerWindowClass(hInstance) == 0 {
		showErrorMessage(0, "registerWindowClass failed")
		return 1
	}

	if err := initializeInstance(hInstance, winapi.SW_SHOW); err != nil {
		showErrorMessage(0, err.Error())
		return 1
	}

	var msg winapi.MSG
	for winapi.GetMessage(&msg, 0,0,0) != 0 {
		winapi.TranslateMessage(&msg)
		winapi.DispatchMessage(&msg)
	}

	finalizeInstance(hInstance)

	return int(msg.WParam)
}

func registerWindowClass(hInstance winapi.HINSTANCE) winapi.ATOM {
	var wc winapi.WNDCLASSEX

	wc.CbSize = uint32(unsafe.Sizeof(winapi.WNDCLASSEX{}))
	wc.Style = 0
	wc.LpfnWndProc = syscall.NewCallback(wndProc)
	wc.CbClsExtra = 0
	wc.CbWndExtra = 0
	wc.HInstance = hInstance
	wc.HIcon         = winapi.LoadIcon(hInstance, winapi.MAKEINTRESOURCE(132))
	wc.HCursor       = winapi.LoadCursor(0, winapi.MAKEINTRESOURCE(winapi.IDC_HAND))
	wc.HbrBackground = winapi.HBRUSH(winapi.GetStockObject(winapi.WHITE_BRUSH))
	wc.LpszMenuName  = nil
	wc.LpszClassName,_ = syscall.UTF16PtrFromString(WINDOW_CLASS)

	return winapi.RegisterClassEx(&wc)
}

func initializeInstance(hInstance winapi.HINSTANCE, nCmdShow int) error {
	pc, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)
	pt, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)

	hWnd := winapi.CreateWindowEx(
		winapi.WS_EX_TOOLWINDOW|winapi.WS_EX_TOPMOST|winapi.WS_EX_NOACTIVATE|winapi.WS_EX_LAYERED,
		pc,pt,winapi.WS_POPUP,
		0,
		0,
		0,
		0,
		0,0,hInstance,nil)

	if hWnd == 0 {
		return errors.New("CreateWindowEx failed")
	}

	winapi.ShowWindow(hWnd, int32(nCmdShow))
	winapi.UpdateWindow(hWnd)

	if (RegisterHotKey(hWnd, 0, MOD_ALT|MOD_CONTROL, uint(config.Key)) == false) {
		return errors.New("RegisterHotKey failed")
	}

	return nil
}

func finalizeInstance(hInstance winapi.HINSTANCE) error {
	return nil
}

func isProcessGone(id uint32) bool {
	hProcess,err := syscall.OpenProcess(SYNCHRONIZE, false, id);
	if err != nil {
		return true;
	}

	dwWait,err := syscall.WaitForSingleObject(hProcess,0);
	if err != nil {
		return false
	}

	err = syscall.CloseHandle(hProcess)
	if err != nil {
		return false
	}

	return(dwWait == WAIT_OBJECT_0);
}

func createChildProcess(id uint32) (uint32,error) {
	if(!isProcessGone(id)) {
		return id,nil;
	}

	var sys syscall.SysProcAttr
	var attr syscall.ProcAttr

	sys.CreationFlags = CREATE_NEW_CONSOLE
	sys.CmdLine       = config.Cmdline

	attr.Files = make([]uintptr, 3)
	attr.Sys = &sys
	if config.WorkDir == "" {
		attr.Dir = os.Getenv("USERPROFILE")
	} else {
		attr.Dir = config.WorkDir
	}

	pid, _, err := createProcess(&attr)
	if err != nil {
		return 0,err
	}

	return uint32(pid), nil
}

func toggleWindowbyProcID(hwnd syscall.Handle, lparam uintptr) uintptr {
	var pid uint32
	_, pid = GetWindowThreadProcessId(hwnd)

	if (uint32(lparam) == pid) {
		if (winapi.IsWindowVisible(winapi.HWND(hwnd))) {
			if GetForegroundWindow() != hwnd {
				SetForegroundWindow(hwnd)
			} else {
				winapi.ShowWindow(winapi.HWND(hwnd), winapi.SW_HIDE);
			}
		} else {
			winapi.ShowWindow(winapi.HWND(hwnd), winapi.SW_SHOW);
			SetForegroundWindow(hwnd)
		}
		return 0
	}
	return 1
}

func wndProc(hWnd winapi.HWND, msg uint32, wParam uintptr, lParam uintptr) uintptr {
	switch msg {
	case winapi.WM_HOTKEY:
		var err error
		dwProcessId,err = createChildProcess(dwProcessId);
		if err != nil {
			procReplyMessage.Call(1)
			return 0
		}

		EnumWindows(toggleWindowbyProcID, dwProcessId)
		return 0
	case winapi.WM_DESTROY:
		winapi.PostQuitMessage(0)
	default:
		return winapi.DefWindowProc(hWnd, msg, wParam, lParam)
	}
	return 0
}
<commit_msg>Add monitoring child process<commit_after>package main

import (
	"github.com/cwchiu/go-winapi"
	"os"
	"sync"
	"unsafe"
	"syscall"
	"errors"
)

const (
	WINDOW_CLASS = "dacko"
)

const (
	MOD_ALT = 1
	MOD_CONTROL = 2
	MOD_SHIFT = 4
	MOD_WIN = 8
)

const (
	SYNCHRONIZE = 0x00100000
)

const (
	CREATE_NEW_CONSOLE = 0x00000010
)

const (
	WAIT_OBJECT_0 = 0x00000000
	WAIT_ABANDONED = 0x00000080
	WAIT_timeout = 0x00000102
	WAIT_FAILED = 0xFFFFFFFF
)

var (
	user32, _         = syscall.LoadLibrary("user32.dll")
	registerHotkey, _ = syscall.GetProcAddress(user32, "RegisterHotKey")
	getWindowThreadProcessId, _ = syscall.GetProcAddress(user32, "GetWindowThreadProcessId")
	enumWindows, _ = syscall.GetProcAddress(user32, "EnumWindows")
	procReplyMessage = syscall.NewLazyDLL("user32.dll").NewProc("ReplyMessage")
	getForegroundWindow,_ = syscall.GetProcAddress(user32, "GetForegroundWindow")
	setForegroundWindow,_ = syscall.GetProcAddress(user32, "SetForegroundWindow")

	kernel32, _            = syscall.LoadLibrary("kernel32.dll")
	waitForSingleObject, _ = syscall.GetProcAddress(kernel32, "WaitForSingleObject")
	dwProcessId uint32 = 0
	zeroProcAttr syscall.ProcAttr
	zeroSysProcAttr syscall.SysProcAttr
	ForkLock sync.RWMutex
)

func RegisterHotKey(hWnd winapi.HWND, id int, fsModifiers, vk uint) bool {
	ret, _, _ := syscall.Syscall6(uintptr(registerHotkey), 4,
		uintptr(hWnd),
		uintptr(id),
		uintptr(fsModifiers),
		uintptr(vk),0,0)

	return ret != 0
}

func GetWindowThreadProcessId(hWnd syscall.Handle) (winapi.HANDLE, uint32) {
	var id int
	ret, _, _ := syscall.Syscall(uintptr(getWindowThreadProcessId), 2,
		uintptr(hWnd),
		uintptr(unsafe.Pointer(&id)),
		0)

	return winapi.HANDLE(ret), uint32(id)
}

func EnumWindows(f func(syscall.Handle, uintptr) uintptr, lParam uint32) bool {
	ret, _, _ := syscall.Syscall(uintptr(enumWindows), 2,
		uintptr(syscall.NewCallback(f)),
		uintptr(lParam),
		0)

	return ret != 0
}

func GetForegroundWindow() syscall.Handle {
	ret,_,_ := syscall.Syscall(uintptr(getForegroundWindow), 0, 0, 0, 0)
	return syscall.Handle(ret)
}

func SetForegroundWindow(hnd syscall.Handle) syscall.Handle {
	ret,_,_ := syscall.Syscall(uintptr(setForegroundWindow), 1,
		uintptr(hnd), 0, 0,
	)

	return syscall.Handle(ret)
}

func createProcess(attr *syscall.ProcAttr) (pid int, handle uintptr, err error) {
	if attr == nil {
		attr = &zeroProcAttr
	}
	sys := attr.Sys
	if sys == nil {
		sys = &zeroSysProcAttr
	}

	if len(attr.Files) > 3 {
		return 0, 0, syscall.EWINDOWS
	}
	if len(attr.Files) < 3 {
		return 0, 0, syscall.EINVAL
	}

	var cmdline string
	// Windows CreateProcess takes the command line as a single string:
	// use attr.CmdLine if set, else build the command line by escaping
	// and joining each argument with spaces
	if sys.CmdLine != "" {
		cmdline = sys.CmdLine
	} else {
		return 0, 0, errors.New("sys.CmdLine is empty")
	}

	var argvp *uint16
	if len(cmdline) != 0 {
		argvp, err = syscall.UTF16PtrFromString(cmdline)
		if err != nil {
			return 0, 0, err
		}
	}

	var dirp *uint16
	if len(attr.Dir) != 0 {
		dirp, err = syscall.UTF16PtrFromString(attr.Dir)
		if err != nil {
			return 0, 0, err
		}
	}

	// Acquire the fork lock so that no other threads
	// create new fds that are not yet close-on-exec
	// before we fork.
	ForkLock.Lock()
	defer ForkLock.Unlock()

	p, _ := syscall.GetCurrentProcess()
	fd := make([]syscall.Handle, len(attr.Files))
	for i := range attr.Files {
		if attr.Files[i] > 0 {
			err := syscall.DuplicateHandle(p, syscall.Handle(attr.Files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS)
			if err != nil {
				return 0, 0, err
			}
			defer syscall.CloseHandle(syscall.Handle(fd[i]))
		}
	}
	si := new(syscall.StartupInfo)
	si.Cb = uint32(unsafe.Sizeof(*si))
	if sys.HideWindow {
		si.Flags |= syscall.STARTF_USESHOWWINDOW
		si.ShowWindow = syscall.SW_HIDE
	}

	pi := new(syscall.ProcessInformation)

	flags := sys.CreationFlags | syscall.CREATE_UNICODE_ENVIRONMENT
	err = syscall.CreateProcess(nil, argvp, nil, nil, false, flags, nil, dirp, si, pi)
	if err != nil {
		return 0, 0, err
	}
	defer syscall.CloseHandle(syscall.Handle(pi.Thread))

	return int(pi.ProcessId), uintptr(pi.Process), nil
}

func showErrorMessage(hWnd winapi.HWND, msg string) {
	s, _ := syscall.UTF16PtrFromString(msg)
	t, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)
	winapi.MessageBox(hWnd, s, t, winapi.MB_ICONWARNING|winapi.MB_OK)
}

func run() int {
	hInstance := winapi.GetModuleHandle(nil)

	if registerWindowClass(hInstance) == 0 {
		showErrorMessage(0, "registerWindowClass failed")
		return 1
	}

	if err := initializeInstance(hInstance, winapi.SW_SHOW); err != nil {
		showErrorMessage(0, err.Error())
		return 1
	}

	var msg winapi.MSG
	for winapi.GetMessage(&msg, 0,0,0) != 0 {
		winapi.TranslateMessage(&msg)
		winapi.DispatchMessage(&msg)
	}

	finalizeInstance(hInstance)

	return int(msg.WParam)
}

func registerWindowClass(hInstance winapi.HINSTANCE) winapi.ATOM {
	var wc winapi.WNDCLASSEX

	wc.CbSize = uint32(unsafe.Sizeof(winapi.WNDCLASSEX{}))
	wc.Style = 0
	wc.LpfnWndProc = syscall.NewCallback(wndProc)
	wc.CbClsExtra = 0
	wc.CbWndExtra = 0
	wc.HInstance = hInstance
	wc.HIcon         = winapi.LoadIcon(hInstance, winapi.MAKEINTRESOURCE(132))
	wc.HCursor       = winapi.LoadCursor(0, winapi.MAKEINTRESOURCE(winapi.IDC_HAND))
	wc.HbrBackground = winapi.HBRUSH(winapi.GetStockObject(winapi.WHITE_BRUSH))
	wc.LpszMenuName  = nil
	wc.LpszClassName,_ = syscall.UTF16PtrFromString(WINDOW_CLASS)

	return winapi.RegisterClassEx(&wc)
}

func initializeInstance(hInstance winapi.HINSTANCE, nCmdShow int) error {
	pc, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)
	pt, _ := syscall.UTF16PtrFromString(WINDOW_CLASS)

	hWnd := winapi.CreateWindowEx(
		winapi.WS_EX_TOOLWINDOW|winapi.WS_EX_TOPMOST|winapi.WS_EX_NOACTIVATE|winapi.WS_EX_LAYERED,
		pc,pt,winapi.WS_POPUP,
		0,
		0,
		0,
		0,
		0,0,hInstance,nil)

	if hWnd == 0 {
		return errors.New("CreateWindowEx failed")
	}

	winapi.ShowWindow(hWnd, int32(nCmdShow))
	winapi.UpdateWindow(hWnd)

	if (RegisterHotKey(hWnd, 0, MOD_ALT|MOD_CONTROL, uint(config.Key)) == false) {
		return errors.New("RegisterHotKey failed")
	}

	return nil
}

func finalizeInstance(hInstance winapi.HINSTANCE) error {
	return nil
}

func isProcessGone(id uint32) bool {
	hProcess,err := syscall.OpenProcess(SYNCHRONIZE, false, id);
	if err != nil {
		return true;
	}

	dwWait,err := syscall.WaitForSingleObject(hProcess,0);
	if err != nil {
		return false
	}

	err = syscall.CloseHandle(hProcess)
	if err != nil {
		return false
	}

	return(dwWait == WAIT_OBJECT_0);
}

func createChildProcess(id uint32, hideWindow bool) (uint32,error) {
	if(!isProcessGone(id)) {
		return id,nil;
	}

	var sys syscall.SysProcAttr
	var attr syscall.ProcAttr

	sys.HideWindow    = hideWindow
	sys.CreationFlags = CREATE_NEW_CONSOLE
	sys.CmdLine       = config.Cmdline

	attr.Files = make([]uintptr, 3)
	attr.Sys = &sys
	if config.WorkDir == "" {
		attr.Dir = os.Getenv("USERPROFILE")
	} else {
		attr.Dir = config.WorkDir
	}

	pid, _, err := createProcess(&attr)
	if err != nil {
		return 0,err
	}

	return uint32(pid), nil
}

func toggleWindowbyProcID(hwnd syscall.Handle, lparam uintptr) uintptr {
	var pid uint32
	_, pid = GetWindowThreadProcessId(hwnd)

	if (uint32(lparam) == pid) {
		if (winapi.IsWindowVisible(winapi.HWND(hwnd))) {
			if GetForegroundWindow() != hwnd {
				SetForegroundWindow(hwnd)
			} else {
				winapi.ShowWindow(winapi.HWND(hwnd), winapi.SW_HIDE);
			}
		} else {
			winapi.ShowWindow(winapi.HWND(hwnd), winapi.SW_SHOW);
			SetForegroundWindow(hwnd)
		}
		return 0
	}
	return 1
}

func wndProc(hWnd winapi.HWND, msg uint32, wParam uintptr, lParam uintptr) uintptr {
	var err error
	switch msg {
	case winapi.WM_HOTKEY:
		dwProcessId,err = createChildProcess(dwProcessId, false);
		if err != nil {
			procReplyMessage.Call(1)
			return 0
		}

		EnumWindows(toggleWindowbyProcID, dwProcessId)
		return 0
	case winapi.WM_CREATE:
		winapi.SetTimer(hWnd, uintptr(1), 1000, uintptr(0))
	case winapi.WM_TIMER:
		dwProcessId,err = createChildProcess(dwProcessId, true);
		if err != nil {
			procReplyMessage.Call(1)
			return 0
		}
	case winapi.WM_DESTROY:
		winapi.PostQuitMessage(0)
	default:
		return winapi.DefWindowProc(hWnd, msg, wParam, lParam)
	}
	return 0
}
<|endoftext|>


<commit_before>package client

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

// DownloadData retrieves a file from the server and saves contents at filePath
func DownloadData(url string, filePath string) error {

	// Fetch the file
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("error %d downloading file at %s", resp.StatusCode, url)
	}

	// If response OK, create our file with downloaded response body
	f, err := os.Create(filePath)
	if err != nil {
		return err
	}
	n, err := io.Copy(f, resp.Body)
	if err != nil {
		return err
	}
	fmt.Printf("Wrote %d bytes to file %s\n", n, filePath)

	return nil
}

// PostData sends data to the server
func PostData(sender, recipient, file, url string) error {

	// Prepare a new multipart form writer
	var formData bytes.Buffer
	w := multipart.NewWriter(&formData)

	// Add the encrypted file
	err := addFile(w, file)
	if err != nil {
		return err
	}

	// Add sender identity
	err = addField(w, "from", sender)
	if err != nil {
		return err
	}
	// Add recipient identity
	err = addField(w, "to", recipient)
	if err != nil {
		return err
	}
	// Close the writer
	w.Close()

	// Now post the form
	req, err := http.NewRequest("POST", url, &formData)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", w.FormDataContentType())

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("Error status %d posting file to %s\n", resp.StatusCode, url)
	}

	fmt.Printf("File sent to: %s %v\n", url, resp)

	return nil

}

// addFile adds a file to this multipart form
func addFile(w *multipart.Writer, filePath string) error {
	f, err := os.Open(filePath)
	if err != nil {
		return err
	}
	fw, err := w.CreateFormFile("file", filePath)
	if err != nil {
		return err
	}
	_, err = io.Copy(fw, f)
	if err != nil {
		return err
	}
	return nil
}

// addField adds a field to the multipart writer
func addField(w *multipart.Writer, k, v string) error {
	fw, err := w.CreateFormField(k)
	if err != nil {
		return err
	}
	_, err = fw.Write([]byte(v))
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Adjusted page templates, added font awesome, ready for styling<commit_after>package client

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

// DownloadData retrieves a file from the server and saves contents at filePath
func DownloadData(url string, filePath string) error {

	// Fetch the file
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("error %d downloading file at %s", resp.StatusCode, url)
	}

	// If response OK, create our file with downloaded response body
	f, err := os.Create(filePath)
	if err != nil {
		return err
	}
	n, err := io.Copy(f, resp.Body)
	if err != nil {
		return err
	}
	fmt.Printf("Wrote %d bytes to file %s\n", n, filePath)

	return nil
}

// PostData sends data to the server
func PostData(sender, recipient, file, url string) error {

	// Prepare a new multipart form writer
	var formData bytes.Buffer
	w := multipart.NewWriter(&formData)

	// Add the encrypted file
	err := addFile(w, file)
	if err != nil {
		return err
	}

	// Add sender identity
	err = addField(w, "sender", sender)
	if err != nil {
		return err
	}
	// Add recipient identity
	err = addField(w, "recipient", recipient)
	if err != nil {
		return err
	}

	// Close the writer
	w.Close()

	// Now post the form
	req, err := http.NewRequest("POST", url, &formData)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", w.FormDataContentType())

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("Error status %d posting file to %s\n", resp.StatusCode, url)
	}

	fmt.Printf("File sent to: %s %v\n", url, resp)

	return nil

}

// addFile adds a file to this multipart form
func addFile(w *multipart.Writer, filePath string) error {
	f, err := os.Open(filePath)
	if err != nil {
		return err
	}
	fw, err := w.CreateFormFile("file", filePath)
	if err != nil {
		return err
	}
	_, err = io.Copy(fw, f)
	if err != nil {
		return err
	}
	return nil
}

// addField adds a field to the multipart writer
func addField(w *multipart.Writer, k, v string) error {
	fw, err := w.CreateFormField(k)
	if err != nil {
		return err
	}
	_, err = fw.Write([]byte(v))
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>