<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package limitranger

import (
	"fmt"
	"io"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

func init() {
	admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
		return NewLimitRanger(client, Limit), nil
	})
}

// limitRanger enforces usage limits on a per resource basis in the namespace
type limitRanger struct {
	client    client.Interface
	limitFunc LimitFunc
	indexer   cache.Indexer
}

// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
	// ignore deletes
	if a.GetOperation() == "DELETE" {
		return nil
	}

	obj := a.GetObject()
	resource := a.GetResource()
	name := "Unknown"
	if obj != nil {
		name, _ = meta.NewAccessor().Name(obj)
	}

	key := &api.LimitRange{
		ObjectMeta: api.ObjectMeta{
			Namespace: a.GetNamespace(),
			Name:      "",
		},
	}
	items, err := l.indexer.Index("namespace", key)
	if err != nil {
		return apierrors.NewForbidden(a.GetResource(), name, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing limit ranges", a.GetOperation(), resource))
	}
	if len(items) == 0 {
		return nil
	}

	// ensure it meets each prescribed min/max
	for i := range items {
		limitRange := items[i].(*api.LimitRange)
		err = l.limitFunc(limitRange, a.GetResource(), a.GetObject())
		if err != nil {
			return err
		}
	}
	return nil
}

// NewLimitRanger returns an object that enforces limits based on the supplied limit function
func NewLimitRanger(client client.Interface, limitFunc LimitFunc) admission.Interface {
	lw := &cache.ListWatch{
		ListFunc: func() (runtime.Object, error) {
			return client.LimitRanges(api.NamespaceAll).List(labels.Everything())
		},
		WatchFunc: func(resourceVersion string) (watch.Interface, error) {
			return client.LimitRanges(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), resourceVersion)
		},
	}
	indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
	reflector.Run()
	return &limitRanger{client: client, limitFunc: limitFunc, indexer: indexer}
}

func Min(a int64, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func Max(a int64, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

// Limit enforces resource requirements of incoming resources against enumerated constraints
// on the LimitRange.  It may modify the incoming object to apply default resource requirements
// if not specified, and enumerated on the LimitRange
func Limit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
	switch resourceName {
	case "pods":
		return PodLimitFunc(limitRange, obj.(*api.Pod))
	}
	return nil
}

// defaultContainerResourceRequirements returns the default requirements for a container
// the requirement.Limits are taken from the LimitRange defaults (if specified)
// the requirement.Requests are taken from the LimitRange min (if specified)
func defaultContainerResourceRequirements(limitRange *api.LimitRange) api.ResourceRequirements {
	requirements := api.ResourceRequirements{}
	requirements.Limits = api.ResourceList{}
	requirements.Requests = api.ResourceList{}

	for i := range limitRange.Spec.Limits {
		limit := limitRange.Spec.Limits[i]
		if limit.Type == api.LimitTypeContainer {
			for k, v := range limit.Default {
				value := v.Copy()
				requirements.Limits[k] = *value
			}
			for k, v := range limit.Min {
				value := v.Copy()
				requirements.Requests[k] = *value
			}
		}
	}
	return requirements
}

// mergePodResourceRequirements merges enumerated requirements with default requirements
func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.ResourceRequirements) {
	for i := range pod.Spec.Containers {
		container := pod.Spec.Containers[i]
		for k, v := range defaultRequirements.Limits {
			_, found := container.Resources.Limits[k]
			if !found {
				container.Resources.Limits[k] = *v.Copy()
			}
		}
		for k, v := range defaultRequirements.Requests {
			_, found := container.Resources.Requests[k]
			if !found {
				container.Resources.Requests[k] = *v.Copy()
			}
		}
	}
}

// PodLimitFunc enforces resource requirements enumerated by the pod against
// the specified LimitRange.  The pod may be modified to apply default resource
// requirements if not specified, and enumerated on the LimitRange
func PodLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {

	defaultResources := defaultContainerResourceRequirements(limitRange)
	mergePodResourceRequirements(pod, &defaultResources)

	podCPU := int64(0)
	podMem := int64(0)

	minContainerCPU := int64(0)
	minContainerMem := int64(0)
	maxContainerCPU := int64(0)
	maxContainerMem := int64(0)

	for i := range pod.Spec.Containers {
		container := pod.Spec.Containers[i]
		containerCPU := container.Resources.Limits.Cpu().MilliValue()
		containerMem := container.Resources.Limits.Memory().Value()

		if i == 0 {
			minContainerCPU = containerCPU
			minContainerMem = containerMem
			maxContainerCPU = containerCPU
			maxContainerMem = containerMem
		}

		podCPU = podCPU + container.Resources.Limits.Cpu().MilliValue()
		podMem = podMem + container.Resources.Limits.Memory().Value()

		minContainerCPU = Min(containerCPU, minContainerCPU)
		minContainerMem = Min(containerMem, minContainerMem)
		maxContainerCPU = Max(containerCPU, maxContainerCPU)
		maxContainerMem = Max(containerMem, maxContainerMem)
	}

	for i := range limitRange.Spec.Limits {
		limit := limitRange.Spec.Limits[i]
		for _, minOrMax := range []string{"Min", "Max"} {
			var rl api.ResourceList
			switch minOrMax {
			case "Min":
				rl = limit.Min
			case "Max":
				rl = limit.Max
			}
			for k, v := range rl {
				observed := int64(0)
				enforced := int64(0)
				var err error
				switch k {
				case api.ResourceMemory:
					enforced = v.Value()
					switch limit.Type {
					case api.LimitTypePod:
						observed = podMem
						err = fmt.Errorf("%simum memory usage per pod is %s", minOrMax, v.String())
					case api.LimitTypeContainer:
						observed = maxContainerMem
						err = fmt.Errorf("%simum memory usage per container is %s", minOrMax, v.String())
					}
				case api.ResourceCPU:
					enforced = v.MilliValue()
					switch limit.Type {
					case api.LimitTypePod:
						observed = podCPU
						err = fmt.Errorf("%simum CPU usage per pod is %s, but requested %s", minOrMax, v.String(), resource.NewMilliQuantity(observed, resource.DecimalSI))
					case api.LimitTypeContainer:
						observed = maxContainerCPU
						err = fmt.Errorf("%simum CPU usage per container is %s", minOrMax, v.String())
					}
				}
				switch minOrMax {
				case "Min":
					if observed < enforced {
						return apierrors.NewForbidden("pods", pod.Name, err)
					}
				case "Max":
					if observed > enforced {
						return apierrors.NewForbidden("pods", pod.Name, err)
					}
				}
			}
		}
	}
	return nil
}
<commit_msg>UPSTREAM Fix nil pointer in limit ranger<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package limitranger

import (
	"fmt"
	"io"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)

func init() {
	admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
		return NewLimitRanger(client, Limit), nil
	})
}

// limitRanger enforces usage limits on a per resource basis in the namespace
type limitRanger struct {
	client    client.Interface
	limitFunc LimitFunc
	indexer   cache.Indexer
}

// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
	// ignore deletes
	if a.GetOperation() == "DELETE" {
		return nil
	}

	obj := a.GetObject()
	resource := a.GetResource()
	name := "Unknown"
	if obj != nil {
		name, _ = meta.NewAccessor().Name(obj)
	}

	key := &api.LimitRange{
		ObjectMeta: api.ObjectMeta{
			Namespace: a.GetNamespace(),
			Name:      "",
		},
	}
	items, err := l.indexer.Index("namespace", key)
	if err != nil {
		return apierrors.NewForbidden(a.GetResource(), name, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing limit ranges", a.GetOperation(), resource))
	}
	if len(items) == 0 {
		return nil
	}

	// ensure it meets each prescribed min/max
	for i := range items {
		limitRange := items[i].(*api.LimitRange)
		err = l.limitFunc(limitRange, a.GetResource(), a.GetObject())
		if err != nil {
			return err
		}
	}
	return nil
}

// NewLimitRanger returns an object that enforces limits based on the supplied limit function
func NewLimitRanger(client client.Interface, limitFunc LimitFunc) admission.Interface {
	lw := &cache.ListWatch{
		ListFunc: func() (runtime.Object, error) {
			return client.LimitRanges(api.NamespaceAll).List(labels.Everything())
		},
		WatchFunc: func(resourceVersion string) (watch.Interface, error) {
			return client.LimitRanges(api.NamespaceAll).Watch(labels.Everything(), fields.Everything(), resourceVersion)
		},
	}
	indexer, reflector := cache.NewNamespaceKeyedIndexerAndReflector(lw, &api.LimitRange{}, 0)
	reflector.Run()
	return &limitRanger{client: client, limitFunc: limitFunc, indexer: indexer}
}

func Min(a int64, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func Max(a int64, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

// Limit enforces resource requirements of incoming resources against enumerated constraints
// on the LimitRange.  It may modify the incoming object to apply default resource requirements
// if not specified, and enumerated on the LimitRange
func Limit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
	switch resourceName {
	case "pods":
		return PodLimitFunc(limitRange, obj.(*api.Pod))
	}
	return nil
}

// defaultContainerResourceRequirements returns the default requirements for a container
// the requirement.Limits are taken from the LimitRange defaults (if specified)
// the requirement.Requests are taken from the LimitRange min (if specified)
func defaultContainerResourceRequirements(limitRange *api.LimitRange) api.ResourceRequirements {
	requirements := api.ResourceRequirements{}
	requirements.Limits = api.ResourceList{}
	requirements.Requests = api.ResourceList{}

	for i := range limitRange.Spec.Limits {
		limit := limitRange.Spec.Limits[i]
		if limit.Type == api.LimitTypeContainer {
			for k, v := range limit.Default {
				value := v.Copy()
				requirements.Limits[k] = *value
			}
			for k, v := range limit.Min {
				value := v.Copy()
				requirements.Requests[k] = *value
			}
		}
	}
	return requirements
}

// mergePodResourceRequirements merges enumerated requirements with default requirements
func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.ResourceRequirements) {
	for i := range pod.Spec.Containers {
		container := pod.Spec.Containers[i]
		if container.Resources.Limits == nil {
			container.Resources.Limits = api.ResourceList{}
		}
		if container.Resources.Requests == nil {
			container.Resources.Requests = api.ResourceList{}
		}
		for k, v := range defaultRequirements.Limits {
			_, found := container.Resources.Limits[k]
			if !found {
				container.Resources.Limits[k] = *v.Copy()
			}
		}
		for k, v := range defaultRequirements.Requests {
			_, found := container.Resources.Requests[k]
			if !found {
				container.Resources.Requests[k] = *v.Copy()
			}
		}
	}
}

// PodLimitFunc enforces resource requirements enumerated by the pod against
// the specified LimitRange.  The pod may be modified to apply default resource
// requirements if not specified, and enumerated on the LimitRange
func PodLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {

	defaultResources := defaultContainerResourceRequirements(limitRange)
	mergePodResourceRequirements(pod, &defaultResources)

	podCPU := int64(0)
	podMem := int64(0)

	minContainerCPU := int64(0)
	minContainerMem := int64(0)
	maxContainerCPU := int64(0)
	maxContainerMem := int64(0)

	for i := range pod.Spec.Containers {
		container := pod.Spec.Containers[i]
		containerCPU := container.Resources.Limits.Cpu().MilliValue()
		containerMem := container.Resources.Limits.Memory().Value()

		if i == 0 {
			minContainerCPU = containerCPU
			minContainerMem = containerMem
			maxContainerCPU = containerCPU
			maxContainerMem = containerMem
		}

		podCPU = podCPU + container.Resources.Limits.Cpu().MilliValue()
		podMem = podMem + container.Resources.Limits.Memory().Value()

		minContainerCPU = Min(containerCPU, minContainerCPU)
		minContainerMem = Min(containerMem, minContainerMem)
		maxContainerCPU = Max(containerCPU, maxContainerCPU)
		maxContainerMem = Max(containerMem, maxContainerMem)
	}

	for i := range limitRange.Spec.Limits {
		limit := limitRange.Spec.Limits[i]
		for _, minOrMax := range []string{"Min", "Max"} {
			var rl api.ResourceList
			switch minOrMax {
			case "Min":
				rl = limit.Min
			case "Max":
				rl = limit.Max
			}
			for k, v := range rl {
				observed := int64(0)
				enforced := int64(0)
				var err error
				switch k {
				case api.ResourceMemory:
					enforced = v.Value()
					switch limit.Type {
					case api.LimitTypePod:
						observed = podMem
						err = fmt.Errorf("%simum memory usage per pod is %s", minOrMax, v.String())
					case api.LimitTypeContainer:
						observed = maxContainerMem
						err = fmt.Errorf("%simum memory usage per container is %s", minOrMax, v.String())
					}
				case api.ResourceCPU:
					enforced = v.MilliValue()
					switch limit.Type {
					case api.LimitTypePod:
						observed = podCPU
						err = fmt.Errorf("%simum CPU usage per pod is %s, but requested %s", minOrMax, v.String(), resource.NewMilliQuantity(observed, resource.DecimalSI))
					case api.LimitTypeContainer:
						observed = maxContainerCPU
						err = fmt.Errorf("%simum CPU usage per container is %s", minOrMax, v.String())
					}
				}
				switch minOrMax {
				case "Min":
					if observed < enforced {
						return apierrors.NewForbidden("pods", pod.Name, err)
					}
				case "Max":
					if observed > enforced {
						return apierrors.NewForbidden("pods", pod.Name, err)
					}
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package magicsql

import (
	"reflect"
)

// OperationTable ties together a memorized MagicTable definition with an
// in-progress SQL operation
type OperationTable struct {
	op *Operation
	t  *MagicTable
}

// Reconfigure sends explicit ConfigTags data to the underlying MagicTable in
// order to override the reflected structure's tags
func (ot *OperationTable) Reconfigure(conf ConfigTags) {
	ot.t.Configure(conf)
}

// Select simply instantiates a Select instance with the OperationTable set up
// for it to use for gathering fields and running the query
func (ot *OperationTable) Select() Select {
	return NewSelect(ot)
}

// Save determines if an INSERT or UPDATE is necessary (primary key of 0 means
// INSERT here), generates the SQL and arguments, and runs the Exec call on the
// database.  Behavior may be unpredictable if a MagicTable was manually
// registered with a structure of a different type than obj.
func (ot *OperationTable) Save(obj interface{}) *Result {
	// Check for object's primary key field being zero
	var rVal = reflect.ValueOf(obj).Elem()
	var pkValField = rVal.FieldByName(ot.t.primaryKey.Field.Name)

	if pkValField.Interface() == reflect.Zero(pkValField.Type()).Interface() {
		var res = ot.op.Exec(ot.t.InsertSQL(), ot.t.InsertArgs(obj)...)
		pkValField.SetInt(res.LastInsertId())
		return res
	}

	return ot.op.Exec(ot.t.UpdateSQL(), ot.t.UpdateArgs(obj)...)
}

// Insert forces an insert, ignoring any primary key tagging.  Note that
// directly inserting via this method will *not* auto-set the primary key to
// the last insert id.
//
// TODO: make the DB querying backend more flexible so it doesn't care about
// tagging for generating SQL and arg lists, instead relying on field and
// column name mappings
func (ot *OperationTable) Insert(obj interface{}) *Result {
	var pkField = ot.t.primaryKey
	ot.t.primaryKey = nil
	var res = ot.op.Exec(ot.t.InsertSQL(), ot.t.InsertArgs(obj)...)
	ot.t.primaryKey = pkField

	return res
}
<commit_msg>Handle uint primary keys without a panic<commit_after>package magicsql

import (
	"reflect"
)

// OperationTable ties together a memorized MagicTable definition with an
// in-progress SQL operation
type OperationTable struct {
	op *Operation
	t  *MagicTable
}

// Reconfigure sends explicit ConfigTags data to the underlying MagicTable in
// order to override the reflected structure's tags
func (ot *OperationTable) Reconfigure(conf ConfigTags) {
	ot.t.Configure(conf)
}

// Select simply instantiates a Select instance with the OperationTable set up
// for it to use for gathering fields and running the query
func (ot *OperationTable) Select() Select {
	return NewSelect(ot)
}

// Save determines if an INSERT or UPDATE is necessary (primary key of 0 means
// INSERT here), generates the SQL and arguments, and runs the Exec call on the
// database.  Behavior may be unpredictable if a MagicTable was manually
// registered with a structure of a different type than obj.
func (ot *OperationTable) Save(obj interface{}) *Result {
	// Check for object's primary key field being zero
	var rVal = reflect.ValueOf(obj).Elem()
	var pkValField = rVal.FieldByName(ot.t.primaryKey.Field.Name)

	if pkValField.Interface() == reflect.Zero(pkValField.Type()).Interface() {
		var res = ot.op.Exec(ot.t.InsertSQL(), ot.t.InsertArgs(obj)...)
		switch pkValField.Type().Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			pkValField.SetInt(res.LastInsertId())
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			pkValField.SetUint(uint64(res.LastInsertId()))
		}
		return res
	}

	return ot.op.Exec(ot.t.UpdateSQL(), ot.t.UpdateArgs(obj)...)
}

// Insert forces an insert, ignoring any primary key tagging.  Note that
// directly inserting via this method will *not* auto-set the primary key to
// the last insert id.
//
// TODO: make the DB querying backend more flexible so it doesn't care about
// tagging for generating SQL and arg lists, instead relying on field and
// column name mappings
func (ot *OperationTable) Insert(obj interface{}) *Result {
	var pkField = ot.t.primaryKey
	ot.t.primaryKey = nil
	var res = ot.op.Exec(ot.t.InsertSQL(), ot.t.InsertArgs(obj)...)
	ot.t.primaryKey = pkField

	return res
}
<|endoftext|>


<commit_before>package options

import (
	"fmt"
	"github.com/mesos/mesos-go"
	"github.com/satori/go.uuid"
	"strconv"
)

type TaskID struct {
	ID *mesos.TaskID
}

func NewTaskID() *TaskID {
	return &TaskID{
		ID: &mesos.TaskID{
			Value: uuid.NewV4().String(),
		},
	}
}

func (o *TaskID) String() string {
	return o.ID.Value
}

func (o *TaskID) Set(name string) error {
	o.ID.Value = name
	return nil
}

type States []*mesos.TaskState

func NewStates() States {
	return States{mesos.TASK_RUNNING.Enum()}
}

func (o *States) String() string {
	return fmt.Sprintf("%v", *o)
}

func (o *States) Set(name string) error {
	v, ok := mesos.TaskState_value[name]
	if !ok {
		return fmt.Errorf("Invalid state %s", name)
	}
	*o = append(*o, mesos.TaskState(v).Enum())
	return nil
}

func (o *States) Clear() {
	*o = []*mesos.TaskState{}
}

type ScalarResources struct {
	Name      string
	Resources mesos.Resources
}

func NewScalarResources(name string, resources mesos.Resources) *ScalarResources {
	return &ScalarResources{
		Name:      name,
		Resources: resources,
	}
}

func (o *ScalarResources) String() string {
	var value float64
	if scalar := o.Resources.SumScalars(mesos.NamedResources(o.Name)); scalar != nil {
		value = scalar.Value
	}
	return fmt.Sprintf("%.2f", value)
}

func (o *ScalarResources) Set(v string) error {
	value, err := strconv.ParseFloat(v, 64)
	if err != nil {
		return err
	}
	o.Resources = append(o.Resources, mesos.Resource{
		Name:   o.Name,
		Type:   mesos.SCALAR.Enum(),
		Scalar: &mesos.Value_Scalar{Value: value},
	})
	return nil
}
<commit_msg>remove options module<commit_after><|endoftext|>


<commit_before>package gossh

import (
  "time"
  "github.com/dcapwell/gossh/workpool"
)

type Options struct {
  Concurrent  int
  User        string
  Identity    string
  Options     map[string]string
}

type SshResponse struct {
  Code      int
  Stdout    string
  Stderr    string
}

type SshResponseContext struct {
  Hostname        string
  Duration        time.Duration
  Response        SshResponse
}

type SshResponses struct {
  Responses     []SshResponseContext
}

type Ssh interface {
  Run(hosts []string, cmd string, options Options) (SshResponses, error)
}

type sshImpl struct {
  pool      workpool.WorkPool
}

func (s *sshImpl) Run(hosts []string, cmd string, options Options) (SshResponses, error) {
  // find how many hosts to run concurrently
  // create new bounded worker pool
  // create ssh worker per host, send to pool
  // wait for completion
  return SshResponses{}, nil
}

func NewSsh() Ssh {
  pool, _ := workpool.NewWorkPoolWithMax(40)
  // error is only returned if max is not positive, so can ignore it
  return &sshImpl{pool: pool}
}

<commit_msg>working on impl run<commit_after>package gossh

import (
  "time"
  "github.com/dcapwell/gossh/workpool"
)

const (
  MIN_POOL_SIZE = 1
  MAX_POOL_SIZE = 100
)

type Options struct {
  Concurrent  int
  User        string
  Identity    string
  Options     map[string]string
}

type SshResponse struct {
  Code      int
  Stdout    string
  Stderr    string
}

type SshResponseContext struct {
  Hostname        string
  Duration        time.Duration
  Response        SshResponse
}

type SshResponses struct {
  Responses     []SshResponseContext
}

type Ssh interface {
  Run(hosts []string, cmd string, options Options) (SshResponses, error)
}

type sshImpl struct {
  pool      workpool.WorkPool
}

func (s *sshImpl) Run(hosts []string, cmd string, options Options) (SshResponses, error) {
  // find how many hosts to run concurrently
  /*
  conc := MAX_POOL_SIZE
  if options.Concurrent > 0 {
    conc = options.Concurrent
  }
  */
  // create ssh worker per host, send to pool
  // wait for completion
  return SshResponses{}, nil
}

func NewSsh() Ssh {
  pool, _ := workpool.NewWorkPoolWithMax(MAX_POOL_SIZE)
  // error is only returned if max is not positive, so can ignore it
  return &sshImpl{pool: pool}
}

<|endoftext|>


<commit_before>// Package autoupdate provides Lantern with special tools to autoupdate itself
// with minimal effort.
package autoupdate

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

	"github.com/blang/semver"
	"github.com/getlantern/go-update"
	"github.com/getlantern/go-update/check"
	"github.com/getlantern/golog"
)

var (
	log                  = golog.LoggerFor("autoupdate")
	defaultCheckInterval = time.Hour * 4
	defaultHTTPClient    = &http.Client{}
)

type Config struct {
	// CurrentVersion: the current version of the program, must be in the form
	// X.Y.Z
	CurrentVersion string

	version semver.Version

	// URL: the url at which to check for updates
	URL string

	// PublicKey: the public key against which to check the signature of any
	// received updates.
	PublicKey []byte

	// CheckInterval: the interval at which to check for updates, defaults to
	// 4 hours.
	CheckInterval time.Duration

	// HTTPClient: (optional), an http.Client to use when checking for updates
	HTTPClient *http.Client
}

// Apply applies the next available update whenever it is available, blocking
// until the next update has been applied. If ApplyNext returns without an
// error, that means that the current program's executable has been udpated in
// place and you may want to restart. If ApplyNext returns an error, that means
// that an unrecoverable error has occurred and we can't continue checking for
// updates.
func ApplyNext(cfg *Config) error {
	// Parse the semantic version
	var err error
	cfg.version, err = semver.Parse(cfg.CurrentVersion)
	if err != nil {
		return fmt.Errorf("Bad version string: %v", err)
	}
	if cfg.CheckInterval == 0 {
		cfg.CheckInterval = defaultCheckInterval
		log.Debugf("Defaulted CheckInterval to %v", cfg.CheckInterval)
	}
	if cfg.HTTPClient == nil {
		cfg.HTTPClient = defaultHTTPClient
		log.Debug("Defaulted HTTPClient")
	}
	update.HTTPClient = cfg.HTTPClient

	return cfg.loop()
}

func (cfg *Config) loop() error {
	for {
		res, err := cfg.check()

		if err != nil {
			log.Errorf("Problem checking for update: %v", err)
		} else {
			if res == nil {
				log.Debug("No update available")
			} else if isNewerVersion(cfg.version, res.Version) {
				log.Debugf("Attempting to update to %s.", res.Version)
				err, errRecover := res.Update()
				if errRecover != nil {
					// This should never happen, if this ever happens it means bad news such as
					// a missing executable file.
					return fmt.Errorf("Failed to recover from failed update attempt: %v\n", errRecover)
				}
				if err == nil {
					log.Debugf("Patching succeeded!")
					return nil
				}
				log.Errorf("Patching failed: %q\n", err)
			} else {
				log.Debug("Already up to date.")
			}
		}

		time.Sleep(cfg.CheckInterval)
	}
}

func isNewerVersion(version semver.Version, newer string) bool {
	nv, err := semver.Parse(newer)
	if err != nil {
		log.Errorf("Bad version string on update: %v", err)
		return false
	}
	return nv.GT(version)
}

func checkUpdate(currentVersion, URL string, publicKey []byte) (res *check.Result, err error) {
	var up *update.Update

	param := check.Params{
		AppVersion: currentVersion,
	}

	up = update.New().ApplyPatch(update.PATCHTYPE_BSDIFF)

	if _, err = up.VerifySignatureWithPEM(publicKey); err != nil {
		return nil, fmt.Errorf("Problem verifying signature of update: %v", err)
	}

	if res, err = param.CheckForUpdate(URL, up); err != nil {
		if err == check.NoUpdateAvailable {
			return nil, nil
		}
		return nil, fmt.Errorf("Problem fetching update: %v", err)
	}

	return res, nil
}

// check uses go-update to look for updates.
func (cfg *Config) check() (res *check.Result, err error) {
	return checkUpdate(cfg.CurrentVersion, cfg.URL, cfg.PublicKey)
}
<commit_msg>Update error message<commit_after>// Package autoupdate provides Lantern with special tools to autoupdate itself
// with minimal effort.
package autoupdate

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

	"github.com/blang/semver"
	"github.com/getlantern/go-update"
	"github.com/getlantern/go-update/check"
	"github.com/getlantern/golog"
)

var (
	log                  = golog.LoggerFor("autoupdate")
	defaultCheckInterval = time.Hour * 4
	defaultHTTPClient    = &http.Client{}
)

type Config struct {
	// CurrentVersion: the current version of the program, must be in the form
	// X.Y.Z
	CurrentVersion string

	version semver.Version

	// URL: the url at which to check for updates
	URL string

	// PublicKey: the public key against which to check the signature of any
	// received updates.
	PublicKey []byte

	// CheckInterval: the interval at which to check for updates, defaults to
	// 4 hours.
	CheckInterval time.Duration

	// HTTPClient: (optional), an http.Client to use when checking for updates
	HTTPClient *http.Client
}

// Apply applies the next available update whenever it is available, blocking
// until the next update has been applied. If ApplyNext returns without an
// error, that means that the current program's executable has been udpated in
// place and you may want to restart. If ApplyNext returns an error, that means
// that an unrecoverable error has occurred and we can't continue checking for
// updates.
func ApplyNext(cfg *Config) error {
	// Parse the semantic version
	var err error
	cfg.version, err = semver.Parse(cfg.CurrentVersion)
	if err != nil {
		return fmt.Errorf("Bad version string: %v", err)
	}
	if cfg.CheckInterval == 0 {
		cfg.CheckInterval = defaultCheckInterval
		log.Debugf("Defaulted CheckInterval to %v", cfg.CheckInterval)
	}
	if cfg.HTTPClient == nil {
		cfg.HTTPClient = defaultHTTPClient
		log.Debug("Defaulted HTTPClient")
	}
	update.HTTPClient = cfg.HTTPClient

	return cfg.loop()
}

func (cfg *Config) loop() error {
	for {
		res, err := cfg.check()

		if err != nil {
			log.Errorf("Problem checking for update: %v", err)
		} else {
			if res == nil {
				log.Debug("No update available")
			} else if isNewerVersion(cfg.version, res.Version) {
				log.Debugf("Attempting to update to %s.", res.Version)
				err, errRecover := res.Update()
				if errRecover != nil {
					// This should never happen, if this ever happens it means bad news such as
					// a missing executable file.
					return fmt.Errorf("Failed to recover from failed update attempt: %v\n", errRecover)
				}
				if err == nil {
					log.Debugf("Patching succeeded!")
					return nil
				}
				log.Errorf("Patching failed: %q\n", err)
			} else {
				log.Debug("Already up to date.")
			}
		}

		time.Sleep(cfg.CheckInterval)
	}
}

func isNewerVersion(version semver.Version, newer string) bool {
	nv, err := semver.Parse(newer)
	if err != nil {
		log.Errorf("Bad version string on update: %v", err)
		return false
	}
	return nv.GT(version)
}

func checkUpdate(currentVersion, URL string, publicKey []byte) (res *check.Result, err error) {
	var up *update.Update

	param := check.Params{
		AppVersion: currentVersion,
	}

	up = update.New().ApplyPatch(update.PATCHTYPE_BSDIFF)

	if _, err = up.VerifySignatureWithPEM(publicKey); err != nil {
		return nil, fmt.Errorf("Problem verifying signature of update: %v", err)
	}

	if res, err = param.CheckForUpdate(URL, up); err != nil {
		if err == check.ErrNoUpdateAvailable {
			return nil, nil
		}
		return nil, fmt.Errorf("Problem fetching update: %v", err)
	}

	return res, nil
}

// check uses go-update to look for updates.
func (cfg *Config) check() (res *check.Result, err error) {
	return checkUpdate(cfg.CurrentVersion, cfg.URL, cfg.PublicKey)
}
<|endoftext|>


<commit_before>
package gotomic

import (
	"sync/atomic"
	"fmt"
	"unsafe"
	"sort"
)

const (
	UNDECIDED = iota
	READ_CHECK
	SUCCESSFUL
	FAILED
)

var nextTransactionNumber uint64 = 0

type Clonable interface {
	Clone() Clonable
}

type Handle struct {
	/*
	 Will point to a version.
	 */
	unsafe.Pointer
}
func NewHandle(c Clonable) *Handle {
	return &Handle{unsafe.Pointer(&version{0, nil, c})}
}
func (self *Handle) getVersion() *version {
	return (*version)(atomic.LoadPointer(&self.Pointer))
}
func (self *Handle) replace(old, neu *version) bool {
	return atomic.CompareAndSwapPointer(&self.Pointer, unsafe.Pointer(old), unsafe.Pointer(neu))
}

type Handles []*Handle
func (self Handles) Len() int {
	return len(self)
}
func (self Handles) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}
func (self Handles) Less(i, j int) bool {
	return uintptr(unsafe.Pointer(self[i])) < uintptr(unsafe.Pointer(self[j]))
}

type version struct {
	/*
	 The number of the transaction that created this version.
	 */
	transactionNumber uint64
	/*
	 The transaction (or nil) having locked this version.
	 */
	lockedBy *Transaction
	/*
	The content in this version.
	 */
	content Clonable
}
func (self *version) clone() *version {
	newVersion := *self
	newVersion.content = self.content.Clone()
	return &newVersion
}

type snapshot struct {
	old *version
	neu *version
}

type Transaction struct {
	/*
	 Steadily incrementing number for each created transaction.
	 */
	id uint64
	status int32
	readHandles map[*Handle]*snapshot
	writeHandles map[*Handle]*snapshot
}
func NewTransaction() *Transaction {
	return &Transaction{
		atomic.AddUint64(&nextTransactionNumber, 1),
		UNDECIDED,
		make(map[*Handle]*snapshot),
		make(map[*Handle]*snapshot),
	}
}
func (self *Transaction) getStatus() int32 {
	return atomic.LoadInt32(&self.status)
}
func (self *Transaction) objRead(h *Handle) (rval *version, err error) {
	version := h.getVersion()
	if version.transactionNumber > self.id {
		return nil, fmt.Errorf("%v has changed", h.getVersion().content)
	}
	if version.lockedBy == nil {
		return version, nil
	}
	other := version.lockedBy
	if other.getStatus() == READ_CHECK {
		if self.getStatus() != READ_CHECK || self.id > other.id {
			other.Commit()
		} else {
			other.Abort()
		}
	}
	if other.getStatus() == SUCCESSFUL {
		return other.writeHandles[h].neu, nil
	}
	return other.writeHandles[h].old, nil
}
func (self *Transaction) sortedWrites() []*Handle {
	var rval Handles
	for handle, _ := range self.writeHandles {
		rval = append(rval, handle)
	}
	sort.Sort(rval)
	return rval
}
func (self *Transaction) release() {
	stat := self.getStatus()
	for _, handle := range self.sortedWrites() {
		current := handle.getVersion()
		if current.lockedBy == self {
			snapshot := self.writeHandles[handle]
			wanted := snapshot.old
			if stat == SUCCESSFUL {
				wanted = snapshot.neu
			}
			handle.replace(current, wanted)
		}
	}
}
func (self *Transaction) acquire() bool {
 	for _, handle := range self.sortedWrites() {
		for {
			snapshot, _ := self.writeHandles[handle]
			lockedVersion := snapshot.old.clone()
			lockedVersion.lockedBy = self
			if handle.replace(snapshot.old, lockedVersion) {
				break
			}
			current := handle.getVersion()
			if current.lockedBy == nil {
				return false
			}
			if current.lockedBy == self {
				break
			}
			current.lockedBy.Commit()
		}
	}
	return true
}
func (self *Transaction) readCheck() bool {
	for handle, snapshot := range self.readHandles {
		if handle.getVersion() != snapshot.old {
			return false
		}
	}
	return true
}
func (self *Transaction) Commit() bool {
	if !self.acquire() {
		self.Abort()
		return false
	}
	atomic.CompareAndSwapInt32(&self.status, UNDECIDED, READ_CHECK)
	if !self.readCheck() {
		self.Abort()
		return false
	}
	current := self.getStatus()
	for {
		if current == FAILED || current == SUCCESSFUL {
			break
		}
		atomic.CompareAndSwapInt32(&self.status, current, SUCCESSFUL)
		current = self.getStatus()
	}
	self.release()
	return self.getStatus() == SUCCESSFUL;
}
func (self *Transaction) Abort() {
	for {
		current := self.getStatus()
		if current == FAILED {
			return
		}
		atomic.CompareAndSwapInt32(&self.status, current, FAILED)
	}
	self.release()
}
func (self *Transaction) Read(h *Handle) (rval Clonable, err error)  {
	if snapshot, ok := self.readHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	if snapshot, ok := self.writeHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	oldVersion, err := self.objRead(h)
	if err != nil {
		return nil, err
	}
	newVersion := oldVersion.clone()
	self.readHandles[h] = &snapshot{oldVersion, newVersion}
	return newVersion.content, nil
}
func (self *Transaction) Write(h *Handle) (rval Clonable, err error) {
	if snapshot, ok := self.writeHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	if snapshot, ok := self.readHandles[h]; ok {
		delete(self.readHandles, h)
		self.writeHandles[h] = snapshot
		return snapshot.neu.content, nil
	}
	oldVersion, err := self.objRead(h)
	if err != nil {
		return nil, err
	}
	newVersion := oldVersion.clone()
	self.writeHandles[h] = &snapshot{oldVersion, newVersion}
	return newVersion.content, nil
}
<commit_msg>more error checking<commit_after>
package gotomic

import (
	"sync/atomic"
	"fmt"
	"unsafe"
	"sort"
)

const (
	UNDECIDED = iota
	READ_CHECK
	SUCCESSFUL
	FAILED
)

var nextTransactionNumber uint64 = 0

type Clonable interface {
	Clone() Clonable
}

type Handle struct {
	/*
	 Will point to a version.
	 */
	unsafe.Pointer
}
func NewHandle(c Clonable) *Handle {
	return &Handle{unsafe.Pointer(&version{0, nil, c})}
}
func (self *Handle) getVersion() *version {
	return (*version)(atomic.LoadPointer(&self.Pointer))
}
func (self *Handle) replace(old, neu *version) bool {
	return atomic.CompareAndSwapPointer(&self.Pointer, unsafe.Pointer(old), unsafe.Pointer(neu))
}

type Handles []*Handle
func (self Handles) Len() int {
	return len(self)
}
func (self Handles) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}
func (self Handles) Less(i, j int) bool {
	return uintptr(unsafe.Pointer(self[i])) < uintptr(unsafe.Pointer(self[j]))
}

type version struct {
	/*
	 The number of the transaction that created this version.
	 */
	transactionNumber uint64
	/*
	 The transaction (or nil) having locked this version.
	 */
	lockedBy *Transaction
	/*
	The content in this version.
	 */
	content Clonable
}
func (self *version) clone() *version {
	newVersion := *self
	newVersion.content = self.content.Clone()
	return &newVersion
}

type snapshot struct {
	old *version
	neu *version
}

type Transaction struct {
	/*
	 Steadily incrementing number for each created transaction.
	 */
	id uint64
	status int32
	readHandles map[*Handle]*snapshot
	writeHandles map[*Handle]*snapshot
}
func NewTransaction() *Transaction {
	return &Transaction{
		atomic.AddUint64(&nextTransactionNumber, 1),
		UNDECIDED,
		make(map[*Handle]*snapshot),
		make(map[*Handle]*snapshot),
	}
}
func (self *Transaction) getStatus() int32 {
	return atomic.LoadInt32(&self.status)
}
func (self *Transaction) objRead(h *Handle) (rval *version, err error) {
	version := h.getVersion()
	if version.transactionNumber > self.id {
		return nil, fmt.Errorf("%v has changed", h.getVersion().content)
	}
	if version.lockedBy == nil {
		return version, nil
	}
	other := version.lockedBy
	if other.getStatus() == READ_CHECK {
		if self.getStatus() != READ_CHECK || self.id > other.id {
			other.Commit()
		} else {
			other.Abort()
		}
	}
	if other.getStatus() == SUCCESSFUL {
		return other.writeHandles[h].neu, nil
	}
	return other.writeHandles[h].old, nil
}
func (self *Transaction) sortedWrites() []*Handle {
	var rval Handles
	for handle, _ := range self.writeHandles {
		rval = append(rval, handle)
	}
	sort.Sort(rval)
	return rval
}
func (self *Transaction) release() {
	stat := self.getStatus()
	for _, handle := range self.sortedWrites() {
		current := handle.getVersion()
		if current.lockedBy == self {
			snapshot := self.writeHandles[handle]
			wanted := snapshot.old
			if stat == SUCCESSFUL {
				wanted = snapshot.neu
			}
			handle.replace(current, wanted)
		}
	}
}
func (self *Transaction) acquire() bool {
 	for _, handle := range self.sortedWrites() {
		for {
			snapshot, _ := self.writeHandles[handle]
			lockedVersion := snapshot.old.clone()
			lockedVersion.lockedBy = self
			if handle.replace(snapshot.old, lockedVersion) {
				break
			}
			current := handle.getVersion()
			if current.lockedBy == nil {
				return false
			}
			if current.lockedBy == self {
				break
			}
			current.lockedBy.Commit()
		}
	}
	return true
}
func (self *Transaction) readCheck() bool {
	for handle, snapshot := range self.readHandles {
		if handle.getVersion() != snapshot.old {
			return false
		}
	}
	return true
}
func (self *Transaction) Commit() bool {
	if !self.acquire() {
		self.Abort()
		return false
	}
	atomic.CompareAndSwapInt32(&self.status, UNDECIDED, READ_CHECK)
	if !self.readCheck() {
		self.Abort()
		return false
	}
	current := self.getStatus()
	for {
		if current == FAILED || current == SUCCESSFUL {
			break
		}
		atomic.CompareAndSwapInt32(&self.status, current, SUCCESSFUL)
		current = self.getStatus()
	}
	self.release()
	return self.getStatus() == SUCCESSFUL;
}
func (self *Transaction) Abort() {
	for {
		current := self.getStatus()
		if current == FAILED {
			return
		}
		atomic.CompareAndSwapInt32(&self.status, current, FAILED)
	}
	self.release()
}
func (self *Transaction) Read(h *Handle) (rval Clonable, err error)  {
	if self.getStatus() != UNDECIDED {
		return nil, fmt.Errorf("%v is not UNDECIDED", self)
	}
	if snapshot, ok := self.readHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	if snapshot, ok := self.writeHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	oldVersion, err := self.objRead(h)
	if err != nil {
		return nil, err
	}
	newVersion := oldVersion.clone()
	self.readHandles[h] = &snapshot{oldVersion, newVersion}
	return newVersion.content, nil
}
func (self *Transaction) Write(h *Handle) (rval Clonable, err error) {
	if self.getStatus() != UNDECIDED {
		return nil, fmt.Errorf("%v is not UNDECIDED", self)
	}
	if snapshot, ok := self.writeHandles[h]; ok {
		return snapshot.neu.content, nil
	}
	if snapshot, ok := self.readHandles[h]; ok {
		delete(self.readHandles, h)
		self.writeHandles[h] = snapshot
		return snapshot.neu.content, nil
	}
	oldVersion, err := self.objRead(h)
	if err != nil {
		return nil, err
	}
	newVersion := oldVersion.clone()
	self.writeHandles[h] = &snapshot{oldVersion, newVersion}
	return newVersion.content, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package id3v2

import (
	"bufio"
	"errors"
	"io"
	"os"
)

var ErrNoFile = errors.New("tag was not initialized with file")

// Tag stores all information about opened tag.
type Tag struct {
	frames    map[string]Framer
	sequences map[string]*sequence

	defaultEncoding Encoding
	reader          io.Reader
	originalSize    int64
	version         byte
}

// AddFrame adds f to tag with appropriate id. If id is "" or f is nil,
// AddFrame will not add it to tag.
//
// If you want to add attached picture, comment or unsynchronised lyrics/text
// transcription frames, better use AddAttachedPicture, AddCommentFrame
// or AddUnsynchronisedLyricsFrame methods respectively.
func (tag *Tag) AddFrame(id string, f Framer) {
	if id == "" || f == nil {
		return
	}

	if mustFrameBeInSequence(id) {
		if tag.sequences[id] == nil {
			tag.sequences[id] = getSequence()
		}
		tag.sequences[id].AddFrame(f)
	} else {
		tag.frames[id] = f
	}
}

// AddAttachedPicture adds a picture frame to tag.
func (tag *Tag) AddAttachedPicture(pf PictureFrame) {
	id := tag.CommonID("Attached picture")
	tag.AddFrame(id, pf)
}

// AddCommentFrame adds a comment frame to tag.
func (tag *Tag) AddCommentFrame(cf CommentFrame) {
	id := tag.CommonID("Comments")
	tag.AddFrame(id, cf)
}

// AddUnsynchronisedLyricsFrame adds an unsynchronised lyrics/text frame
// to tag.
func (tag *Tag) AddUnsynchronisedLyricsFrame(uslf UnsynchronisedLyricsFrame) {
	id := tag.CommonID("Unsynchronised lyrics/text transcription")
	tag.AddFrame(id, uslf)
}

// CommonID returns ID3v2.3 or ID3v2.4 (in appropriate to version of Tag) frame ID
// from given description.
// For example, CommonID("Language") will return "TLAN".
// If it can't find the ID with given description, it returns the description.
//
// All descriptions you can find in file common_ids.go
// or in id3 documentation (for fourth version: http://id3.org/id3v2.4.0-frames;
// for third version: http://id3.org/id3v2.3.0#Declared_ID3v2_frames).
func (tag *Tag) CommonID(description string) string {
	var ids map[string]string
	if tag.version == 3 {
		ids = V23CommonIDs
	} else {
		ids = V24CommonIDs
	}
	if id, ok := ids[description]; ok {
		return id
	}
	return description
}

// AllFrames returns map, that contains all frames in tag, that could be parsed.
// The key of this map is an ID of frame and value is an array of frames.
func (tag *Tag) AllFrames() map[string][]Framer {
	frames := make(map[string][]Framer)

	for id, f := range tag.frames {
		frames[id] = []Framer{f}
	}
	for id, sequence := range tag.sequences {
		frames[id] = sequence.Frames()
	}

	return frames
}

// DeleteAllFrames deletes all frames in tag.
func (tag *Tag) DeleteAllFrames() {
	if tag.frames == nil || len(tag.frames) > 0 {
		tag.frames = make(map[string]Framer)
	}
	if tag.sequences == nil || len(tag.sequences) > 0 {
		for _, s := range tag.sequences {
			putSequence(s)
		}
		tag.sequences = make(map[string]*sequence)
	}
}

// DeleteFrames deletes frames in tag with given id.
func (tag *Tag) DeleteFrames(id string) {
	delete(tag.frames, id)
	if s, ok := tag.sequences[id]; ok {
		putSequence(s)
		delete(tag.sequences, id)
	}
}

// Reset deletes all frames in tag and parses rd considering opts.
func (tag *Tag) Reset(rd io.Reader, opts Options) error {
	tag.DeleteAllFrames()
	return tag.parse(rd, opts)
}

// GetFrames returns frames with corresponding id.
// It returns nil if there is no frames with given id.
func (tag *Tag) GetFrames(id string) []Framer {
	if f, exists := tag.frames[id]; exists {
		return []Framer{f}
	} else if s, exists := tag.sequences[id]; exists {
		return s.Frames()
	}
	return nil
}

// GetLastFrame returns last frame from slice, that is returned from GetFrames function.
// GetLastFrame is suitable for frames, that can be only one in whole tag.
// For example, for text frames.
func (tag *Tag) GetLastFrame(id string) Framer {
	// Avoid an allocation of slice in GetFrames,
	// if there is anyway one frame.
	if f, exists := tag.frames[id]; exists {
		return f
	}

	fs := tag.GetFrames(id)
	if len(fs) == 0 {
		return nil
	}
	return fs[len(fs)-1]
}

// GetTextFrame returns text frame with corresponding id.
func (tag *Tag) GetTextFrame(id string) TextFrame {
	f := tag.GetLastFrame(id)
	if f == nil {
		return TextFrame{}
	}
	tf := f.(TextFrame)
	return tf
}

// Count returns the number of frames in tag.
func (tag *Tag) Count() int {
	n := len(tag.frames)
	for _, s := range tag.sequences {
		n += s.Count()
	}
	return n
}

// HasFrames checks if there is at least one frame in tag.
// It's much faster than tag.Count() > 0.
func (tag *Tag) HasFrames() bool {
	return len(tag.frames) > 0 || len(tag.sequences) > 0
}

func (tag *Tag) Title() string {
	f := tag.GetTextFrame(tag.CommonID("Title"))
	return f.Text
}

func (tag *Tag) SetTitle(title string) {
	tag.AddFrame(tag.CommonID("Title"), TextFrame{Encoding: tag.defaultEncoding, Text: title})
}

func (tag *Tag) Artist() string {
	f := tag.GetTextFrame(tag.CommonID("Artist"))
	return f.Text
}

func (tag *Tag) SetArtist(artist string) {
	tag.AddFrame(tag.CommonID("Artist"), TextFrame{Encoding: tag.defaultEncoding, Text: artist})
}

func (tag *Tag) Album() string {
	f := tag.GetTextFrame(tag.CommonID("Album/Movie/Show title"))
	return f.Text
}

func (tag *Tag) SetAlbum(album string) {
	tag.AddFrame(tag.CommonID("Album/Movie/Show title"), TextFrame{Encoding: tag.defaultEncoding, Text: album})
}

func (tag *Tag) Year() string {
	f := tag.GetTextFrame(tag.CommonID("Year"))
	return f.Text
}

func (tag *Tag) SetYear(year string) {
	tag.AddFrame(tag.CommonID("Year"), TextFrame{Encoding: tag.defaultEncoding, Text: year})
}

func (tag *Tag) Genre() string {
	f := tag.GetTextFrame(tag.CommonID("Content type"))
	return f.Text
}

func (tag *Tag) SetGenre(genre string) {
	tag.AddFrame(tag.CommonID("Content type"), TextFrame{Encoding: tag.defaultEncoding, Text: genre})
}

// iterateOverAllFrames iterates over every single frame in tag and calls
// f for them. It consumps no memory at all, unlike the tag.AllFrames().
// It returns error only if f returns error.
func (tag *Tag) iterateOverAllFrames(f func(id string, frame Framer) error) error {
	for id, frame := range tag.frames {
		if err := f(id, frame); err != nil {
			return err
		}
	}
	for id, sequence := range tag.sequences {
		for _, frame := range sequence.Frames() {
			if err := f(id, frame); err != nil {
				return err
			}
		}
	}
	return nil
}

// Size returns the size of tag (tag header + size of all frames) in bytes.
func (tag *Tag) Size() int {
	if !tag.HasFrames() {
		return 0
	}

	var n int
	n += tagHeaderSize // Add the size of tag header
	tag.iterateOverAllFrames(func(id string, f Framer) error {
		n += frameHeaderSize + f.Size() // Add the whole frame size
		return nil
	})

	return n
}

// Version returns current ID3v2 version of tag.
func (tag *Tag) Version() byte {
	return tag.version
}

// SetVersion sets given ID3v2 version to tag.
// If version is less than 3 or greater than 4, then this method will do nothing.
// If tag has some frames, which are deprecated or changed in given version,
// then to your notice you can delete, change or just stay them.
func (tag *Tag) SetVersion(version byte) {
	if version < 3 || version > 4 {
		return
	}
	tag.version = version
}

// Save writes tag to the file, if tag was opened with a file.
// If there are no frames in tag, Save will write
// only music part without any ID3v2 information.
// If tag was initiliazed not with file, it returns ErrNoFile.
func (tag *Tag) Save() error {
	file, ok := tag.reader.(*os.File)
	if !ok {
		return ErrNoFile
	}

	// Get original file mode.
	originalFile := file
	originalStat, err := originalFile.Stat()
	if err != nil {
		return err
	}

	// Create a temp file for mp3 file, which will contain new tag.
	name := file.Name() + "-id3v2"
	newFile, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, originalStat.Mode())
	if err != nil {
		return err
	}

	// Make sure we clean up the temp file if it's still around.
	defer os.Remove(newFile.Name())

	// Write tag in new file.
	tagSize, err := tag.WriteTo(newFile)
	if err != nil {
		return err
	}

	// Seek to a music part of original file.
	if _, err = originalFile.Seek(tag.originalSize, os.SEEK_SET); err != nil {
		return err
	}

	// Write to new file the music part.
	buf := getByteSlice(32 * 1024)
	defer putByteSlice(buf)
	if _, err = io.CopyBuffer(newFile, originalFile, buf); err != nil {
		return err
	}

	// Close files to allow replacing.
	newFile.Close()
	originalFile.Close()

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

	// Set tag.reader to new file with original name.
	tag.reader, err = os.Open(originalFile.Name())
	if err != nil {
		return err
	}

	// Set tag.originalSize to new frames size.
	if tagSize > tagHeaderSize {
		tag.originalSize = tagSize - tagHeaderSize
	} else {
		tag.originalSize = 0
	}

	return nil
}

// WriteTo writes whole tag in w if there is at least one frame.
// It returns the number of bytes written and error during the write.
// It returns nil as error if the write was successful.
func (tag *Tag) WriteTo(w io.Writer) (n int64, err error) {
	if w == nil {
		return 0, errors.New("w is nil")
	}

	// Count size of frames.
	framesSize := tag.Size() - tagHeaderSize
	if framesSize <= 0 {
		return 0, nil
	}

	// Write tag header.
	bw := getBufioWriter(w)
	defer putBufioWriter(bw)
	if err := writeTagHeader(bw, uint(framesSize), tag.version); err != nil {
		return 0, err
	}
	n += tagHeaderSize

	// Write frames.
	err = tag.iterateOverAllFrames(func(id string, f Framer) error {
		nn, err := writeFrame(bw, id, f)
		n += nn
		return err
	})
	if err != nil {
		return n, err
	}

	return n, bw.Flush()
}

func writeFrame(bw *bufio.Writer, id string, frame Framer) (int64, error) {
	if err := writeFrameHeader(bw, id, uint(frame.Size())); err != nil {
		return 0, err
	}

	frameSize, err := frame.WriteTo(bw)
	return frameHeaderSize + frameSize, err
}

func writeFrameHeader(bw *bufio.Writer, id string, frameSize uint) error {
	// ID
	if _, err := bw.WriteString(id); err != nil {
		return err
	}

	// Size
	if err := writeBytesSize(bw, frameSize); err != nil {
		return err
	}

	// Flags
	if _, err := bw.Write([]byte{0, 0}); err != nil {
		return err
	}
	return nil
}

// Close closes tag's file, if tag was opened with a file.
// If tag was initiliazed not with file, it returns ErrNoFile.
func (tag *Tag) Close() error {
	file, ok := tag.reader.(*os.File)
	if !ok {
		return ErrNoFile
	}
	return file.Close()
}
<commit_msg>Prevent removing file in Save if it succesfully renamed<commit_after>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package id3v2

import (
	"bufio"
	"errors"
	"io"
	"os"
)

var ErrNoFile = errors.New("tag was not initialized with file")

// Tag stores all information about opened tag.
type Tag struct {
	frames    map[string]Framer
	sequences map[string]*sequence

	defaultEncoding Encoding
	reader          io.Reader
	originalSize    int64
	version         byte
}

// AddFrame adds f to tag with appropriate id. If id is "" or f is nil,
// AddFrame will not add it to tag.
//
// If you want to add attached picture, comment or unsynchronised lyrics/text
// transcription frames, better use AddAttachedPicture, AddCommentFrame
// or AddUnsynchronisedLyricsFrame methods respectively.
func (tag *Tag) AddFrame(id string, f Framer) {
	if id == "" || f == nil {
		return
	}

	if mustFrameBeInSequence(id) {
		if tag.sequences[id] == nil {
			tag.sequences[id] = getSequence()
		}
		tag.sequences[id].AddFrame(f)
	} else {
		tag.frames[id] = f
	}
}

// AddAttachedPicture adds a picture frame to tag.
func (tag *Tag) AddAttachedPicture(pf PictureFrame) {
	id := tag.CommonID("Attached picture")
	tag.AddFrame(id, pf)
}

// AddCommentFrame adds a comment frame to tag.
func (tag *Tag) AddCommentFrame(cf CommentFrame) {
	id := tag.CommonID("Comments")
	tag.AddFrame(id, cf)
}

// AddUnsynchronisedLyricsFrame adds an unsynchronised lyrics/text frame
// to tag.
func (tag *Tag) AddUnsynchronisedLyricsFrame(uslf UnsynchronisedLyricsFrame) {
	id := tag.CommonID("Unsynchronised lyrics/text transcription")
	tag.AddFrame(id, uslf)
}

// CommonID returns ID3v2.3 or ID3v2.4 (in appropriate to version of Tag) frame ID
// from given description.
// For example, CommonID("Language") will return "TLAN".
// If it can't find the ID with given description, it returns the description.
//
// All descriptions you can find in file common_ids.go
// or in id3 documentation (for fourth version: http://id3.org/id3v2.4.0-frames;
// for third version: http://id3.org/id3v2.3.0#Declared_ID3v2_frames).
func (tag *Tag) CommonID(description string) string {
	var ids map[string]string
	if tag.version == 3 {
		ids = V23CommonIDs
	} else {
		ids = V24CommonIDs
	}
	if id, ok := ids[description]; ok {
		return id
	}
	return description
}

// AllFrames returns map, that contains all frames in tag, that could be parsed.
// The key of this map is an ID of frame and value is an array of frames.
func (tag *Tag) AllFrames() map[string][]Framer {
	frames := make(map[string][]Framer)

	for id, f := range tag.frames {
		frames[id] = []Framer{f}
	}
	for id, sequence := range tag.sequences {
		frames[id] = sequence.Frames()
	}

	return frames
}

// DeleteAllFrames deletes all frames in tag.
func (tag *Tag) DeleteAllFrames() {
	if tag.frames == nil || len(tag.frames) > 0 {
		tag.frames = make(map[string]Framer)
	}
	if tag.sequences == nil || len(tag.sequences) > 0 {
		for _, s := range tag.sequences {
			putSequence(s)
		}
		tag.sequences = make(map[string]*sequence)
	}
}

// DeleteFrames deletes frames in tag with given id.
func (tag *Tag) DeleteFrames(id string) {
	delete(tag.frames, id)
	if s, ok := tag.sequences[id]; ok {
		putSequence(s)
		delete(tag.sequences, id)
	}
}

// Reset deletes all frames in tag and parses rd considering opts.
func (tag *Tag) Reset(rd io.Reader, opts Options) error {
	tag.DeleteAllFrames()
	return tag.parse(rd, opts)
}

// GetFrames returns frames with corresponding id.
// It returns nil if there is no frames with given id.
func (tag *Tag) GetFrames(id string) []Framer {
	if f, exists := tag.frames[id]; exists {
		return []Framer{f}
	} else if s, exists := tag.sequences[id]; exists {
		return s.Frames()
	}
	return nil
}

// GetLastFrame returns last frame from slice, that is returned from GetFrames function.
// GetLastFrame is suitable for frames, that can be only one in whole tag.
// For example, for text frames.
func (tag *Tag) GetLastFrame(id string) Framer {
	// Avoid an allocation of slice in GetFrames,
	// if there is anyway one frame.
	if f, exists := tag.frames[id]; exists {
		return f
	}

	fs := tag.GetFrames(id)
	if len(fs) == 0 {
		return nil
	}
	return fs[len(fs)-1]
}

// GetTextFrame returns text frame with corresponding id.
func (tag *Tag) GetTextFrame(id string) TextFrame {
	f := tag.GetLastFrame(id)
	if f == nil {
		return TextFrame{}
	}
	tf := f.(TextFrame)
	return tf
}

// Count returns the number of frames in tag.
func (tag *Tag) Count() int {
	n := len(tag.frames)
	for _, s := range tag.sequences {
		n += s.Count()
	}
	return n
}

// HasFrames checks if there is at least one frame in tag.
// It's much faster than tag.Count() > 0.
func (tag *Tag) HasFrames() bool {
	return len(tag.frames) > 0 || len(tag.sequences) > 0
}

func (tag *Tag) Title() string {
	f := tag.GetTextFrame(tag.CommonID("Title"))
	return f.Text
}

func (tag *Tag) SetTitle(title string) {
	tag.AddFrame(tag.CommonID("Title"), TextFrame{Encoding: tag.defaultEncoding, Text: title})
}

func (tag *Tag) Artist() string {
	f := tag.GetTextFrame(tag.CommonID("Artist"))
	return f.Text
}

func (tag *Tag) SetArtist(artist string) {
	tag.AddFrame(tag.CommonID("Artist"), TextFrame{Encoding: tag.defaultEncoding, Text: artist})
}

func (tag *Tag) Album() string {
	f := tag.GetTextFrame(tag.CommonID("Album/Movie/Show title"))
	return f.Text
}

func (tag *Tag) SetAlbum(album string) {
	tag.AddFrame(tag.CommonID("Album/Movie/Show title"), TextFrame{Encoding: tag.defaultEncoding, Text: album})
}

func (tag *Tag) Year() string {
	f := tag.GetTextFrame(tag.CommonID("Year"))
	return f.Text
}

func (tag *Tag) SetYear(year string) {
	tag.AddFrame(tag.CommonID("Year"), TextFrame{Encoding: tag.defaultEncoding, Text: year})
}

func (tag *Tag) Genre() string {
	f := tag.GetTextFrame(tag.CommonID("Content type"))
	return f.Text
}

func (tag *Tag) SetGenre(genre string) {
	tag.AddFrame(tag.CommonID("Content type"), TextFrame{Encoding: tag.defaultEncoding, Text: genre})
}

// iterateOverAllFrames iterates over every single frame in tag and calls
// f for them. It consumps no memory at all, unlike the tag.AllFrames().
// It returns error only if f returns error.
func (tag *Tag) iterateOverAllFrames(f func(id string, frame Framer) error) error {
	for id, frame := range tag.frames {
		if err := f(id, frame); err != nil {
			return err
		}
	}
	for id, sequence := range tag.sequences {
		for _, frame := range sequence.Frames() {
			if err := f(id, frame); err != nil {
				return err
			}
		}
	}
	return nil
}

// Size returns the size of tag (tag header + size of all frames) in bytes.
func (tag *Tag) Size() int {
	if !tag.HasFrames() {
		return 0
	}

	var n int
	n += tagHeaderSize // Add the size of tag header
	tag.iterateOverAllFrames(func(id string, f Framer) error {
		n += frameHeaderSize + f.Size() // Add the whole frame size
		return nil
	})

	return n
}

// Version returns current ID3v2 version of tag.
func (tag *Tag) Version() byte {
	return tag.version
}

// SetVersion sets given ID3v2 version to tag.
// If version is less than 3 or greater than 4, then this method will do nothing.
// If tag has some frames, which are deprecated or changed in given version,
// then to your notice you can delete, change or just stay them.
func (tag *Tag) SetVersion(version byte) {
	if version < 3 || version > 4 {
		return
	}
	tag.version = version
}

// Save writes tag to the file, if tag was opened with a file.
// If there are no frames in tag, Save will write
// only music part without any ID3v2 information.
// If tag was initiliazed not with file, it returns ErrNoFile.
func (tag *Tag) Save() error {
	file, ok := tag.reader.(*os.File)
	if !ok {
		return ErrNoFile
	}

	// Get original file mode.
	originalFile := file
	originalStat, err := originalFile.Stat()
	if err != nil {
		return err
	}

	// Create a temp file for mp3 file, which will contain new tag.
	name := file.Name() + "-id3v2"
	newFile, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, originalStat.Mode())
	if err != nil {
		return err
	}

	// Make sure we clean up the temp file if it's still around.
	// tempfileShouldBeRemoved created only for performance
	// improvement to prevent calling redundant Remove syscalls if file is moved
	// and is not need to be removed.
	tempfileShouldBeRemoved := true
	defer func() {
		if tempfileShouldBeRemoved {
			os.Remove(newFile.Name())
		}
	}()

	// Write tag in new file.
	tagSize, err := tag.WriteTo(newFile)
	if err != nil {
		return err
	}

	// Seek to a music part of original file.
	if _, err = originalFile.Seek(tag.originalSize, os.SEEK_SET); err != nil {
		return err
	}

	// Write to new file the music part.
	buf := getByteSlice(32 * 1024)
	defer putByteSlice(buf)
	if _, err = io.CopyBuffer(newFile, originalFile, buf); err != nil {
		return err
	}

	// Close files to allow replacing.
	newFile.Close()
	originalFile.Close()

	// Replace original file with new file.
	if err = os.Rename(newFile.Name(), originalFile.Name()); err != nil {
		return err
	}
	tempfileShouldBeRemoved = false

	// Set tag.reader to new file with original name.
	tag.reader, err = os.Open(originalFile.Name())
	if err != nil {
		return err
	}

	// Set tag.originalSize to new frames size.
	if tagSize > tagHeaderSize {
		tag.originalSize = tagSize - tagHeaderSize
	} else {
		tag.originalSize = 0
	}

	return nil
}

// WriteTo writes whole tag in w if there is at least one frame.
// It returns the number of bytes written and error during the write.
// It returns nil as error if the write was successful.
func (tag *Tag) WriteTo(w io.Writer) (n int64, err error) {
	if w == nil {
		return 0, errors.New("w is nil")
	}

	// Count size of frames.
	framesSize := tag.Size() - tagHeaderSize
	if framesSize <= 0 {
		return 0, nil
	}

	// Write tag header.
	bw := getBufioWriter(w)
	defer putBufioWriter(bw)
	if err := writeTagHeader(bw, uint(framesSize), tag.version); err != nil {
		return 0, err
	}
	n += tagHeaderSize

	// Write frames.
	err = tag.iterateOverAllFrames(func(id string, f Framer) error {
		nn, err := writeFrame(bw, id, f)
		n += nn
		return err
	})
	if err != nil {
		return n, err
	}

	return n, bw.Flush()
}

func writeFrame(bw *bufio.Writer, id string, frame Framer) (int64, error) {
	if err := writeFrameHeader(bw, id, uint(frame.Size())); err != nil {
		return 0, err
	}

	frameSize, err := frame.WriteTo(bw)
	return frameHeaderSize + frameSize, err
}

func writeFrameHeader(bw *bufio.Writer, id string, frameSize uint) error {
	// ID
	if _, err := bw.WriteString(id); err != nil {
		return err
	}

	// Size
	if err := writeBytesSize(bw, frameSize); err != nil {
		return err
	}

	// Flags
	if _, err := bw.Write([]byte{0, 0}); err != nil {
		return err
	}
	return nil
}

// Close closes tag's file, if tag was opened with a file.
// If tag was initiliazed not with file, it returns ErrNoFile.
func (tag *Tag) Close() error {
	file, ok := tag.reader.(*os.File)
	if !ok {
		return ErrNoFile
	}
	return file.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	var (
		flags   int = (os.O_WRONLY | os.O_CREATE)
		files   []io.Writer
		exitval int = 0
	)

	interruptFlag := flag.Bool("i", false, "")
	appendFlag := flag.Bool("a", false, "")
	flag.Usage = usage

	flag.Parse()

	if *interruptFlag {
		signal.Ignore(syscall.SIGINT)
	}

	if *appendFlag {
		flags |= os.O_APPEND
	} else {
		flags |= os.O_TRUNC
	}

	files = append(files, os.Stdout)

	for _, arg := range flag.Args() {
		if arg == "-" {
			continue
		}

		if f, err := os.OpenFile(arg, flags, os.ModePerm); err != nil {
			fmt.Fprintf(os.Stderr, "%s - %v", arg, err)
			exitval = 1
		} else {
			defer f.Close()
			files = append(files, f)
		}
	}

	if _, err := io.Copy(io.MultiWriter(files...), os.Stdin); err != nil {
		fmt.Fprintf(os.Stderr, "%v", err)
		exitval = 1
	}

	os.Exit(exitval)
}

func usage() {
	fmt.Fprintln(os.Stderr, "usage: tee [-ai] [file ...]")
	os.Exit(1)
}
<commit_msg>add flag descriptions<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	var (
		flags   int = (os.O_WRONLY | os.O_CREATE)
		files   []io.Writer
		exitval int
	)

	appendFlag := flag.Bool("a", false, "Append the output to the files rather than overwriting them.")
	interruptFlag := flag.Bool("i", false, "Ignore the SIGINT signal.")
	flag.Usage = usage

	flag.Parse()

	if *interruptFlag {
		signal.Ignore(syscall.SIGINT)
	}

	if *appendFlag {
		flags |= os.O_APPEND
	} else {
		flags |= os.O_TRUNC
	}

	files = append(files, os.Stdout)

	for _, arg := range flag.Args() {
		if arg == "-" {
			continue
		}

		if f, err := os.OpenFile(arg, flags, os.ModePerm); err != nil {
			fmt.Fprintf(os.Stderr, "%s - %v", arg, err)
			exitval = 1
		} else {
			defer f.Close()
			files = append(files, f)
		}
	}

	if _, err := io.Copy(io.MultiWriter(files...), os.Stdin); err != nil {
		fmt.Fprintf(os.Stderr, "%v", err)
		exitval = 1
	}

	os.Exit(exitval)
}

func usage() {
	fmt.Fprintln(os.Stderr, "usage: tee [-ai] [file ...]")
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

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

func loadNameWithSynsetFromSynset(synset string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select name from synset where synset=?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var name string
	err = stmt.QueryRow(synset).Scan(&name)

	if err != nil {
		log.Fatal(err, ": DBにwordidが見つかりません")
	}
	return name
}

func loadSynsetsWithWordidFromSense(wordid string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select synset from sense where wordid=?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	rows, err := stmt.Query(wordid)
	defer rows.Close()
	synsets := []string{}
	for i := 0; rows.Next(); i++ {
		var synset string
		rows.Scan(&synset)
		synsets = append(synsets, synset)
	}

	if err != nil {
		log.Fatal(err, ": senseにwordidが見つかりません")
	}
	return synsets
}

func loadWordsWithLemmmaFromWord(lemma string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select wordid from word where lemma = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	rows, err := stmt.Query(lemma)
	defer rows.Close()
	var wordids []string
	for i := 0; rows.Next(); i++ {
		var wordid string
		rows.Scan(&wordid)
		wordids = append(wordids, wordid)
	}

	if err != nil {
		log.Fatal(err, ": wordにwordidが見つかりません")
	}
	return wordids
}

func loadSynsetsWithSynsetFromSynlink(synset string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select synset2 from synlink where synset1=? and link='hype';"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	rows, err := stmt.Query(synset)
	defer rows.Close()
	synsets := []string{}
	for i := 0; rows.Next(); i++ {
		var synset2 string
		rows.Scan(&synset2)
		synsets = append(synsets, synset2)
	}

	if err != nil {
		log.Fatal(err, ": synlinkにwordidが見つかりません")
	}
	return synsets
}

func loadLemmaWithWordidFromWord(wordid string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select lemma from word where wordid = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var lemma string
	err = stmt.QueryRow(wordid).Scan(&lemma)

	if err != nil {
		log.Fatal(err, ": wordに単語が見つかりません")
	}
	return lemma
}

func loadWordidWithSynsetFromSense(synset string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select wordid from sense where synset = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var wordid string
	err = stmt.QueryRow(synset).Scan(&wordid)

	if err != nil {
		log.Fatal(err, ": senseに単語が見つかりません", synset)
	}
	return wordid
}
func printSynlinksRecursively(wordids []string, depth int) {
	for j := 0; j < len(wordids); j++ {
		synsets := loadSynsetsWithWordidFromSense(wordids[j])
		synlinksSynsets := []string{}
		for i := 0; i < len(synsets); i++ {
			synlinksSynsets = append(synlinksSynsets, loadSynsetsWithSynsetFromSynlink(synsets[i])...)
		}
		deeperWordids := []string{}
		if len(synlinksSynsets) != 0 {
			for i := 0; i < depth+1; i++ {
				fmt.Print("  ")
			}
			lemma := loadLemmaWithWordidFromWord(wordids[j])
			fmt.Println("  ", lemma)
			for i := 0; i < len(synlinksSynsets); i++ {
				newWordid := loadWordidWithSynsetFromSense(synlinksSynsets[i])
				deeperWordids = append(deeperWordids, newWordid)
			}
			printSynlinksRecursively(deeperWordids, depth+1)
		}
	}
}

func main() {
	lemma := "夢"
	wordids := loadWordsWithLemmmaFromWord(lemma)
	printSynlinksRecursively(wordids, 0)
}
<commit_msg>completed<commit_after>package main

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

func loadNameWithSynsetFromSynset(synset string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select name from synset where synset=?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var name string
	err = stmt.QueryRow(synset).Scan(&name)

	if err != nil {
		log.Fatal(err, ": DBにwordidが見つかりません")
	}
	return name
}

func loadSynsetsWithWordidFromSense(wordid string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select synset from sense where wordid=?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	rows, err := stmt.Query(wordid)
	defer rows.Close()
	synsets := []string{}
	for i := 0; rows.Next(); i++ {
		var synset string
		rows.Scan(&synset)
		synsets = append(synsets, synset)
	}

	if err != nil {
		log.Fatal(err, ": senseにwordidが見つかりません")
	}
	return synsets
}

func loadWordsWithLemmmaFromWord(lemma string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select wordid from word where lemma = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	rows, err := stmt.Query(lemma)
	defer rows.Close()
	var wordids []string
	for i := 0; rows.Next(); i++ {
		var wordid string
		rows.Scan(&wordid)
		wordids = append(wordids, wordid)
	}

	if err != nil {
		log.Fatal(err, ": wordにwordidが見つかりません")
	}
	return wordids
}

func loadSynsetsWithSynsetFromSynlink(synset string) []string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select synset2 from synlink where synset1=? and link='hype';"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	rows, err := stmt.Query(synset)
	defer rows.Close()
	synsets := []string{}
	for i := 0; rows.Next(); i++ {
		var synset2 string
		rows.Scan(&synset2)
		synsets = append(synsets, synset2)
	}

	if err != nil {
		log.Fatal(err, ": synlinkにwordidが見つかりません")
	}
	return synsets
}

func loadLemmaWithWordidFromWord(wordid string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select lemma from word where wordid = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var lemma string
	err = stmt.QueryRow(wordid).Scan(&lemma)

	if err != nil {
		log.Fatal(err, ": wordに単語が見つかりません")
	}
	return lemma
}

func loadWordidWithSynsetFromSense(synset string) string {
	db, err := sql.Open("sqlite3", "wnjpn.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sql := "select wordid from sense where synset = ?;"
	stmt, err := db.Prepare(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var wordid string
	err = stmt.QueryRow(synset).Scan(&wordid)

	if err != nil {
		log.Fatal(err, ": senseに単語が見つかりません", synset)
	}
	return wordid
}
func printSynlinksRecursively(wordids []string, depth int) {
	if depth > 20 {
		log.Fatal("おしまい")
	}
	for j := 0; j < len(wordids); j++ {
		synsets := loadSynsetsWithWordidFromSense(wordids[j])
		synlinksSynsets := []string{}
		for k := 0; k < len(synsets); k++ {
			synlinksSynsets = append(synlinksSynsets, loadSynsetsWithSynsetFromSynlink(synsets[k])...)
		}
		deeperWordids := []string{}
		if len(synlinksSynsets) != 0 {
			for i := 0; i < depth+1; i++ {
				fmt.Print("  ")
			}
			lemma := loadLemmaWithWordidFromWord(wordids[j])
			fmt.Println("  ", lemma)
			for i := 0; i < len(synlinksSynsets); i++ {
				newWordid := loadWordidWithSynsetFromSense(synlinksSynsets[i])
				deeperWordids = append(deeperWordids, newWordid)
			}
		}
		printSynlinksRecursively(deeperWordids, depth+1)
	}
}

func main() {
	lemma := os.Args[1]
	wordids := loadWordsWithLemmmaFromWord(lemma)
	printSynlinksRecursively(wordids, 0)
}
<|endoftext|>


<commit_before>// Package tuntap provides a portable interface to create and use
// TUN/TAP virtual network interfaces.
//
// Note that while this package lets you create the interface and pass
// packets to/from it, it does not provide an API to configure the
// interface. Interface configuration is a very large topic and should
// be dealt with separately.
package tuntap

import (
	"encoding/binary"
	"io"
	"net"
	"os"
	"unsafe"
)

type DevKind int

const (
	// Receive/send layer routable 3 packets (IP, IPv6...). Notably,
	// you don't receive link-local multicast with this interface
	// type.
	DevTun DevKind = iota
	// Receive/send Ethernet II frames. You receive all packets that
	// would be visible on an Ethernet link, including broadcast and
	// multicast traffic.
	DevTap
)

const (
	// various ethernet protocols, using the same names as linux does
	ETH_P_IP   int = 0x0800
	ETH_P_IPV6 int = 0x86dd
)

type Packet struct {
	// The Ethernet type of the packet. Commonly seen values are
	// 0x8000 for IPv4 and 0x86dd for IPv6.
	Protocol int
	// True if the packet was too large to be read completely.
	Truncated bool
	// The raw bytes of the Ethernet payload (for DevTun) or the full
	// Ethernet frame (for DevTap).
	Body []byte
}

type Interface struct {
	name string
	file *os.File
}

// Disconnect from the tun/tap interface.
//
// If the interface isn't configured to be persistent, it is
// immediately destroyed by the kernel.
func (t *Interface) Close() error {
	return t.file.Close()
}

// The name of the interface. May be different from the name given to
// Open(), if the latter was a pattern.
func (t *Interface) Name() string {
	return t.name
}

// Read a single packet from the kernel.
func (t *Interface) ReadPacket() (*Packet, error) {
	buf := make([]byte, 1600)

	n, err := t.file.Read(buf)
	if err != nil {
		return nil, err
	}

	pkt := &Packet{Body: buf[4:n]}
	pkt.Protocol = int(binary.BigEndian.Uint16(buf[2:4]))
	flags := *(*uint16)(unsafe.Pointer(&buf[0]))
	if flags&flagTruncated != 0 {
		pkt.Truncated = true
	}
	return pkt, nil
}

// Send a single packet to the kernel.
func (t *Interface) WritePacket(pkt *Packet) error {
	// If only we had writev(), I could do zero-copy here...
	buf := make([]byte, len(pkt.Body)+4)
	binary.BigEndian.PutUint16(buf[2:4], uint16(pkt.Protocol))
	copy(buf[4:], pkt.Body)
	n, err := t.file.Write(buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return io.ErrShortWrite
	}
	return nil
}

// Open connects to the specified tun/tap interface.
//
// If the specified device has been configured as persistent, this
// simply looks like a "cable connected" event to observers of the
// interface. Otherwise, the interface is created out of thin air.
//
// ifPattern can be an exact interface name, e.g. "tun42", or a
// pattern containing one %d format specifier, e.g. "tun%d". In the
// latter case, the kernel will select an available interface name and
// create it.
//
// Returns a TunTap object with channels to send/receive packets, or
// nil and an error if connecting to the interface failed.
func Open(ifPattern string, kind DevKind) (*Interface, error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}

	ifName, err := createInterface(file, ifPattern, kind)
	if err != nil {
		file.Close()
		return nil, err
	}

	return &Interface{ifName, file}, nil
}

// query parts of Packets
// NOTE: think whether this wouldn't be better done with a interface and two implemenations, one for each protocol

// return the destination IP
func (p *Packet) DIP() net.IP {
	switch p.Protocol {
	case ETH_P_IP:
		return net.IP(p.Body[16:20])
	case ETH_P_IPV6:
		return net.IP(p.Body[24:40])
	}
	return net.IP{}
}

// return the source IP
func (p *Packet) SIP() net.IP {
	switch p.Protocol {
	case ETH_P_IP:
		return net.IP(p.Body[12:16])
	case ETH_P_IPV6:
		return net.IP(p.Body[8:24])
	}
	return net.IP{}
}
<commit_msg>added DSCP() method to extract the 6-bit DSCP field<commit_after>// Package tuntap provides a portable interface to create and use
// TUN/TAP virtual network interfaces.
//
// Note that while this package lets you create the interface and pass
// packets to/from it, it does not provide an API to configure the
// interface. Interface configuration is a very large topic and should
// be dealt with separately.
package tuntap

import (
	"encoding/binary"
	"io"
	"net"
	"os"
	"unsafe"
)

type DevKind int

const (
	// Receive/send layer routable 3 packets (IP, IPv6...). Notably,
	// you don't receive link-local multicast with this interface
	// type.
	DevTun DevKind = iota
	// Receive/send Ethernet II frames. You receive all packets that
	// would be visible on an Ethernet link, including broadcast and
	// multicast traffic.
	DevTap
)

const (
	// various ethernet protocols, using the same names as linux does
	ETH_P_IP   int = 0x0800
	ETH_P_IPV6 int = 0x86dd
)

type Packet struct {
	// The Ethernet type of the packet. Commonly seen values are
	// 0x8000 for IPv4 and 0x86dd for IPv6.
	Protocol int
	// True if the packet was too large to be read completely.
	Truncated bool
	// The raw bytes of the Ethernet payload (for DevTun) or the full
	// Ethernet frame (for DevTap).
	Body []byte
}

type Interface struct {
	name string
	file *os.File
}

// Disconnect from the tun/tap interface.
//
// If the interface isn't configured to be persistent, it is
// immediately destroyed by the kernel.
func (t *Interface) Close() error {
	return t.file.Close()
}

// The name of the interface. May be different from the name given to
// Open(), if the latter was a pattern.
func (t *Interface) Name() string {
	return t.name
}

// Read a single packet from the kernel.
func (t *Interface) ReadPacket() (*Packet, error) {
	buf := make([]byte, 1600)

	n, err := t.file.Read(buf)
	if err != nil {
		return nil, err
	}

	pkt := &Packet{Body: buf[4:n]}
	pkt.Protocol = int(binary.BigEndian.Uint16(buf[2:4]))
	flags := *(*uint16)(unsafe.Pointer(&buf[0]))
	if flags&flagTruncated != 0 {
		pkt.Truncated = true
	}
	return pkt, nil
}

// Send a single packet to the kernel.
func (t *Interface) WritePacket(pkt *Packet) error {
	// If only we had writev(), I could do zero-copy here...
	buf := make([]byte, len(pkt.Body)+4)
	binary.BigEndian.PutUint16(buf[2:4], uint16(pkt.Protocol))
	copy(buf[4:], pkt.Body)
	n, err := t.file.Write(buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return io.ErrShortWrite
	}
	return nil
}

// Open connects to the specified tun/tap interface.
//
// If the specified device has been configured as persistent, this
// simply looks like a "cable connected" event to observers of the
// interface. Otherwise, the interface is created out of thin air.
//
// ifPattern can be an exact interface name, e.g. "tun42", or a
// pattern containing one %d format specifier, e.g. "tun%d". In the
// latter case, the kernel will select an available interface name and
// create it.
//
// Returns a TunTap object with channels to send/receive packets, or
// nil and an error if connecting to the interface failed.
func Open(ifPattern string, kind DevKind) (*Interface, error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}

	ifName, err := createInterface(file, ifPattern, kind)
	if err != nil {
		file.Close()
		return nil, err
	}

	return &Interface{ifName, file}, nil
}

// query parts of Packets
// NOTE: think whether this wouldn't be better done with a interface and two implemenations, one for each protocol

// return the destination IP
func (p *Packet) DIP() net.IP {
	switch p.Protocol {
	case ETH_P_IP:
		return net.IP(p.Body[16:20])
	case ETH_P_IPV6:
		return net.IP(p.Body[24:40])
	}
	return net.IP{}
}

// return the source IP
func (p *Packet) SIP() net.IP {
	switch p.Protocol {
	case ETH_P_IP:
		return net.IP(p.Body[12:16])
	case ETH_P_IPV6:
		return net.IP(p.Body[8:24])
	}
	return net.IP{}
}

// return the 6-bit DSCP field
func (p *Packet) DSCP() int {
	switch p.Protocol {
	case ETH_P_IP:
		return int(p.Body[1] >> 2)
	case ETH_P_IPV6:
		return int((p.Body[0]&0x0f)<<2 | (p.Body[1]&0xf0)>>6)
	}
	return 0
}
<|endoftext|>


<commit_before>package mango

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"

	"github.com/singpenguin/mango/utils"
)

type HTTPRequest struct {
	Args       []string //route params
	Method     string   //HTTP method
	RemoteAddr string   //ip
	Path       string
	Host       string
	Params     url.Values                         //GET or POST params
	Body       []byte                             //Content-Type=application/octet-stream, Body=http body
	Files      map[string][]*multipart.FileHeader //Content-Type=multipart/form-data

	W http.ResponseWriter
	R *http.Request
}

func (self *HTTPRequest) Init(w http.ResponseWriter, r *http.Request, a []string) {
	self.W = w
	self.R = r
	self.Method = r.Method
	self.Path = r.URL.Path
	self.Args = a
	self.Host = r.Host

	ip := r.Header.Get("X-Forwarded-For")
	if ip == "" {
		ip = r.RemoteAddr
	}
	self.RemoteAddr = strings.Split(ip, ":")[0]
	self.parseBodyArguments()
}

func (self *HTTPRequest) UserAgent() string {
	return self.R.Header.Get("User-Agent")
}

func (self *HTTPRequest) Header(s string) string {
	return self.R.Header.Get(s)
}

func (self *HTTPRequest) SetHeader(k, v string) {
	self.W.Header().Set(k, v)
}

func (self *HTTPRequest) SetStatus(st int) {
	self.W.WriteHeader(st)
}

func (self *HTTPRequest) Cookie(k string) (string, error) {
	ck, err := self.R.Cookie(k)
	if err != nil {
		return "", err
	}
	return ck.Value, nil
}

var cks = strings.NewReplacer("\n", "-", "\r", "-")
var cvs = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")

func (self *HTTPRequest) SetSecureCookie(k, v string, params ...interface{}) {
	bv := []byte(v)
	ts := utils.FormatInt(utils.Timestamp())
	v = utils.Base64Encode(bv)
	sa := []string{}
	sa = append(sa, "2|1:0")
	sa = append(sa, fmt.Sprintf("%d:%s", len(ts), ts))
	sa = append(sa, fmt.Sprintf("%d:%s", len(k), k))
	sa = append(sa, fmt.Sprintf("%d:%s", len(v), v))
	sa = append(sa, "")
	to_sign := strings.Join(sa, "|")
	signature := utils.HmacSha256(to_sign, CookieSecret)

	self.SetCookie(k, to_sign+signature, params...)
}

func (self *HTTPRequest) GetSecureCookie(k string) (string, error) {
	value, err := self.Cookie(k)
	if err != nil || len(value) < 64 {
		return "", err
	}
	_rest := value[2:]
	_, rest, err := consumeField(_rest)
	if err != nil {
		return "", err
	}
	timestamp_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	name_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	value_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	passed_sig := rest
	signed_str := value[:len(value)-len(passed_sig)]
	signature := utils.HmacSha256(signed_str, CookieSecret)
	if passed_sig != signature {
		return "", errors.New("signature invalid")
	}
	if name_field != k {
		return "", errors.New("cookie name invalid")
	}
	timestamp, _ := utils.ParseInt(timestamp_field)
	if timestamp < Timestamp()-2678400 {
		return "", errors.New("signature has expired")
	}
	devalue, err := utils.Base64Decode(value_field)
	if err != nil {
		return "", errors.New("value cannot be decode")
	}
	return devalue, nil
}

func consumeField(value string) (string, string, error) {
	var length, rest string
	unpack(strings.SplitN(value, ":", 2), &length, &rest)

	n, err := ParseInt(length)
	if err != nil {
		return "", "", errors.New("length field invalid")
	}
	key_field := rest[:n]
	if rest[n:n+1] != "|" {
		return "", "", errors.New("malformed signed value")
	}
	rest = rest[n+1:]
	return key_field, rest, nil
}

func (self *HTTPRequest) SetCookie(k, v string, params ...interface{}) {
	var b bytes.Buffer
	fmt.Fprintf(&b, "%s=%s", cks.Replace(k), cvs.Replace(v))
	if len(params) > 0 {
		switch v := params[0].(type) {
		case int:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		case int64:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		case int32:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		}
	}
	// Path, Domain, Secure, HttpOnly

	// default "/"
	if len(params) > 1 {
		if v, ok := params[1].(string); ok && len(v) > 0 {
			fmt.Fprintf(&b, "; Path=%s", cvs.Replace(v))
		}
	} else {
		fmt.Fprintf(&b, "; Path=%s", "/")
	}

	// default empty
	if len(params) > 2 {
		if v, ok := params[2].(string); ok && len(v) > 0 {
			fmt.Fprintf(&b, "; Domain=%s", cvs.Replace(v))
		}
	}

	// default empty
	if len(params) > 3 {
		var secure bool
		switch v := params[3].(type) {
		case bool:
			secure = v
		default:
			if params[3] != nil {
				secure = true
			}
		}
		if secure {
			fmt.Fprintf(&b, "; Secure")
		}
	}

	// default false.
	httponly := false
	if len(params) > 4 {
		if v, ok := params[4].(bool); ok && v {
			// HttpOnly = true
			httponly = true
		}
	}

	if httponly {
		fmt.Fprintf(&b, "; HttpOnly")
	}

	self.W.Header().Add("Set-Cookie", b.String())
}

func (self *HTTPRequest) Scheme() string {
	if self.R.URL.Scheme != "" {
		return self.R.URL.Scheme
	} else if self.R.TLS == nil {
		return "http"
	} else {
		return "https"
	}
}

func (self *HTTPRequest) Redirect(newloc string) {
	self.SetHeader("Location", newloc)
	self.SetStatus(303)
}

func (self *HTTPRequest) Query() map[string][]string {
	return self.R.URL.Query()
}

func (self *HTTPRequest) QueryString() string {
	if s := strings.Split(self.R.RequestURI, "?"); len(s) > 1 {
		return s[1]
	} else {
		return ""
	}
}

func (self *HTTPRequest) parseBodyArguments() {
	qs := self.R.URL.Query()
	var pt url.Values
	ct := self.Header("Content-Type")
	if strings.HasPrefix(ct, "application/x-www-form-urlencoded") {
		if err := self.R.ParseForm(); err != nil {
			fmt.Println("Error parsing request body:", err)
		} else {
			pt = self.R.Form
		}
	} else if strings.HasPrefix(ct, "multipart/form-data") {
		// TODO: Extract the multipart form param so app can set it.
		if err := self.R.ParseMultipartForm(32 << 20 /* 32 MB */); err != nil {
			fmt.Println("Error parsing request body:", err)
		} else {
			self.Files = self.R.MultipartForm.File
		}
	} else if strings.HasPrefix(ct, "application/octet-stream") {
		self.Body = self.Data()
	}

	num := len(qs) + len(pt)

	if num == 0 {
		self.Params = make(url.Values, 0)
		return
	}
	values := make(url.Values, num)
	for k, v := range qs {
		values[k] = append(values[k], v...)
	}
	for k, v := range pt {
		values[k] = append(values[k], v...)
	}
	self.Params = values
}

func (self *HTTPRequest) Data() []byte {
	body, _ := ioutil.ReadAll(self.R.Body)
	self.R.Body.Close()
	bf := bytes.NewBuffer(body)
	self.R.Body = ioutil.NopCloser(bf)
	return body
}

func (self *HTTPRequest) Write(s string) {
	self.W.Write([]byte(s))
}

func (self *HTTPRequest) Render(name string, data interface{}) {
	Template[name].Execute(self.W, data)
}

func (self *HTTPRequest) GET() {
	http.Error(self.W, "Method GET Not Allowed", 405)
}

func (self *HTTPRequest) POST() {
	http.Error(self.W, "Method POST Not Allowed", 405)
}

func (self *HTTPRequest) HEAD() {
	http.Error(self.W, "Method HEAD Not Allowed", 405)
}

func (self *HTTPRequest) OPTION() {
	http.Error(self.W, "Method OPTION Not Allowed", 405)
}

func (self *HTTPRequest) PUT() {
	http.Error(self.W, "Method PUT Not Allowed", 405)
}

func (self *HTTPRequest) DELETE() {
	http.Error(self.W, "Method DELETE Not Allowed", 405)
}
<commit_msg>fix bug<commit_after>package mango

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"

	"github.com/singpenguin/mango/utils"
)

type HTTPRequest struct {
	Args       []string //route params
	Method     string   //HTTP method
	RemoteAddr string   //ip
	Path       string
	Host       string
	Params     url.Values                         //GET or POST params
	Body       []byte                             //Content-Type=application/octet-stream, Body=http body
	Files      map[string][]*multipart.FileHeader //Content-Type=multipart/form-data

	W http.ResponseWriter
	R *http.Request
}

func (self *HTTPRequest) Init(w http.ResponseWriter, r *http.Request, a []string) {
	self.W = w
	self.R = r
	self.Method = r.Method
	self.Path = r.URL.Path
	self.Args = a
	self.Host = r.Host

	ip := r.Header.Get("X-Forwarded-For")
	if ip == "" {
		ip = r.RemoteAddr
	}
	self.RemoteAddr = strings.Split(ip, ":")[0]
	self.parseBodyArguments()
}

func (self *HTTPRequest) UserAgent() string {
	return self.R.Header.Get("User-Agent")
}

func (self *HTTPRequest) Header(s string) string {
	return self.R.Header.Get(s)
}

func (self *HTTPRequest) SetHeader(k, v string) {
	self.W.Header().Set(k, v)
}

func (self *HTTPRequest) SetStatus(st int) {
	self.W.WriteHeader(st)
}

func (self *HTTPRequest) Cookie(k string) (string, error) {
	ck, err := self.R.Cookie(k)
	if err != nil {
		return "", err
	}
	return ck.Value, nil
}

var cks = strings.NewReplacer("\n", "-", "\r", "-")
var cvs = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")

func (self *HTTPRequest) SetSecureCookie(k, v string, params ...interface{}) {
	bv := []byte(v)
	ts := utils.FormatInt(utils.Timestamp())
	v = utils.Base64Encode(bv)
	sa := []string{}
	sa = append(sa, "2|1:0")
	sa = append(sa, fmt.Sprintf("%d:%s", len(ts), ts))
	sa = append(sa, fmt.Sprintf("%d:%s", len(k), k))
	sa = append(sa, fmt.Sprintf("%d:%s", len(v), v))
	sa = append(sa, "")
	to_sign := strings.Join(sa, "|")
	signature := utils.HmacSha256(to_sign, CookieSecret)

	self.SetCookie(k, to_sign+signature, params...)
}

func (self *HTTPRequest) GetSecureCookie(k string) (string, error) {
	value, err := self.Cookie(k)
	if err != nil || len(value) < 64 {
		return "", err
	}
	_rest := value[2:]
	_, rest, err := consumeField(_rest)
	if err != nil {
		return "", err
	}
	timestamp_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	name_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	value_field, rest, err := consumeField(rest)
	if err != nil {
		return "", err
	}
	passed_sig := rest
	signed_str := value[:len(value)-len(passed_sig)]
	signature := utils.HmacSha256(signed_str, CookieSecret)
	if passed_sig != signature {
		return "", errors.New("signature invalid")
	}
	if name_field != k {
		return "", errors.New("cookie name invalid")
	}
	timestamp, _ := utils.ParseInt(timestamp_field)
	if timestamp < utils.Timestamp()-2678400 {
		return "", errors.New("signature has expired")
	}
	devalue, err := utils.Base64Decode(value_field)
	if err != nil {
		return "", errors.New("value cannot be decode")
	}
	return devalue, nil
}

func consumeField(value string) (string, string, error) {
	var length, rest string
	utils.unpack(strings.SplitN(value, ":", 2), &length, &rest)

	n, err := utils.ParseInt(length)
	if err != nil {
		return "", "", errors.New("length field invalid")
	}
	key_field := rest[:n]
	if rest[n:n+1] != "|" {
		return "", "", errors.New("malformed signed value")
	}
	rest = rest[n+1:]
	return key_field, rest, nil
}

func (self *HTTPRequest) SetCookie(k, v string, params ...interface{}) {
	var b bytes.Buffer
	fmt.Fprintf(&b, "%s=%s", cks.Replace(k), cvs.Replace(v))
	if len(params) > 0 {
		switch v := params[0].(type) {
		case int:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		case int64:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		case int32:
			if v > 0 {
				fmt.Fprintf(&b, "; Max-Age=%d", v)
			} else if v < 0 {
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		}
	}
	// Path, Domain, Secure, HttpOnly

	// default "/"
	if len(params) > 1 {
		if v, ok := params[1].(string); ok && len(v) > 0 {
			fmt.Fprintf(&b, "; Path=%s", cvs.Replace(v))
		}
	} else {
		fmt.Fprintf(&b, "; Path=%s", "/")
	}

	// default empty
	if len(params) > 2 {
		if v, ok := params[2].(string); ok && len(v) > 0 {
			fmt.Fprintf(&b, "; Domain=%s", cvs.Replace(v))
		}
	}

	// default empty
	if len(params) > 3 {
		var secure bool
		switch v := params[3].(type) {
		case bool:
			secure = v
		default:
			if params[3] != nil {
				secure = true
			}
		}
		if secure {
			fmt.Fprintf(&b, "; Secure")
		}
	}

	// default false.
	httponly := false
	if len(params) > 4 {
		if v, ok := params[4].(bool); ok && v {
			// HttpOnly = true
			httponly = true
		}
	}

	if httponly {
		fmt.Fprintf(&b, "; HttpOnly")
	}

	self.W.Header().Add("Set-Cookie", b.String())
}

func (self *HTTPRequest) Scheme() string {
	if self.R.URL.Scheme != "" {
		return self.R.URL.Scheme
	} else if self.R.TLS == nil {
		return "http"
	} else {
		return "https"
	}
}

func (self *HTTPRequest) Redirect(newloc string) {
	self.SetHeader("Location", newloc)
	self.SetStatus(303)
}

func (self *HTTPRequest) Query() map[string][]string {
	return self.R.URL.Query()
}

func (self *HTTPRequest) QueryString() string {
	if s := strings.Split(self.R.RequestURI, "?"); len(s) > 1 {
		return s[1]
	} else {
		return ""
	}
}

func (self *HTTPRequest) parseBodyArguments() {
	qs := self.R.URL.Query()
	var pt url.Values
	ct := self.Header("Content-Type")
	if strings.HasPrefix(ct, "application/x-www-form-urlencoded") {
		if err := self.R.ParseForm(); err != nil {
			fmt.Println("Error parsing request body:", err)
		} else {
			pt = self.R.Form
		}
	} else if strings.HasPrefix(ct, "multipart/form-data") {
		// TODO: Extract the multipart form param so app can set it.
		if err := self.R.ParseMultipartForm(32 << 20 /* 32 MB */); err != nil {
			fmt.Println("Error parsing request body:", err)
		} else {
			self.Files = self.R.MultipartForm.File
		}
	} else if strings.HasPrefix(ct, "application/octet-stream") {
		self.Body = self.Data()
	}

	num := len(qs) + len(pt)

	if num == 0 {
		self.Params = make(url.Values, 0)
		return
	}
	values := make(url.Values, num)
	for k, v := range qs {
		values[k] = append(values[k], v...)
	}
	for k, v := range pt {
		values[k] = append(values[k], v...)
	}
	self.Params = values
}

func (self *HTTPRequest) Data() []byte {
	body, _ := ioutil.ReadAll(self.R.Body)
	self.R.Body.Close()
	bf := bytes.NewBuffer(body)
	self.R.Body = ioutil.NopCloser(bf)
	return body
}

func (self *HTTPRequest) Write(s string) {
	self.W.Write([]byte(s))
}

func (self *HTTPRequest) Render(name string, data interface{}) {
	Template[name].Execute(self.W, data)
}

func (self *HTTPRequest) GET() {
	http.Error(self.W, "Method GET Not Allowed", 405)
}

func (self *HTTPRequest) POST() {
	http.Error(self.W, "Method POST Not Allowed", 405)
}

func (self *HTTPRequest) HEAD() {
	http.Error(self.W, "Method HEAD Not Allowed", 405)
}

func (self *HTTPRequest) OPTION() {
	http.Error(self.W, "Method OPTION Not Allowed", 405)
}

func (self *HTTPRequest) PUT() {
	http.Error(self.W, "Method PUT Not Allowed", 405)
}

func (self *HTTPRequest) DELETE() {
	http.Error(self.W, "Method DELETE Not Allowed", 405)
}
<|endoftext|>