<commit_before>package main

import (
	"errors"
	"io/ioutil"
	"os"

	yaml "gopkg.in/yaml.v2"

	"github.com/chihaya/chihaya/frontend/http"
	"github.com/chihaya/chihaya/frontend/udp"
	"github.com/chihaya/chihaya/middleware"
)

import (
	// Imports to register middleware drivers.
	_ "github.com/chihaya/chihaya/middleware/clientapproval"
	_ "github.com/chihaya/chihaya/middleware/jwt"
	_ "github.com/chihaya/chihaya/middleware/torrentapproval"
	_ "github.com/chihaya/chihaya/middleware/varinterval"
)

import (
	// Imports to register storage drivers.
	_ "github.com/chihaya/chihaya/storage/memory"
	_ "github.com/chihaya/chihaya/storage/redis"
)

type storageConfig struct {
	Name   string      `yaml:"name"`
	Config interface{} `yaml:"config"`
}

// Config represents the configuration used for executing Chihaya.
type Config struct {
	middleware.ResponseConfig `yaml:",inline"`
	PrometheusAddr            string                  `yaml:"prometheus_addr"`
	HTTPConfig                http.Config             `yaml:"http"`
	UDPConfig                 udp.Config              `yaml:"udp"`
	Storage                   storageConfig           `yaml:"storage"`
	PreHooks                  []middleware.HookConfig `yaml:"prehooks"`
	PostHooks                 []middleware.HookConfig `yaml:"posthooks"`
}

// PreHookNames returns only the names of the configured middleware.
func (cfg Config) PreHookNames() (names []string) {
	for _, hook := range cfg.PreHooks {
		names = append(names, hook.Name)
	}

	return
}

// PostHookNames returns only the names of the configured middleware.
func (cfg Config) PostHookNames() (names []string) {
	for _, hook := range cfg.PostHooks {
		names = append(names, hook.Name)
	}

	return
}

// ConfigFile represents a namespaced YAML configation file.
type ConfigFile struct {
	Chihaya Config `yaml:"chihaya"`
}

// ParseConfigFile returns a new ConfigFile given the path to a YAML
// configuration file.
//
// It supports relative and absolute paths and environment variables.
func ParseConfigFile(path string) (*ConfigFile, error) {
	if path == "" {
		return nil, errors.New("no config path specified")
	}

	f, err := os.Open(os.ExpandEnv(path))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	contents, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}

	var cfgFile ConfigFile
	err = yaml.Unmarshal(contents, &cfgFile)
	if err != nil {
		return nil, err
	}

	return &cfgFile, nil
}
<commit_msg>cmd/chihaya: fix imports for updated goimports<commit_after>package main

import (
	"errors"
	"io/ioutil"
	"os"

	yaml "gopkg.in/yaml.v2"

	"github.com/chihaya/chihaya/frontend/http"
	"github.com/chihaya/chihaya/frontend/udp"
	"github.com/chihaya/chihaya/middleware"

	// Imports to register middleware drivers.
	_ "github.com/chihaya/chihaya/middleware/clientapproval"
	_ "github.com/chihaya/chihaya/middleware/jwt"
	_ "github.com/chihaya/chihaya/middleware/torrentapproval"
	_ "github.com/chihaya/chihaya/middleware/varinterval"

	// Imports to register storage drivers.
	_ "github.com/chihaya/chihaya/storage/memory"
	_ "github.com/chihaya/chihaya/storage/redis"
)

type storageConfig struct {
	Name   string      `yaml:"name"`
	Config interface{} `yaml:"config"`
}

// Config represents the configuration used for executing Chihaya.
type Config struct {
	middleware.ResponseConfig `yaml:",inline"`
	PrometheusAddr            string                  `yaml:"prometheus_addr"`
	HTTPConfig                http.Config             `yaml:"http"`
	UDPConfig                 udp.Config              `yaml:"udp"`
	Storage                   storageConfig           `yaml:"storage"`
	PreHooks                  []middleware.HookConfig `yaml:"prehooks"`
	PostHooks                 []middleware.HookConfig `yaml:"posthooks"`
}

// PreHookNames returns only the names of the configured middleware.
func (cfg Config) PreHookNames() (names []string) {
	for _, hook := range cfg.PreHooks {
		names = append(names, hook.Name)
	}

	return
}

// PostHookNames returns only the names of the configured middleware.
func (cfg Config) PostHookNames() (names []string) {
	for _, hook := range cfg.PostHooks {
		names = append(names, hook.Name)
	}

	return
}

// ConfigFile represents a namespaced YAML configation file.
type ConfigFile struct {
	Chihaya Config `yaml:"chihaya"`
}

// ParseConfigFile returns a new ConfigFile given the path to a YAML
// configuration file.
//
// It supports relative and absolute paths and environment variables.
func ParseConfigFile(path string) (*ConfigFile, error) {
	if path == "" {
		return nil, errors.New("no config path specified")
	}

	f, err := os.Open(os.ExpandEnv(path))
	if err != nil {
		return nil, err
	}
	defer f.Close()

	contents, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}

	var cfgFile ConfigFile
	err = yaml.Unmarshal(contents, &cfgFile)
	if err != nil {
		return nil, err
	}

	return &cfgFile, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/jessevdk/go-flags"
	"github.com/vito/twentythousandtonnesofcrudeoil"
)

// overridden via linker flags
var Version = "0.0.0-dev"

func main() {
	var cmd ConcourseCommand

	cmd.Version = func() {
		fmt.Println(Version)
		os.Exit(0)
	}

	parser := flags.NewParser(&cmd, flags.HelpFlag|flags.PassDoubleDash)
	parser.NamespaceDelimiter = "-"

	cmd.lessenRequirements(parser)

	twentythousandtonnesofcrudeoil.TheEnvironmentIsPerfectlySafe(parser, "CONCOURSE_")

	_, err := parser.Parse()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>update auth flags setup<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/concourse/atc/auth/provider"
	flags "github.com/jessevdk/go-flags"
	"github.com/vito/twentythousandtonnesofcrudeoil"

	_ "github.com/concourse/atc/auth/genericoauth"
	_ "github.com/concourse/atc/auth/github"
	_ "github.com/concourse/atc/auth/uaa"
)

// overridden via linker flags
var Version = "0.0.0-dev"

func main() {
	var cmd ConcourseCommand

	cmd.Version = func() {
		fmt.Println(Version)
		os.Exit(0)
	}

	parser := flags.NewParser(&cmd, flags.HelpFlag|flags.PassDoubleDash)
	parser.NamespaceDelimiter = "-"

	cmd.lessenRequirements(parser)

	twentythousandtonnesofcrudeoil.TheEnvironmentIsPerfectlySafe(parser, "CONCOURSE_")

	authConfigs := make(provider.AuthConfigs)

	for name, p := range provider.GetProviders() {
		authGroup := p.AuthGroup()

		group, err := parser.Command.Group.AddGroup(authGroup.Name(), "", authGroup.AuthConfig())
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		group.Namespace = authGroup.Namespace()

		authConfigs[name] = authGroup.AuthConfig()
	}

	_, err := parser.Parse()

	cmd.Web.ProviderAuth = authConfigs

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package apns

import (
	"bytes"
	"crypto/tls"
	"encoding/binary"
	"errors"
	"github.com/zhangpeihao/log"
	"net"
	"time"
)

const (
	MIN_QUEUE_SIZE = 8
)

var (
	LOG_HEADERS  = []string{"Out", "Out_E"}
	logger       *log.Logger
	READ_TIMEOUT = time.Second * 3600
)

var (
	ErrClosed  = errors.New("Closed")
	ErrBlocked = errors.New("Blocked")
)

func InitLog(l *log.Logger) {
	logger = l
	logger.Println("InitLog()")
}

type Conn struct {
	c           *tls.Conn
	sendTimeout time.Duration
	exit        bool
}

func Dial(serverAddress string, cert []tls.Certificate,
	sendTimeout time.Duration) (c *Conn, err error) {
	var conn net.Conn
	if conn, err = net.DialTimeout("tcp", serverAddress, sendTimeout); err != nil {
		return
	}
	tlsConn := tls.Client(conn, &tls.Config{
		Certificates: cert,
	})
	if err = tlsConn.SetDeadline(time.Now().Add(sendTimeout)); err != nil {
		return
	}
	logger.Debugln("apnd.Dial() Handshake")
	if err = tlsConn.Handshake(); err != nil {
		logger.Debugln("apnd.Dial() Handshake failed")
		return
	}
	logger.Debugln("apnd.Dial() Handshake success")
	c = &Conn{
		c:           tlsConn,
		sendTimeout: sendTimeout,
	}

	go c.readLoop()
	return
}

func (c *Conn) Close() {
	c.exit = true
	c.c.Close()
}

func (c *Conn) readLoop() {
	//	var err error
	if err := c.c.SetReadDeadline(time.Unix(9999999999, 0)); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::readLoop() SetReadDeadline err:", err)
		c.Close()
		return
	}
	buf := make([]byte, 6)
	for !c.exit {
		// read response
		if n, err := c.c.Read(buf); err != nil {
			netErr, ok := err.(net.Error)
			if ok && netErr.Temporary() {
				time.Sleep(time.Second)
			} else {
				logger.Add("Out_E", int64(1))
				logger.Debugln("apns.Conn::readLoop() Read err:", err)
				if n > 0 {
					logger.Debugf("APNS read %02X\n", buf)
				}
				break
			}
		} else {
			logger.Debugf("APNS read %02X\n", buf)
		}
	}
	c.Close()
}

func (c *Conn) Send(data []byte) (err error) {
	if c.exit {
		return ErrClosed
	}
	if err = c.c.SetWriteDeadline(time.Now().Add(c.sendTimeout)); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::Send() SetWriteDeadline err:", err)
		return
	}
	logger.Debugf("sendLoop() data: % 02X\n", data)
	if _, err = c.c.Write(data); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::Send() Write err:", err)
		return
	}

	logger.Add("Out", int64(1))
	return
}

func (c *Conn) SendMessage(deviceToken []byte, message []byte) (err error) {
	buf := new(bytes.Buffer)
	if _, err = buf.Write([]byte{0, 0, 32}); err != nil {
		return
	}
	if _, err = buf.Write(deviceToken); err != nil {
		return
	}
	if err = binary.Write(buf, binary.BigEndian, uint16(len(message))); err != nil {
		return
	}
	if _, err = buf.Write(message); err != nil {
		return
	}
	return c.Send(buf.Bytes())
}
<commit_msg>Append handshake timeout<commit_after>package apns

import (
	"bytes"
	"crypto/tls"
	"encoding/binary"
	"errors"
	"github.com/zhangpeihao/log"
	"net"
	"time"
)

const (
	MIN_QUEUE_SIZE = 8
)

var (
	LOG_HEADERS  = []string{"Out", "Out_E"}
	logger       *log.Logger
	READ_TIMEOUT = time.Second * 3600
)

var (
	ErrClosed  = errors.New("Closed")
	ErrBlocked = errors.New("Blocked")
)

func InitLog(l *log.Logger) {
	logger = l
	logger.Println("InitLog()")
}

type Conn struct {
	c           *tls.Conn
	sendTimeout time.Duration
	exit        bool
}

func Dial(serverAddress string, cert []tls.Certificate,
	sendTimeout time.Duration) (c *Conn, err error) {
	var conn net.Conn
	if conn, err = net.DialTimeout("tcp", serverAddress, sendTimeout); err != nil {
		return
	}
	tlsConn := tls.Client(conn, &tls.Config{
		Certificates: cert,
	})
	if err = tlsConn.SetWriteDeadline(time.Now().Add(sendTimeout)); err != nil {
		return
	}
	handshakeChan := make(chan bool)
	go func(ch chan<- bool) {
		logger.Debugln("apnd.Dial() Handshake")
		if err = tlsConn.Handshake(); err != nil {
			logger.Debugln("apnd.Dial() Handshake failed")
			ch <- false
		}
		logger.Debugln("apnd.Dial() Handshake success")
		ch <- true
	}(handshakeChan)
	select {
	case b := <-handshakeChan:
		if !b {
			return
		}
	case <-time.After(time.Second * time.Duration(5)):
		logger.Debugln("apnd.Dial() Handshake timeout")
		tlsConn.Close()
		return
	}
	c = &Conn{
		c:           tlsConn,
		sendTimeout: sendTimeout,
	}

	go c.readLoop()
	return
}

func (c *Conn) Close() {
	c.exit = true
	c.c.Close()
}

func (c *Conn) readLoop() {
	//	var err error
	if err := c.c.SetReadDeadline(time.Unix(9999999999, 0)); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::readLoop() SetReadDeadline err:", err)
		c.Close()
		return
	}
	buf := make([]byte, 6)
	for !c.exit {
		// read response
		if n, err := c.c.Read(buf); err != nil {
			netErr, ok := err.(net.Error)
			if ok && netErr.Temporary() {
				time.Sleep(time.Second)
			} else {
				logger.Add("Out_E", int64(1))
				logger.Debugln("apns.Conn::readLoop() Read err:", err)
				if n > 0 {
					logger.Debugf("APNS read %02X\n", buf)
				}
				break
			}
		} else {
			logger.Debugf("APNS read %02X\n", buf)
		}
	}
	c.Close()
}

func (c *Conn) Send(data []byte) (err error) {
	if c.exit {
		return ErrClosed
	}
	if err = c.c.SetWriteDeadline(time.Now().Add(c.sendTimeout)); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::Send() SetWriteDeadline err:", err)
		return
	}
	logger.Debugf("sendLoop() data: % 02X\n", data)
	if _, err = c.c.Write(data); err != nil {
		logger.Add("Out_E", int64(1))
		logger.Warningln("apns.Conn::Send() Write err:", err)
		return
	}

	logger.Add("Out", int64(1))
	return
}

func (c *Conn) SendMessage(deviceToken []byte, message []byte) (err error) {
	buf := new(bytes.Buffer)
	if _, err = buf.Write([]byte{0, 0, 32}); err != nil {
		return
	}
	if _, err = buf.Write(deviceToken); err != nil {
		return
	}
	if err = binary.Write(buf, binary.BigEndian, uint16(len(message))); err != nil {
		return
	}
	if _, err = buf.Write(message); err != nil {
		return
	}
	return c.Send(buf.Bytes())
}
<|endoftext|>


<commit_before>package main

// This is a direct port of https://gist.github.com/benjojo/0124c7875113831a4274

import (
	"fmt"
	"strconv"
	"strings"
)

// PacketType can be:
// * Status Report
// * GPGGA
type APRSPacket struct {
	Callsign      string // Done!
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string // Done!
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.Contains(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	p = APRSPacket{}
	CommaParts := strings.Split(input, ",")
	RouteString := CommaParts[0]
	RouteParts := strings.Split(RouteString, ">")
	if len(RouteParts) != 2 {
		e = fmt.Errorf("There was not one > in the route part of the packet, dunno how to decode this")
		return p, e
	}
	p.Callsign = RouteParts[0]
	p.Destination = RouteParts[1]

	LocationOfStatusMarker := strings.Index(input, ":>")
	LocationOfNormalMarker := strings.Index(input, ">")

	if LocationOfStatusMarker > LocationOfNormalMarker {
		p.PacketType = "Status Report"
		RawArray := []byte(input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+(len(input)-LocationOfStatusMarker-2)])
		if len(RawArray) > 6 && strings.ToLower(string(RawArray[6])) == "z" {
			p.GPSTime = input[LocationOfStatusMarker+2 : LocationOfStatusMarker+8]
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-9]
		} else {
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-2]
		}
	}

	// Test if the packet is a GPGGA packet
	if strings.Contains(input, ":$GPGGA,") {
		p.PacketType = "GPGGA"
		GPGGALocation := strings.Index(input, ":$GPGGA,")
		RawData := input[GPGGALocation : GPGGALocation+(len(input)-GPGGALocation)]
		SplitData := strings.Split(RawData, ",")
		if len(SplitData) < 9 {
			e = fmt.Errorf("There was not enough data inside the GPGGA packet to decode it")
			return p, e
		}
		p.GPSTime = SplitData[1]

		// Lat
		DegLatitude := SplitData[2]
		DegLatMin, e := strconv.ParseFloat(DegLatitude[2:2+len(DegLatitude)-2], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLatMin part of the GPGGA packet")
			return p, e
		}
		DegLatMin = DegLatMin / 60
		StrDegLatMin := fmt.Sprintf("%f", DegLatMin)
		p.Latitude = fmt.Sprintf("%s%s", DegLatitude[:2], StrDegLatMin[1:len(StrDegLatMin)-1])

		if Split[3] == "S" {
			p.Latitude = fmt.Sprintf("-%s", p.Latitude)
		}

		// Long
		DegLongitude := SplitData[4]
		DegLonMin, e := strconv.ParseFloat(DegLongitude[3:3+len(DegLongitude)-3], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLonMin part of the GPGGA packet")
			return p, e
		}
		DegLonMin = DegLonMin / 60
		StrDegLonMin := fmt.Sprintf("%f", DegLonMin)
		p.Longitude = fmt.Sprintf("%s%s", DegLongitude[:3], StrDegLonMin[1:len(StrDegLonMin)-1])

		if Split[3] == "W" {
			p.Longitude = fmt.Sprintf("-%s", p.Longitude)
		}

		f, e := strconv.ParseFloat(SplitData[9], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the Altitude part of the GPGGA packet")
			return p, e
		}
		p.Altitude = fmt.Sprintf("%f", f)
	}

	return p, e
}
<commit_msg>Fixed compile breaking typo<commit_after>package main

// This is a direct port of https://gist.github.com/benjojo/0124c7875113831a4274

import (
	"fmt"
	"strconv"
	"strings"
)

// PacketType can be:
// * Status Report
// * GPGGA
type APRSPacket struct {
	Callsign      string // Done!
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string // Done!
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.Contains(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	p = APRSPacket{}
	CommaParts := strings.Split(input, ",")
	RouteString := CommaParts[0]
	RouteParts := strings.Split(RouteString, ">")
	if len(RouteParts) != 2 {
		e = fmt.Errorf("There was not one > in the route part of the packet, dunno how to decode this")
		return p, e
	}
	p.Callsign = RouteParts[0]
	p.Destination = RouteParts[1]

	LocationOfStatusMarker := strings.Index(input, ":>")
	LocationOfNormalMarker := strings.Index(input, ">")

	if LocationOfStatusMarker > LocationOfNormalMarker {
		p.PacketType = "Status Report"
		RawArray := []byte(input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+(len(input)-LocationOfStatusMarker-2)])
		if len(RawArray) > 6 && strings.ToLower(string(RawArray[6])) == "z" {
			p.GPSTime = input[LocationOfStatusMarker+2 : LocationOfStatusMarker+8]
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-9]
		} else {
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-2]
		}
	}

	// Test if the packet is a GPGGA packet
	if strings.Contains(input, ":$GPGGA,") {
		p.PacketType = "GPGGA"
		GPGGALocation := strings.Index(input, ":$GPGGA,")
		RawData := input[GPGGALocation : GPGGALocation+(len(input)-GPGGALocation)]
		SplitData := strings.Split(RawData, ",")
		if len(SplitData) < 9 {
			e = fmt.Errorf("There was not enough data inside the GPGGA packet to decode it")
			return p, e
		}
		p.GPSTime = SplitData[1]

		// Lat
		DegLatitude := SplitData[2]
		DegLatMin, e := strconv.ParseFloat(DegLatitude[2:2+len(DegLatitude)-2], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLatMin part of the GPGGA packet")
			return p, e
		}
		DegLatMin = DegLatMin / 60
		StrDegLatMin := fmt.Sprintf("%f", DegLatMin)
		p.Latitude = fmt.Sprintf("%s%s", DegLatitude[:2], StrDegLatMin[1:len(StrDegLatMin)-1])

		if SplitData[3] == "S" {
			p.Latitude = fmt.Sprintf("-%s", p.Latitude)
		}

		// Long
		DegLongitude := SplitData[4]
		DegLonMin, e := strconv.ParseFloat(DegLongitude[3:3+len(DegLongitude)-3], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLonMin part of the GPGGA packet")
			return p, e
		}
		DegLonMin = DegLonMin / 60
		StrDegLonMin := fmt.Sprintf("%f", DegLonMin)
		p.Longitude = fmt.Sprintf("%s%s", DegLongitude[:3], StrDegLonMin[1:len(StrDegLonMin)-1])

		if SplitData[3] == "W" {
			p.Longitude = fmt.Sprintf("-%s", p.Longitude)
		}

		f, e := strconv.ParseFloat(SplitData[9], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the Altitude part of the GPGGA packet")
			return p, e
		}
		p.Altitude = fmt.Sprintf("%f", f)
	}

	return p, e
}
<|endoftext|>


<commit_before>// +build !windows

package gottyclient

import (
	"encoding/json"
	"fmt"
	"golang.org/x/sys/unix"
	"os"
	"os/signal"
	"syscall"
)

func notifySignalSIGWINCH(c chan<- os.Signal) {
	signal.Notify(c, syscall.SIGWINCH)
}

func resetSignalSIGWINCH() {
	signal.Reset(syscall.SIGWINCH)
}

func syscallTIOCGWINSZ() ([]byte, error) {
	ws, err := unix.IoctlGetWinsize(0, 0)
	if err != nil {
		return nil, fmt.Errorf("ioctl error: %v", err)
	}
	b, err := json.Marshal(ws)
	if err != nil {
		return nil, fmt.Errorf("json.Marshal error: %v", err)
	}
	return b, err
}
<commit_msg>Fix bug when resizing terminal<commit_after>// +build !windows

package gottyclient

import (
	"encoding/json"
	"fmt"
	"golang.org/x/sys/unix"
	"os"
	"os/signal"
	"syscall"
)

func notifySignalSIGWINCH(c chan<- os.Signal) {
	signal.Notify(c, syscall.SIGWINCH)
}

func resetSignalSIGWINCH() {
	signal.Reset(syscall.SIGWINCH)
}

func syscallTIOCGWINSZ() ([]byte, error) {
	ws, err := unix.IoctlGetWinsize(0, 0)
	if err != nil {
		return nil, fmt.Errorf("ioctl error: %v", err)
	}
	tws := winsize{Rows: ws.Row, Columns: ws.Col}
	b, err := json.Marshal(tws)
	if err != nil {
		return nil, fmt.Errorf("json.Marshal error: %v", err)
	}
	return b, err
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
	"context"
	"encoding/base64"
	"errors"
	"net/http"
	"path"
	"strings"

	jsoniter "github.com/json-iterator/go"
	xhttp "github.com/minio/minio/cmd/http"
	"github.com/minio/minio/cmd/logger"
)

type ssekms struct{}

var (
	// S3KMS represents AWS SSE-KMS. It provides functionality to
	// handle SSE-KMS requests.
	S3KMS = ssekms{}

	_ Type = S3KMS
)

// String returns the SSE domain as string. For SSE-KMS the
// domain is "SSE-KMS".
func (ssekms) String() string { return "SSE-KMS" }

// IsRequested returns true if the HTTP headers contains
// at least one SSE-KMS header.
func (ssekms) IsRequested(h http.Header) bool {
	if _, ok := h[xhttp.AmzServerSideEncryptionKmsID]; ok {
		return true
	}
	if _, ok := h[xhttp.AmzServerSideEncryptionKmsContext]; ok {
		return true
	}
	if _, ok := h[xhttp.AmzServerSideEncryption]; ok {
		return strings.ToUpper(h.Get(xhttp.AmzServerSideEncryption)) != xhttp.AmzEncryptionAES // Return only true if the SSE header is specified and does not contain the SSE-S3 value
	}
	return false
}

// ParseHTTP parses the SSE-KMS headers and returns the SSE-KMS key ID
// and the KMS context on success.
func (ssekms) ParseHTTP(h http.Header) (string, Context, error) {
	algorithm := h.Get(xhttp.AmzServerSideEncryption)
	if algorithm != xhttp.AmzEncryptionKMS {
		return "", nil, ErrInvalidEncryptionMethod
	}

	var ctx Context
	if context, ok := h[xhttp.AmzServerSideEncryptionKmsContext]; ok {
		b, err := base64.StdEncoding.DecodeString(context[0])
		if err != nil {
			return "", nil, err
		}

		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		if err := json.Unmarshal(b, &ctx); err != nil {
			return "", nil, err
		}
	}
	return h.Get(xhttp.AmzServerSideEncryptionKmsID), ctx, nil
}

// IsEncrypted returns true if the object metadata indicates
// that the object was uploaded using SSE-KMS.
func (ssekms) IsEncrypted(metadata map[string]string) bool {
	if _, ok := metadata[MetaSealedKeyKMS]; ok {
		return true
	}
	return false
}

// UnsealObjectKey extracts and decrypts the sealed object key
// from the metadata using KMS and returns the decrypted object
// key.
func (s3 ssekms) UnsealObjectKey(kms KMS, metadata map[string]string, bucket, object string) (key ObjectKey, err error) {
	keyID, kmsKey, sealedKey, ctx, err := s3.ParseMetadata(metadata)
	if err != nil {
		return key, err
	}
	if _, ok := ctx[bucket]; !ok {
		ctx[bucket] = path.Join(bucket, object)
	}
	unsealKey, err := kms.DecryptKey(keyID, kmsKey, ctx)
	if err != nil {
		return key, err
	}
	err = key.Unseal(unsealKey[:], sealedKey, s3.String(), bucket, object)
	return key, err
}

// CreateMetadata encodes the sealed object key into the metadata and returns
// the modified metadata. If the keyID and the kmsKey is not empty it encodes
// both into the metadata as well. It allocates a new metadata map if metadata
// is nil.
func (ssekms) CreateMetadata(metadata map[string]string, keyID string, kmsKey []byte, sealedKey SealedKey, ctx Context) map[string]string {
	if sealedKey.Algorithm != SealAlgorithm {
		logger.CriticalIf(context.Background(), Errorf("The seal algorithm '%s' is invalid for SSE-S3", sealedKey.Algorithm))
	}

	// There are two possibilites:
	// - We use a KMS -> There must be non-empty key ID and a KMS data key.
	// - We use a K/V -> There must be no key ID and no KMS data key.
	// Otherwise, the caller has passed an invalid argument combination.
	if keyID == "" && len(kmsKey) != 0 {
		logger.CriticalIf(context.Background(), errors.New("The key ID must not be empty if a KMS data key is present"))
	}
	if keyID != "" && len(kmsKey) == 0 {
		logger.CriticalIf(context.Background(), errors.New("The KMS data key must not be empty if a key ID is present"))
	}

	if metadata == nil {
		metadata = make(map[string]string, 5)
	}

	metadata[MetaAlgorithm] = sealedKey.Algorithm
	metadata[MetaIV] = base64.StdEncoding.EncodeToString(sealedKey.IV[:])
	metadata[MetaSealedKeyKMS] = base64.StdEncoding.EncodeToString(sealedKey.Key[:])
	if len(ctx) > 0 {
		b, _ := ctx.MarshalText()
		metadata[MetaContext] = base64.StdEncoding.EncodeToString(b)
	}
	if len(kmsKey) > 0 && keyID != "" { // We use a KMS -> Store key ID and sealed KMS data key.
		metadata[MetaKeyID] = keyID
		metadata[MetaDataEncryptionKey] = base64.StdEncoding.EncodeToString(kmsKey)
	}
	return metadata
}

// ParseMetadata extracts all SSE-KMS related values from the object metadata
// and checks whether they are well-formed. It returns the sealed object key
// on success. If the metadata contains both, a KMS master key ID and a sealed
// KMS data key it returns both. If the metadata does not contain neither a
// KMS master key ID nor a sealed KMS data key it returns an empty keyID and
// KMS data key. Otherwise, it returns an error.
func (ssekms) ParseMetadata(metadata map[string]string) (keyID string, kmsKey []byte, sealedKey SealedKey, ctx Context, err error) {
	// Extract all required values from object metadata
	b64IV, ok := metadata[MetaIV]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, errMissingInternalIV
	}
	algorithm, ok := metadata[MetaAlgorithm]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, errMissingInternalSealAlgorithm
	}
	b64SealedKey, ok := metadata[MetaSealedKeyKMS]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal sealed key for SSE-S3")
	}

	// There are two possibilites:
	// - We use a KMS -> There must be a key ID and a KMS data key.
	// - We use a K/V -> There must be no key ID and no KMS data key.
	// Otherwise, the metadata is corrupted.
	keyID, idPresent := metadata[MetaKeyID]
	b64KMSSealedKey, kmsKeyPresent := metadata[MetaDataEncryptionKey]
	if !idPresent && kmsKeyPresent {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal KMS key-ID for SSE-S3")
	}
	if idPresent && !kmsKeyPresent {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal sealed KMS data key for SSE-S3")
	}

	// Check whether all extracted values are well-formed
	iv, err := base64.StdEncoding.DecodeString(b64IV)
	if err != nil || len(iv) != 32 {
		return keyID, kmsKey, sealedKey, ctx, errInvalidInternalIV
	}
	if algorithm != SealAlgorithm {
		return keyID, kmsKey, sealedKey, ctx, errInvalidInternalSealAlgorithm
	}
	encryptedKey, err := base64.StdEncoding.DecodeString(b64SealedKey)
	if err != nil || len(encryptedKey) != 64 {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed key for SSE-KMS is invalid")
	}
	if idPresent && kmsKeyPresent { // We are using a KMS -> parse the sealed KMS data key.
		kmsKey, err = base64.StdEncoding.DecodeString(b64KMSSealedKey)
		if err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed KMS data key for SSE-KMS is invalid")
		}
	}
	b64Ctx, ok := metadata[MetaContext]
	if ok {
		b, err := base64.StdEncoding.DecodeString(b64Ctx)
		if err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal KMS context is not base64-encoded")
		}
		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		if err = json.Unmarshal(b, ctx); err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed KMS context is invalid")
		}
	}

	sealedKey.Algorithm = algorithm
	copy(sealedKey.IV[:], iv)
	copy(sealedKey.Key[:], encryptedKey)
	return keyID, kmsKey, sealedKey, ctx, nil
}
<commit_msg>sse-kms: fix assignment to potential nil map (#12250)<commit_after>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package crypto

import (
	"context"
	"encoding/base64"
	"errors"
	"net/http"
	"path"
	"strings"

	jsoniter "github.com/json-iterator/go"
	xhttp "github.com/minio/minio/cmd/http"
	"github.com/minio/minio/cmd/logger"
	"github.com/minio/minio/pkg/kms"
)

type ssekms struct{}

var (
	// S3KMS represents AWS SSE-KMS. It provides functionality to
	// handle SSE-KMS requests.
	S3KMS = ssekms{}

	_ Type = S3KMS
)

// String returns the SSE domain as string. For SSE-KMS the
// domain is "SSE-KMS".
func (ssekms) String() string { return "SSE-KMS" }

// IsRequested returns true if the HTTP headers contains
// at least one SSE-KMS header.
func (ssekms) IsRequested(h http.Header) bool {
	if _, ok := h[xhttp.AmzServerSideEncryptionKmsID]; ok {
		return true
	}
	if _, ok := h[xhttp.AmzServerSideEncryptionKmsContext]; ok {
		return true
	}
	if _, ok := h[xhttp.AmzServerSideEncryption]; ok {
		return strings.ToUpper(h.Get(xhttp.AmzServerSideEncryption)) != xhttp.AmzEncryptionAES // Return only true if the SSE header is specified and does not contain the SSE-S3 value
	}
	return false
}

// ParseHTTP parses the SSE-KMS headers and returns the SSE-KMS key ID
// and the KMS context on success.
func (ssekms) ParseHTTP(h http.Header) (string, Context, error) {
	algorithm := h.Get(xhttp.AmzServerSideEncryption)
	if algorithm != xhttp.AmzEncryptionKMS {
		return "", nil, ErrInvalidEncryptionMethod
	}

	var ctx Context
	if context, ok := h[xhttp.AmzServerSideEncryptionKmsContext]; ok {
		b, err := base64.StdEncoding.DecodeString(context[0])
		if err != nil {
			return "", nil, err
		}

		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		if err := json.Unmarshal(b, &ctx); err != nil {
			return "", nil, err
		}
	}
	return h.Get(xhttp.AmzServerSideEncryptionKmsID), ctx, nil
}

// IsEncrypted returns true if the object metadata indicates
// that the object was uploaded using SSE-KMS.
func (ssekms) IsEncrypted(metadata map[string]string) bool {
	if _, ok := metadata[MetaSealedKeyKMS]; ok {
		return true
	}
	return false
}

// UnsealObjectKey extracts and decrypts the sealed object key
// from the metadata using KMS and returns the decrypted object
// key.
func (s3 ssekms) UnsealObjectKey(KMS kms.KMS, metadata map[string]string, bucket, object string) (key ObjectKey, err error) {
	keyID, kmsKey, sealedKey, ctx, err := s3.ParseMetadata(metadata)
	if err != nil {
		return key, err
	}
	if ctx == nil {
		ctx = kms.Context{bucket: path.Join(bucket, object)}
	} else if _, ok := ctx[bucket]; !ok {
		ctx[bucket] = path.Join(bucket, object)
	}
	unsealKey, err := KMS.DecryptKey(keyID, kmsKey, ctx)
	if err != nil {
		return key, err
	}
	err = key.Unseal(unsealKey[:], sealedKey, s3.String(), bucket, object)
	return key, err
}

// CreateMetadata encodes the sealed object key into the metadata and returns
// the modified metadata. If the keyID and the kmsKey is not empty it encodes
// both into the metadata as well. It allocates a new metadata map if metadata
// is nil.
func (ssekms) CreateMetadata(metadata map[string]string, keyID string, kmsKey []byte, sealedKey SealedKey, ctx Context) map[string]string {
	if sealedKey.Algorithm != SealAlgorithm {
		logger.CriticalIf(context.Background(), Errorf("The seal algorithm '%s' is invalid for SSE-S3", sealedKey.Algorithm))
	}

	// There are two possibilites:
	// - We use a KMS -> There must be non-empty key ID and a KMS data key.
	// - We use a K/V -> There must be no key ID and no KMS data key.
	// Otherwise, the caller has passed an invalid argument combination.
	if keyID == "" && len(kmsKey) != 0 {
		logger.CriticalIf(context.Background(), errors.New("The key ID must not be empty if a KMS data key is present"))
	}
	if keyID != "" && len(kmsKey) == 0 {
		logger.CriticalIf(context.Background(), errors.New("The KMS data key must not be empty if a key ID is present"))
	}

	if metadata == nil {
		metadata = make(map[string]string, 5)
	}

	metadata[MetaAlgorithm] = sealedKey.Algorithm
	metadata[MetaIV] = base64.StdEncoding.EncodeToString(sealedKey.IV[:])
	metadata[MetaSealedKeyKMS] = base64.StdEncoding.EncodeToString(sealedKey.Key[:])
	if len(ctx) > 0 {
		b, _ := ctx.MarshalText()
		metadata[MetaContext] = base64.StdEncoding.EncodeToString(b)
	}
	if len(kmsKey) > 0 && keyID != "" { // We use a KMS -> Store key ID and sealed KMS data key.
		metadata[MetaKeyID] = keyID
		metadata[MetaDataEncryptionKey] = base64.StdEncoding.EncodeToString(kmsKey)
	}
	return metadata
}

// ParseMetadata extracts all SSE-KMS related values from the object metadata
// and checks whether they are well-formed. It returns the sealed object key
// on success. If the metadata contains both, a KMS master key ID and a sealed
// KMS data key it returns both. If the metadata does not contain neither a
// KMS master key ID nor a sealed KMS data key it returns an empty keyID and
// KMS data key. Otherwise, it returns an error.
func (ssekms) ParseMetadata(metadata map[string]string) (keyID string, kmsKey []byte, sealedKey SealedKey, ctx Context, err error) {
	// Extract all required values from object metadata
	b64IV, ok := metadata[MetaIV]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, errMissingInternalIV
	}
	algorithm, ok := metadata[MetaAlgorithm]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, errMissingInternalSealAlgorithm
	}
	b64SealedKey, ok := metadata[MetaSealedKeyKMS]
	if !ok {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal sealed key for SSE-S3")
	}

	// There are two possibilites:
	// - We use a KMS -> There must be a key ID and a KMS data key.
	// - We use a K/V -> There must be no key ID and no KMS data key.
	// Otherwise, the metadata is corrupted.
	keyID, idPresent := metadata[MetaKeyID]
	b64KMSSealedKey, kmsKeyPresent := metadata[MetaDataEncryptionKey]
	if !idPresent && kmsKeyPresent {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal KMS key-ID for SSE-S3")
	}
	if idPresent && !kmsKeyPresent {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The object metadata is missing the internal sealed KMS data key for SSE-S3")
	}

	// Check whether all extracted values are well-formed
	iv, err := base64.StdEncoding.DecodeString(b64IV)
	if err != nil || len(iv) != 32 {
		return keyID, kmsKey, sealedKey, ctx, errInvalidInternalIV
	}
	if algorithm != SealAlgorithm {
		return keyID, kmsKey, sealedKey, ctx, errInvalidInternalSealAlgorithm
	}
	encryptedKey, err := base64.StdEncoding.DecodeString(b64SealedKey)
	if err != nil || len(encryptedKey) != 64 {
		return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed key for SSE-KMS is invalid")
	}
	if idPresent && kmsKeyPresent { // We are using a KMS -> parse the sealed KMS data key.
		kmsKey, err = base64.StdEncoding.DecodeString(b64KMSSealedKey)
		if err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed KMS data key for SSE-KMS is invalid")
		}
	}
	b64Ctx, ok := metadata[MetaContext]
	if ok {
		b, err := base64.StdEncoding.DecodeString(b64Ctx)
		if err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal KMS context is not base64-encoded")
		}
		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		if err = json.Unmarshal(b, ctx); err != nil {
			return keyID, kmsKey, sealedKey, ctx, Errorf("The internal sealed KMS context is invalid")
		}
	}

	sealedKey.Algorithm = algorithm
	copy(sealedKey.IV[:], iv)
	copy(sealedKey.Key[:], encryptedKey)
	return keyID, kmsKey, sealedKey, ctx, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/Symantec/Dominator/dom/herd"
	"github.com/Symantec/Dominator/dom/mdb"
	"os"
	"path"
	"runtime"
	"time"
)

var (
	debug       = flag.Bool("debug", false, "If true, show debugging output")
	minInterval = flag.Uint("minInterval", 1,
		"Minimum interval between loops (in seconds)")
	portNum = flag.Uint("portNum", 6970,
		"Port number to allocate and listen on for HTTP/RPC")
	stateDir = flag.String("stateDir", "/var/lib/Dominator",
		"Name of dominator state directory.")
)

func main() {
	flag.Parse()
	fi, err := os.Lstat(*stateDir)
	if err != nil {
		fmt.Printf("Cannot stat: %s\t%s\n", *stateDir, err)
		os.Exit(1)
	}
	if !fi.IsDir() {
		fmt.Printf("%s is not a directory\n", *stateDir)
		os.Exit(1)
	}
	mdbChannel := mdb.StartMdbDaemon(path.Join(*stateDir, "mdb"))
	interval, _ := time.ParseDuration(fmt.Sprintf("%ds", *minInterval))
	var herd herd.Herd
	for {
		minCycleStopTime := time.Now().Add(interval)
		select {
		case mdb := <-mdbChannel:
			herd.MdbUpdate(mdb)
			if *debug {
				b, _ := json.Marshal(mdb)
				var out bytes.Buffer
				json.Indent(&out, b, "", "    ")
				fmt.Println()
				out.WriteTo(os.Stdout)
				fmt.Println()
			}
		default:
			// Do work.
			herd.PollNextSub()
		}
		fmt.Print(".")
		runtime.GC() // An opportune time to take out the garbage.
		time.Sleep(minCycleStopTime.Sub(time.Now()))
	}
}
<commit_msg>Prevent Dominator from running as root.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/Symantec/Dominator/dom/herd"
	"github.com/Symantec/Dominator/dom/mdb"
	"os"
	"path"
	"runtime"
	"time"
)

var (
	debug       = flag.Bool("debug", false, "If true, show debugging output")
	minInterval = flag.Uint("minInterval", 1,
		"Minimum interval between loops (in seconds)")
	portNum = flag.Uint("portNum", 6970,
		"Port number to allocate and listen on for HTTP/RPC")
	stateDir = flag.String("stateDir", "/var/lib/Dominator",
		"Name of dominator state directory.")
)

func main() {
	flag.Parse()
	if os.Geteuid() == 0 {
		fmt.Println("Do not run the Dominator as root")
		os.Exit(1)
	}
	fi, err := os.Lstat(*stateDir)
	if err != nil {
		fmt.Printf("Cannot stat: %s\t%s\n", *stateDir, err)
		os.Exit(1)
	}
	if !fi.IsDir() {
		fmt.Printf("%s is not a directory\n", *stateDir)
		os.Exit(1)
	}
	mdbChannel := mdb.StartMdbDaemon(path.Join(*stateDir, "mdb"))
	interval, _ := time.ParseDuration(fmt.Sprintf("%ds", *minInterval))
	var herd herd.Herd
	for {
		minCycleStopTime := time.Now().Add(interval)
		select {
		case mdb := <-mdbChannel:
			herd.MdbUpdate(mdb)
			if *debug {
				b, _ := json.Marshal(mdb)
				var out bytes.Buffer
				json.Indent(&out, b, "", "    ")
				fmt.Println()
				out.WriteTo(os.Stdout)
				fmt.Println()
			}
		default:
			// Do work.
			herd.PollNextSub()
		}
		fmt.Print(".")
		runtime.GC() // An opportune time to take out the garbage.
		time.Sleep(minCycleStopTime.Sub(time.Now()))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"image"
	"image/draw"
	"image/gif"
	_ "image/png"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"

	_ "golang.org/x/image/bmp"

	"github.com/codegangsta/cli"
	"github.com/disintegration/imaging"
	"github.com/kevin-cantwell/dotmatrix"
	"github.com/nfnt/resize"
	"golang.org/x/crypto/ssh/terminal"
)

func main() {
	app := cli.NewApp()
	app.Version = "0.1.0"
	app.Name = "dotmatrix"
	app.Usage = "A command-line tool for encoding images as unicode braille symbols."
	app.UsageText = "1) dotmatrix [options] [file|url]\n" +
		/*      */ "   2) dotmatrix [options] < [file]"
	app.Author = "Kevin Cantwell"
	app.Email = "kevin.cantwell@gmail.com"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "invert,i",
			Usage: "Inverts image color. Useful for black background terminals",
		},
		cli.Float64Flag{
			Name:  "gamma,g",
			Usage: "GAMMA less than 0 darkens the image and GAMMA greater than 0 lightens it.",
		},
		cli.Float64Flag{
			Name:  "brightness,b",
			Usage: "BRIGHTNESS = -100 gives solid black image. BRIGHTNESS = 100 gives solid white image.",
			Value: 0.0,
		},
		cli.Float64Flag{
			Name:  "contrast,c",
			Usage: "CONTRAST = -100 gives solid grey image. CONTRAST = 100 gives maximum contrast.",
			Value: 0.0,
		},
		cli.Float64Flag{
			Name:  "sharpen,s",
			Usage: "SHARPEN greater than 0 sharpens the image.",
			Value: 0.0,
		},
		cli.BoolFlag{
			Name:  "mirror,m",
			Usage: "Mirrors the image.",
		},
		cli.BoolFlag{
			Name:  "mono",
			Usage: "Images are drawn without Floyd Steinberg diffusion.",
		},
		cli.BoolFlag{
			Name:  "motion,mjpeg",
			Usage: "Interpret input as an mjpeg stream, such as from a webcam.",
		},
		cli.IntFlag{
			Name:  "framerate,fps",
			Usage: "Force a framerate for mjpeg streams. Default is -1 (ie: no delay between frames).",
			Value: -1,
		},
	}
	app.Action = func(c *cli.Context) error {
		reader, mimeType, err := decodeReader(c)
		if err != nil {
			return err
		}

		if c.Bool("motion") {
			return mjpegAction(c, reader, c.Int("framerate"))
		}

		switch mimeType {
		// case "video/mp4", "video/avi", "video/webm":
		// 	return videoAction(c, reader)
		case "video/x-motion-jpeg":
			return mjpegAction(c, reader, c.Int("framerate"))
		case "image/gif":
			return gifAction(c, reader)
		default:
			return imageAction(c, reader)
		}
	}

	if err := app.Run(os.Args); err != nil {
		exit(err.Error(), 1)
	}
}

func config(c *cli.Context) *dotmatrix.Config {
	return &dotmatrix.Config{
		Filter: &Filter{
			Gamma:      c.Float64("gamma"),
			Brightness: c.Float64("brightness"),
			Contrast:   c.Float64("contrast"),
			Sharpen:    c.Float64("sharpen"),
			Invert:     c.Bool("invert"),
			Mirror:     c.Bool("mirror"),
		},
		Drawer: func() draw.Drawer {
			if c.Bool("mono") {
				return draw.Src
			}
			return draw.FloydSteinberg
		}(),
	}
}

func imageAction(c *cli.Context, r io.Reader) error {
	img, _, err := image.Decode(r)
	if err != nil {
		return err
	}
	return dotmatrix.NewPrinter(os.Stdout, config(c)).Print(img)
}

func gifAction(c *cli.Context, r io.Reader) error {
	giff, err := gif.DecodeAll(r)
	if err != nil {
		return err
	}
	return dotmatrix.NewGIFPrinter(os.Stdout, config(c)).Print(giff)
}

func mjpegAction(c *cli.Context, r io.Reader, fps int) error {
	return dotmatrix.NewMJPEGPrinter(os.Stdout, config(c)).Print(r, fps)
}

func videoAction(c *cli.Context, r io.Reader) error {
	fmt.Println("ffmpeg", "-i", "pipe:0", "-f", "mjpeg", "-r", "15", "-loglevel", "error", "pipe:1")
	cmd := exec.Command("ffmpeg", "-i", "pipe:0", "-f", "mjpeg", "-r", "15", "-loglevel", "error", "pipe:1")
	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	cmd.Stderr = os.Stderr
	cmd.Stdin = r
	if err := cmd.Start(); err != nil {
		return err
	}
	go func() {
		if err := cmd.Wait(); err != nil {
			exit(err.Error(), 1)
		}
	}()

	return mjpegAction(c, stdoutPipe, 15)
}

func cameraAction(c *cli.Context) error {
	cmd := exec.Command("ffmpeg", "-r", "30", "-f", "avfoundation", "-i", "FaceTime", "-vf", "hflip", "-s", "640x480", "-f", "mjpeg", "-loglevel", "error", "pipe:1")
	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		return err
	}
	go func() {
		if err := cmd.Wait(); err != nil {
			exit(err.Error(), 1)
		}
	}()

	return mjpegAction(c, stdoutPipe, -1)
}

func decodeReader(c *cli.Context) (io.Reader, string, error) {
	var reader io.Reader = os.Stdin

	// Assign to reader
	if input := c.Args().First(); input != "" {
		// Is it a file?
		if !strings.HasPrefix(input, "http://") && !strings.HasPrefix(input, "https://") {
			file, err := os.Open(input)
			if err != nil {
				return nil, "", err
			}
			reader = file
		} else {
			// Is it a url?
			if resp, err := http.Get(input); err != nil {
				return nil, "", err
			} else {
				reader = resp.Body
			}
		}
	}

	bufioReader := bufio.NewReader(reader)

	peeked, err := bufioReader.Peek(512)
	if err != nil {
		return nil, "", err
	}

	mimeType := http.DetectContentType(peeked)
	// // See if it's an mjpeg stream
	// if mimeType == "image/jpeg" {
	// 	bufioReader.
	// }

	return bufioReader, mimeType, nil
}

type Filter struct {
	// Gamma less than 0 darkens the image and GAMMA greater than 0 lightens it.
	Gamma float64
	// Brightness = -100 gives solid black image. Brightness = 100 gives solid white image.
	Brightness float64
	// Contrast = -100 gives solid grey image. Contrast = 100 gives maximum contrast.
	Contrast float64
	// Sharpen greater than 0 sharpens the image.
	Sharpen float64
	// Inverts pixel color. Transparent pixels remain transparent.
	Invert bool
	// Mirror flips the image on it's vertical axis
	Mirror bool

	scale float64
}

func (f *Filter) Filter(img image.Image) image.Image {
	if f.Gamma != 0 {
		img = imaging.AdjustGamma(img, f.Gamma+1.0)
	}
	if f.Brightness != 0 {
		img = imaging.AdjustBrightness(img, f.Brightness)
	}
	if f.Sharpen != 0 {
		img = imaging.Sharpen(img, f.Sharpen)
	}
	if f.Contrast != 0 {
		img = imaging.AdjustContrast(img, f.Contrast)
	}
	if f.Mirror {
		img = imaging.FlipH(img)
	}
	if f.Invert {
		img = imaging.Invert(img)
	}

	// Only calculate the scalar values once because gifs
	if f.scale == 0 {
		cols, rows := terminalDimensions()
		dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
		scale := scalar(dx, dy, cols, rows)
		if scale >= 1.0 {
			scale = 1.0
		}
		f.scale = scale
	}

	width := uint(f.scale * float64(img.Bounds().Dx()))
	height := uint(f.scale * float64(img.Bounds().Dy()))
	return resize.Resize(width, height, img, resize.NearestNeighbor)
}

func terminalDimensions() (int, int) {
	var cols, rows int

	if terminal.IsTerminal(int(os.Stdout.Fd())) {
		tw, th, err := terminal.GetSize(int(os.Stdout.Fd()))
		if err == nil {
			th -= 1 // Accounts for the terminal prompt
			if cols == 0 {
				cols = tw
			}
			if rows == 0 {
				rows = th
			}
		}
	}

	// Small, but fairly standard defaults
	if cols == 0 {
		cols = 80
	}
	if rows == 0 {
		rows = 25
	}

	return cols, rows
}

func scalar(dx, dy int, cols, rows int) float64 {
	scale := float64(1.0)
	scaleX := float64(cols*2) / float64(dx)
	scaleY := float64(rows*4) / float64(dy)

	if scaleX < scale {
		scale = scaleX
	}
	if scaleY < scale {
		scale = scaleY
	}

	return scale
}

func exit(msg string, code int) {
	fmt.Println(msg)
	os.Exit(code)
}
<commit_msg>remove ffmpeg references<commit_after>package main

import (
	"bufio"
	"fmt"
	"image"
	"image/draw"
	"image/gif"
	_ "image/png"
	"io"
	"net/http"
	"os"
	"strings"

	_ "golang.org/x/image/bmp"

	"github.com/codegangsta/cli"
	"github.com/disintegration/imaging"
	"github.com/kevin-cantwell/dotmatrix"
	"github.com/nfnt/resize"
	"golang.org/x/crypto/ssh/terminal"
)

func main() {
	app := cli.NewApp()
	app.Version = "0.1.0"
	app.Name = "dotmatrix"
	app.Usage = "A command-line tool for encoding images as unicode braille symbols."
	app.UsageText = "1) dotmatrix [options] [file|url]\n" +
		/*      */ "   2) dotmatrix [options] < [file]"
	app.Author = "Kevin Cantwell"
	app.Email = "kevin.cantwell@gmail.com"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "invert,i",
			Usage: "Inverts image color. Useful for black background terminals",
		},
		cli.Float64Flag{
			Name:  "gamma,g",
			Usage: "GAMMA less than 0 darkens the image and GAMMA greater than 0 lightens it.",
		},
		cli.Float64Flag{
			Name:  "brightness,b",
			Usage: "BRIGHTNESS = -100 gives solid black image. BRIGHTNESS = 100 gives solid white image.",
			Value: 0.0,
		},
		cli.Float64Flag{
			Name:  "contrast,c",
			Usage: "CONTRAST = -100 gives solid grey image. CONTRAST = 100 gives maximum contrast.",
			Value: 0.0,
		},
		cli.Float64Flag{
			Name:  "sharpen,s",
			Usage: "SHARPEN greater than 0 sharpens the image.",
			Value: 0.0,
		},
		cli.BoolFlag{
			Name:  "mirror,m",
			Usage: "Mirrors the image.",
		},
		cli.BoolFlag{
			Name:  "mono",
			Usage: "Images are drawn without Floyd Steinberg diffusion.",
		},
		cli.BoolFlag{
			Name:  "motion,mjpeg",
			Usage: "Interpret input as an mjpeg stream, such as from a webcam.",
		},
		cli.IntFlag{
			Name:  "framerate,fps",
			Usage: "Force a framerate for mjpeg streams. Default is -1 (ie: no delay between frames).",
			Value: -1,
		},
	}
	app.Action = func(c *cli.Context) error {
		reader, mimeType, err := decodeReader(c)
		if err != nil {
			return err
		}

		if c.Bool("motion") {
			return mjpegAction(c, reader, c.Int("framerate"))
		}

		switch mimeType {
		case "video/x-motion-jpeg":
			return mjpegAction(c, reader, c.Int("framerate"))
		case "image/gif":
			return gifAction(c, reader)
		default:
			return imageAction(c, reader)
		}
	}

	if err := app.Run(os.Args); err != nil {
		exit(err.Error(), 1)
	}
}

func config(c *cli.Context) *dotmatrix.Config {
	return &dotmatrix.Config{
		Filter: &Filter{
			Gamma:      c.Float64("gamma"),
			Brightness: c.Float64("brightness"),
			Contrast:   c.Float64("contrast"),
			Sharpen:    c.Float64("sharpen"),
			Invert:     c.Bool("invert"),
			Mirror:     c.Bool("mirror"),
		},
		Drawer: func() draw.Drawer {
			if c.Bool("mono") {
				return draw.Src
			}
			return draw.FloydSteinberg
		}(),
	}
}

func imageAction(c *cli.Context, r io.Reader) error {
	img, _, err := image.Decode(r)
	if err != nil {
		return err
	}
	return dotmatrix.NewPrinter(os.Stdout, config(c)).Print(img)
}

func gifAction(c *cli.Context, r io.Reader) error {
	giff, err := gif.DecodeAll(r)
	if err != nil {
		return err
	}
	return dotmatrix.NewGIFPrinter(os.Stdout, config(c)).Print(giff)
}

func mjpegAction(c *cli.Context, r io.Reader, fps int) error {
	return dotmatrix.NewMJPEGPrinter(os.Stdout, config(c)).Print(r, fps)
}

func decodeReader(c *cli.Context) (io.Reader, string, error) {
	var reader io.Reader = os.Stdin

	// Assign to reader
	if input := c.Args().First(); input != "" {
		// Is it a file?
		if !strings.HasPrefix(input, "http://") && !strings.HasPrefix(input, "https://") {
			file, err := os.Open(input)
			if err != nil {
				return nil, "", err
			}
			reader = file
		} else {
			// Is it a url?
			if resp, err := http.Get(input); err != nil {
				return nil, "", err
			} else {
				reader = resp.Body
			}
		}
	}

	bufioReader := bufio.NewReader(reader)

	peeked, err := bufioReader.Peek(512)
	if err != nil {
		return nil, "", err
	}

	mimeType := http.DetectContentType(peeked)

	return bufioReader, mimeType, nil
}

type Filter struct {
	// Gamma less than 0 darkens the image and GAMMA greater than 0 lightens it.
	Gamma float64
	// Brightness = -100 gives solid black image. Brightness = 100 gives solid white image.
	Brightness float64
	// Contrast = -100 gives solid grey image. Contrast = 100 gives maximum contrast.
	Contrast float64
	// Sharpen greater than 0 sharpens the image.
	Sharpen float64
	// Inverts pixel color. Transparent pixels remain transparent.
	Invert bool
	// Mirror flips the image on it's vertical axis
	Mirror bool

	scale float64
}

func (f *Filter) Filter(img image.Image) image.Image {
	if f.Gamma != 0 {
		img = imaging.AdjustGamma(img, f.Gamma+1.0)
	}
	if f.Brightness != 0 {
		img = imaging.AdjustBrightness(img, f.Brightness)
	}
	if f.Sharpen != 0 {
		img = imaging.Sharpen(img, f.Sharpen)
	}
	if f.Contrast != 0 {
		img = imaging.AdjustContrast(img, f.Contrast)
	}
	if f.Mirror {
		img = imaging.FlipH(img)
	}
	if f.Invert {
		img = imaging.Invert(img)
	}

	// Only calculate the scalar values once because gifs
	if f.scale == 0 {
		cols, rows := terminalDimensions()
		dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
		scale := scalar(dx, dy, cols, rows)
		if scale >= 1.0 {
			scale = 1.0
		}
		f.scale = scale
	}

	width := uint(f.scale * float64(img.Bounds().Dx()))
	height := uint(f.scale * float64(img.Bounds().Dy()))
	return resize.Resize(width, height, img, resize.NearestNeighbor)
}

func terminalDimensions() (int, int) {
	var cols, rows int

	if terminal.IsTerminal(int(os.Stdout.Fd())) {
		tw, th, err := terminal.GetSize(int(os.Stdout.Fd()))
		if err == nil {
			th -= 1 // Accounts for the terminal prompt
			if cols == 0 {
				cols = tw
			}
			if rows == 0 {
				rows = th
			}
		}
	}

	// Small, but fairly standard defaults
	if cols == 0 {
		cols = 80
	}
	if rows == 0 {
		rows = 25
	}

	return cols, rows
}

func scalar(dx, dy int, cols, rows int) float64 {
	scale := float64(1.0)
	scaleX := float64(cols*2) / float64(dx)
	scaleY := float64(rows*4) / float64(dy)

	if scaleX < scale {
		scale = scaleX
	}
	if scaleY < scale {
		scale = scaleY
	}

	return scale
}

func exit(msg string, code int) {
	fmt.Println(msg)
	os.Exit(code)
}
<|endoftext|>


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

package aws

import (
	"encoding/json"
	"fmt"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/coreos/mantle/platform/api/aws"
	"github.com/coreos/mantle/sdk"
	"github.com/spf13/cobra"
)

var (
	cmdUpload = &cobra.Command{
		Use:   "upload",
		Short: "Create AWS images",
		Long: `Upload CoreOS image to S3 and create relevant AMIs (hvm and pv).

Supported source formats are VMDK (as created with ./image_to_vm --format=ami_vmdk) and RAW.

After a successful run, the final line of output will be a line of JSON describing the resources created.

A common usage is:

    ore aws upload --region=us-west-2 \
		  --snapshot-description="CoreOS-stable-1234.5.6" \
		  --ami-name="CoreOS-stable-1234.5.6" \
		  --ami-description="CoreOS stable 1234.5.6" \
		  --file="/home/.../coreos_production_ami_vmdk_image.vmdk"
`,
		RunE: runUpload,
	}

	uploadSourceObject        string
	uploadBucket              string
	uploadImageName           string
	uploadBoard               string
	uploadFile                string
	uploadExpire              bool
	uploadForce               bool
	uploadSourceSnapshot      string
	uploadObjectFormat        aws.EC2ImageFormat
	uploadSnapshotDescription string
	uploadAMIName             string
	uploadAMIDescription      string
	uploadCreatePV            bool
)

func init() {
	AWS.AddCommand(cmdUpload)
	cmdUpload.Flags().StringVar(&uploadSourceObject, "source-object", "", "'s3://' URI pointing to image data (default: same as upload)")
	cmdUpload.Flags().StringVar(&uploadBucket, "bucket", "", "s3://bucket/prefix/ (defaults to a regional bucket and prefix defaults to $USER)")
	cmdUpload.Flags().StringVar(&uploadImageName, "name", "", "name of uploaded image (default COREOS_VERSION)")
	cmdUpload.Flags().StringVar(&uploadBoard, "board", "amd64-usr", "board used for naming with default prefix only")
	cmdUpload.Flags().StringVar(&uploadFile, "file",
		defaultUploadFile(),
		"path to CoreOS image (build with: ./image_to_vm.sh --format=ami_vmdk ...)")
	cmdUpload.Flags().BoolVar(&uploadExpire, "expire", true, "expire the S3 object in 10 days")
	cmdUpload.Flags().BoolVar(&uploadForce, "force", false, "overwrite existing S3 object without prompt")
	cmdUpload.Flags().StringVar(&uploadSourceSnapshot, "source-snapshot", "", "the snapshot ID to base this AMI on (default: create new snapshot)")
	cmdUpload.Flags().Var(&uploadObjectFormat, "object-format", fmt.Sprintf("object format: %s or %s (default: %s)", aws.EC2ImageFormatVmdk, aws.EC2ImageFormatRaw, aws.EC2ImageFormatVmdk))
	cmdUpload.Flags().StringVar(&uploadSnapshotDescription, "snapshot-description", "", "snapshot description (default: empty)")
	cmdUpload.Flags().StringVar(&uploadAMIName, "ami-name", "", "name of the AMI to create (default: Container-Linux-$USER-$VERSION)")
	cmdUpload.Flags().StringVar(&uploadAMIDescription, "ami-description", "", "description of the AMI to create (default: empty)")
	cmdUpload.Flags().BoolVar(&uploadCreatePV, "create-pv", true, "create a PV AMI in addition to the HVM AMI")
}

func defaultBucketNameForRegion(region string) string {
	return fmt.Sprintf("s3-%s.users.developer.core-os.net", region)
}

func defaultUploadFile() string {
	build := sdk.BuildRoot()
	return build + "/images/amd64-usr/latest/coreos_production_ami_vmdk_image.vmdk"
}

// defaultBucketURL determines the location the tool should upload to.
// The 'urlPrefix' parameter, if it contains a path, will override all other
// arguments
func defaultBucketURL(urlPrefix, imageName, board, file, region string) (*url.URL, error) {
	if urlPrefix == "" {
		urlPrefix = fmt.Sprintf("s3://%s", defaultBucketNameForRegion(region))
	}

	s3URL, err := url.Parse(urlPrefix)
	if err != nil {
		return nil, err
	}
	if s3URL.Scheme != "s3" {
		return nil, fmt.Errorf("invalid s3 scheme; must be 's3://', not '%s://'", s3URL.Scheme)
	}
	if s3URL.Host == "" {
		return nil, fmt.Errorf("URL missing bucket name %v\n", urlPrefix)
	}

	// if prefix not specified default name to s3://bucket/$USER/$BOARD/$VERSION
	if s3URL.Path == "" {
		if board == "" {
			board = "amd64-usr"
		}

		user := os.Getenv("USER")

		s3URL.Path = "/" + os.Getenv("USER")
		s3URL.Path += "/" + board

		if file == "" {
			file = defaultUploadFile()
		}

		// if an image name is unspecified try to use version.txt
		if imageName == "" {
			ver, err := sdk.VersionsFromDir(filepath.Dir(file))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Unable to get version from image directory, provide a -name flag or include a version.txt in the image directory: %v\n", err)
				os.Exit(1)
			}
			imageName = ver.Version
		}
		fileName := filepath.Base(file)

		s3URL.Path = fmt.Sprintf("/%s/%s/%s/%s", user, board, imageName, fileName)
	}

	return s3URL, nil
}

func runUpload(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		fmt.Fprintf(os.Stderr, "Unrecognized args in aws upload cmd: %v\n", args)
		os.Exit(2)
	}
	if uploadSourceObject != "" && uploadSourceSnapshot != "" {
		fmt.Fprintf(os.Stderr, "At most one of --source-object and --source-snapshot may be specified.\n")
		os.Exit(2)
	}

	if uploadAMIName == "" {
		buildDir := sdk.BuildRoot() + "/images/amd64-usr/latest/coreos_production_ami_vmdk_image.vmdk"
		ver, err := sdk.VersionsFromDir(filepath.Dir(buildDir))
		if err != nil {
			return fmt.Errorf("could not guess image name: %v", err)
		}
		awsVersion := strings.Replace(ver.Version, "+", "-", -1) // '+' is invalid in an AMI name
		uploadAMIName = fmt.Sprintf("Container-Linux-dev-%s-%s", os.Getenv("USER"), awsVersion)
	}

	if uploadFile == "" {
		uploadFile = defaultUploadFile()
	}

	var s3URL *url.URL
	var err error
	if uploadSourceObject != "" {
		s3URL, err = url.Parse(uploadSourceObject)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	} else {
		s3URL, err = defaultBucketURL(uploadBucket, uploadImageName, uploadBoard, uploadFile, region)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	}
	plog.Debugf("S3 object: %v\n", s3URL)
	s3BucketName := s3URL.Host
	s3ObjectPath := strings.TrimPrefix(s3URL.Path, "/")

	var createdObject string
	if uploadSourceObject == "" && uploadSourceSnapshot == "" {
		f, err := os.Open(uploadFile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not open image file %v: %v\n", uploadFile, err)
			os.Exit(1)
		}

		err = API.UploadObject(f, s3BucketName, s3ObjectPath, uploadExpire, uploadForce)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error uploading: %v\n", err)
			os.Exit(1)
		}
		createdObject = s3URL.String()
	}

	var createdSnapshot string
	if uploadSourceSnapshot == "" {
		snapshot, err := API.CreateSnapshot(uploadSnapshotDescription, s3URL.String(), uploadObjectFormat)
		if err != nil {
			return fmt.Errorf("unable to create snapshot: %v", err)
		}
		uploadSourceSnapshot = snapshot.SnapshotID
		createdSnapshot = snapshot.SnapshotID
	}

	hvmID, err := API.CreateHVMImage(uploadSourceSnapshot, uploadAMIName, uploadAMIDescription)
	if err != nil {
		return fmt.Errorf("unable to create HVM image: %v", err)
	}

	var pvID string
	if uploadCreatePV {
		pvImageID, err := API.CreatePVImage(uploadSourceSnapshot, uploadAMIName, uploadAMIDescription)
		if err != nil {
			return fmt.Errorf("unable to create PV image: %v", err)
		}
		pvID = pvImageID
	}

	json.NewEncoder(os.Stdout).Encode(&struct {
		HVM        string
		PV         string `json:",omitempty"`
		SnapshotID string `json:",omitempty"`
		S3Object   string `json:",omitempty"`
	}{
		HVM:        hvmID,
		PV:         pvID,
		SnapshotID: createdSnapshot,
		S3Object:   createdObject,
	})
	return nil
}
<commit_msg>cmd/ore/aws: Don't modify command-line arguments<commit_after>// Copyright 2017 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package aws

import (
	"encoding/json"
	"fmt"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/coreos/mantle/platform/api/aws"
	"github.com/coreos/mantle/sdk"
	"github.com/spf13/cobra"
)

var (
	cmdUpload = &cobra.Command{
		Use:   "upload",
		Short: "Create AWS images",
		Long: `Upload CoreOS image to S3 and create relevant AMIs (hvm and pv).

Supported source formats are VMDK (as created with ./image_to_vm --format=ami_vmdk) and RAW.

After a successful run, the final line of output will be a line of JSON describing the resources created.

A common usage is:

    ore aws upload --region=us-west-2 \
		  --snapshot-description="CoreOS-stable-1234.5.6" \
		  --ami-name="CoreOS-stable-1234.5.6" \
		  --ami-description="CoreOS stable 1234.5.6" \
		  --file="/home/.../coreos_production_ami_vmdk_image.vmdk"
`,
		RunE: runUpload,
	}

	uploadSourceObject        string
	uploadBucket              string
	uploadImageName           string
	uploadBoard               string
	uploadFile                string
	uploadExpire              bool
	uploadForce               bool
	uploadSourceSnapshot      string
	uploadObjectFormat        aws.EC2ImageFormat
	uploadSnapshotDescription string
	uploadAMIName             string
	uploadAMIDescription      string
	uploadCreatePV            bool
)

func init() {
	AWS.AddCommand(cmdUpload)
	cmdUpload.Flags().StringVar(&uploadSourceObject, "source-object", "", "'s3://' URI pointing to image data (default: same as upload)")
	cmdUpload.Flags().StringVar(&uploadBucket, "bucket", "", "s3://bucket/prefix/ (defaults to a regional bucket and prefix defaults to $USER)")
	cmdUpload.Flags().StringVar(&uploadImageName, "name", "", "name of uploaded image (default COREOS_VERSION)")
	cmdUpload.Flags().StringVar(&uploadBoard, "board", "amd64-usr", "board used for naming with default prefix only")
	cmdUpload.Flags().StringVar(&uploadFile, "file",
		defaultUploadFile(),
		"path to CoreOS image (build with: ./image_to_vm.sh --format=ami_vmdk ...)")
	cmdUpload.Flags().BoolVar(&uploadExpire, "expire", true, "expire the S3 object in 10 days")
	cmdUpload.Flags().BoolVar(&uploadForce, "force", false, "overwrite existing S3 object without prompt")
	cmdUpload.Flags().StringVar(&uploadSourceSnapshot, "source-snapshot", "", "the snapshot ID to base this AMI on (default: create new snapshot)")
	cmdUpload.Flags().Var(&uploadObjectFormat, "object-format", fmt.Sprintf("object format: %s or %s (default: %s)", aws.EC2ImageFormatVmdk, aws.EC2ImageFormatRaw, aws.EC2ImageFormatVmdk))
	cmdUpload.Flags().StringVar(&uploadSnapshotDescription, "snapshot-description", "", "snapshot description (default: empty)")
	cmdUpload.Flags().StringVar(&uploadAMIName, "ami-name", "", "name of the AMI to create (default: Container-Linux-$USER-$VERSION)")
	cmdUpload.Flags().StringVar(&uploadAMIDescription, "ami-description", "", "description of the AMI to create (default: empty)")
	cmdUpload.Flags().BoolVar(&uploadCreatePV, "create-pv", true, "create a PV AMI in addition to the HVM AMI")
}

func defaultBucketNameForRegion(region string) string {
	return fmt.Sprintf("s3-%s.users.developer.core-os.net", region)
}

func defaultUploadFile() string {
	build := sdk.BuildRoot()
	return build + "/images/amd64-usr/latest/coreos_production_ami_vmdk_image.vmdk"
}

// defaultBucketURL determines the location the tool should upload to.
// The 'urlPrefix' parameter, if it contains a path, will override all other
// arguments
func defaultBucketURL(urlPrefix, imageName, board, file, region string) (*url.URL, error) {
	if urlPrefix == "" {
		urlPrefix = fmt.Sprintf("s3://%s", defaultBucketNameForRegion(region))
	}

	s3URL, err := url.Parse(urlPrefix)
	if err != nil {
		return nil, err
	}
	if s3URL.Scheme != "s3" {
		return nil, fmt.Errorf("invalid s3 scheme; must be 's3://', not '%s://'", s3URL.Scheme)
	}
	if s3URL.Host == "" {
		return nil, fmt.Errorf("URL missing bucket name %v\n", urlPrefix)
	}

	// if prefix not specified default name to s3://bucket/$USER/$BOARD/$VERSION
	if s3URL.Path == "" {
		if board == "" {
			board = "amd64-usr"
		}

		user := os.Getenv("USER")

		s3URL.Path = "/" + os.Getenv("USER")
		s3URL.Path += "/" + board

		if file == "" {
			file = defaultUploadFile()
		}

		// if an image name is unspecified try to use version.txt
		if imageName == "" {
			ver, err := sdk.VersionsFromDir(filepath.Dir(file))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Unable to get version from image directory, provide a -name flag or include a version.txt in the image directory: %v\n", err)
				os.Exit(1)
			}
			imageName = ver.Version
		}
		fileName := filepath.Base(file)

		s3URL.Path = fmt.Sprintf("/%s/%s/%s/%s", user, board, imageName, fileName)
	}

	return s3URL, nil
}

func runUpload(cmd *cobra.Command, args []string) error {
	if len(args) != 0 {
		fmt.Fprintf(os.Stderr, "Unrecognized args in aws upload cmd: %v\n", args)
		os.Exit(2)
	}
	if uploadSourceObject != "" && uploadSourceSnapshot != "" {
		fmt.Fprintf(os.Stderr, "At most one of --source-object and --source-snapshot may be specified.\n")
		os.Exit(2)
	}

	amiName := uploadAMIName
	if amiName == "" {
		buildDir := sdk.BuildRoot() + "/images/amd64-usr/latest/coreos_production_ami_vmdk_image.vmdk"
		ver, err := sdk.VersionsFromDir(filepath.Dir(buildDir))
		if err != nil {
			return fmt.Errorf("could not guess image name: %v", err)
		}
		awsVersion := strings.Replace(ver.Version, "+", "-", -1) // '+' is invalid in an AMI name
		amiName = fmt.Sprintf("Container-Linux-dev-%s-%s", os.Getenv("USER"), awsVersion)
	}

	var s3URL *url.URL
	var err error
	if uploadSourceObject != "" {
		s3URL, err = url.Parse(uploadSourceObject)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	} else {
		s3URL, err = defaultBucketURL(uploadBucket, uploadImageName, uploadBoard, uploadFile, region)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	}
	plog.Debugf("S3 object: %v\n", s3URL)
	s3BucketName := s3URL.Host
	s3ObjectPath := strings.TrimPrefix(s3URL.Path, "/")

	var createdObject string
	if uploadSourceObject == "" && uploadSourceSnapshot == "" {
		f, err := os.Open(uploadFile)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not open image file %v: %v\n", uploadFile, err)
			os.Exit(1)
		}

		err = API.UploadObject(f, s3BucketName, s3ObjectPath, uploadExpire, uploadForce)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error uploading: %v\n", err)
			os.Exit(1)
		}
		createdObject = s3URL.String()
	}

	sourceSnapshot := uploadSourceSnapshot
	var createdSnapshot string
	if uploadSourceSnapshot == "" {
		snapshot, err := API.CreateSnapshot(uploadSnapshotDescription, s3URL.String(), uploadObjectFormat)
		if err != nil {
			return fmt.Errorf("unable to create snapshot: %v", err)
		}
		sourceSnapshot = snapshot.SnapshotID
		createdSnapshot = sourceSnapshot
	}

	hvmID, err := API.CreateHVMImage(sourceSnapshot, amiName, uploadAMIDescription)
	if err != nil {
		return fmt.Errorf("unable to create HVM image: %v", err)
	}

	var pvID string
	if uploadCreatePV {
		pvImageID, err := API.CreatePVImage(sourceSnapshot, amiName, uploadAMIDescription)
		if err != nil {
			return fmt.Errorf("unable to create PV image: %v", err)
		}
		pvID = pvImageID
	}

	json.NewEncoder(os.Stdout).Encode(&struct {
		HVM        string
		PV         string `json:",omitempty"`
		SnapshotID string `json:",omitempty"`
		S3Object   string `json:",omitempty"`
	}{
		HVM:        hvmID,
		PV:         pvID,
		SnapshotID: createdSnapshot,
		S3Object:   createdObject,
	})
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"
	"errors"
)

type stack struct {
	s []float64
}

func (s *stack) String() string {
	return ""
}

func (s *stack) Set(str string) error {
	var strMode byte
	runes := make([]rune, 0, 32)
	s.s = make([]float64, 0, 32)
	for _, r := range(str) {
		if strMode != 0 && byte(r) != strMode {
			s.s = append(s.s, float64(r))
			continue
		}
		switch r {
		default:
			return errors.New("Invalid initial stack")
		case ' ':
			if len(runes) > 0 {
				if f, err := strconv.ParseFloat(string(runes), 64); err == nil {
					s.s = append(s.s, f)
					runes = make([]rune, 0, 32)
				} else {
					return err
				}
			}
		case '\'', '"':
			if strMode == 0 {
				strMode = byte(r)
			} else {
				strMode = 0
			}
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
			runes = append(runes, r)
		}
	}
	if f, err := strconv.ParseFloat(string(runes), 64); err == nil {
		s.s = append(s.s, f)
		runes = make([]rune, 0, 32)
	} else {
		return err
	}
	return nil
}

func (s *stack) Get() interface{} {
	return s.s
}
<commit_msg>Permit string-only initial stack.<commit_after>package main

import (
	"strconv"
	"errors"
)

type stack struct {
	s []float64
}

func (s *stack) String() string {
	return ""
}

func (s *stack) Set(str string) error {
	var strMode byte
	runes := make([]rune, 0, 32)
	s.s = make([]float64, 0, 32)
	for _, r := range(str) {
		if strMode != 0 && byte(r) != strMode {
			s.s = append(s.s, float64(r))
			continue
		}
		switch r {
		default:
			return errors.New("Invalid initial stack")
		case ' ':
			if len(runes) > 0 {
				if f, err := strconv.ParseFloat(string(runes), 64); err == nil {
					s.s = append(s.s, f)
					runes = make([]rune, 0, 32)
				} else {
					return err
				}
			}
		case '\'', '"':
			if strMode == 0 {
				strMode = byte(r)
			} else {
				strMode = 0
			}
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
			runes = append(runes, r)
		}
	}
	if f, err := strconv.ParseFloat(string(runes), 64); err == nil {
		s.s = append(s.s, f)
		runes = make([]rune, 0, 32)
	} else if len(runes) > 0 {
		return err
	}
	return nil
}

func (s *stack) Get() interface{} {
	return s.s
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Manuel Gauto (github.com/twa16)
 *
 * 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 simpleauth

import (
	"github.com/jinzhu/gorm"
	"github.com/satori/go.uuid"
	"golang.org/x/crypto/bcrypt"
	"strings"
	"time"
	"fmt"
)

type AuthProvider struct {
	Database                 *gorm.DB //Database that the auth provider uses to store user information
	SessionExpireTimeSeconds int64    //The time the sessions created by this provider should live
}

type User struct {
	gorm.Model                  //All DB fields
	Username     string         //The username of the user
	PasswordHash []byte         //BCrypt hash of the user's password
	FirstName    string         //First name of the user
	LastName     string         //Last name of the user
	Email        string         //Email of the user
	PhoneNumber  string         //Phone number of the users
	Role         string         //String that represents a user's role
	Permissions  []Permission   `gorm:"ForeignKey:AuthUserID"` //The permissions the user has
	UserMetaData []UserMetadata `gorm:"ForeignKey:AuthUserID"` //The metadata of the user
	Sessions     []Session      `gorm:"ForeignKey:AuthUserID"` //Sessions associated with this user
}

type Permission struct {
	gorm.Model        //DB Fields
	AuthUserID uint   //ID of the user this belongs to
	Permission string //Permission string
}

type UserMetadata struct {
	gorm.Model        //DB Fields
	AuthUserID uint   //ID of the user this belongs to
	Key        string //Key for the metadata field
	Value      string //Value for this metadata field
}

type Session struct {
	gorm.Model                 //DB Fields
	AuthenticationToken string //Session key used to authorize requests
	AuthUserID          uint   //ID of user that this token belongs to
	LastSeen            int64  //Linux time of last API Call
	Persistent          bool   //If this is set to true, the key never expires.
}

type SessionCheckResponse struct {
	AuthSession *Session //Session pointer. Set if the session exists
	IsExpired   bool     //True if the session is expired
}

//Startup This method migrates all models and does all needed one time setup for the authentication provider
func (authProvider AuthProvider) Startup() {
	authProvider.Database.AutoMigrate(&User{})
	authProvider.Database.AutoMigrate(&Permission{})
	authProvider.Database.AutoMigrate(&UserMetadata{})
	authProvider.Database.AutoMigrate(&Session{})
}

//CreateUser Persists the user in the database
func (authProvider AuthProvider) CreateUser(user User) (User, error) {
	err := authProvider.Database.Save(&user).Error
	if err != nil {
		fmt.Println(err)
	}
	return user, err
}

//UpdateUser Update a user's data. This is just a wrapper around CreateUser.
func (authProvider AuthProvider) UpdateUser(user User) (User, error) {
	return authProvider.CreateUser(user)
}

//GetUser Retrieves a user from the database by their username
func (authProvider AuthProvider) GetUser(username string) (User, error) {
	var user User
	err := authProvider.Database.Where("username = ?", username).First(&user).Error
	if err != nil {
		return user, err
	}
	authProvider.Database.Model(&user).Association("Permissions").Find(&user.Permissions)
	authProvider.Database.Model(&user).Association("UserMetaData").Find(&user.UserMetaData)
	authProvider.Database.Model(&user).Association("Sessions").Find(&user.Sessions)
	return user, err
}

//GetUserByID Gets a user from the database by their ID
func (authProvider AuthProvider) GetUserByID(userID uint) (User, error) {
	var user User
	err := authProvider.Database.First(&user, userID).Error
	authProvider.Database.Model(&user).Association("Permissions").Find(&user.Permissions)
	authProvider.Database.Model(&user).Association("UserMetaData").Find(&user.UserMetaData)
	authProvider.Database.Model(&user).Association("Sessions").Find(&user.Sessions)
	return user, err
}

//SetUserPassword Sets the user's password
func (authProvider AuthProvider) SetUserPassword(user User, password string) error {
	passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.PasswordHash = passwordHash
	authProvider.Database.Save(user)
	return nil
}

//CheckLogin This function returns the user true if the credentials correspond to a user
func (authProvider AuthProvider) CheckLogin(username string, password string) (bool, error) {
	userObject, err := authProvider.GetUser(username)
	//Check if there is an error
	if err != nil {
		return false, err
	}
	//Check if the user exists
	if userObject.Username == "" {
		return false, nil
	}
	compareResultError := bcrypt.CompareHashAndPassword(userObject.PasswordHash, []byte(password))
	return compareResultError == nil, nil
}

//GenerateSessionKey Generates a Session for a user. If 'persistent' is set to true the session will never expire.
func (authProvider AuthProvider) GenerateSessionKey(userID uint, persistent bool) (Session, error) {
	sessionKey := Session{}
	sessionKey.AuthUserID = userID
	sessionKey.Persistent = persistent
	sessionKey.AuthenticationToken = uuid.NewV4().String()
	err := authProvider.Database.Create(&sessionKey).Error
	return sessionKey, err
}

//CheckSessionKey Checks a session key and returns the session if it exists
func (authProvider AuthProvider) CheckSessionKey(sessionKey string) (SessionCheckResponse, error) {
	var session Session
	err := authProvider.Database.Where("authentication_token = ?", sessionKey).First(&session).Error

	curTime := time.Now().Unix()
	checkResponse := SessionCheckResponse{}
	checkResponse.AuthSession = &session
	checkResponse.IsExpired = (curTime - session.LastSeen) < authProvider.SessionExpireTimeSeconds
	return checkResponse, err
}

//UpdateSessionAccessTime Sets the last access time on a session to the current time.
func (authProvider AuthProvider) UpdateSessionAccessTime(session Session) {
	curTime := time.Now().Unix()
	if (curTime - session.LastSeen) > authProvider.SessionExpireTimeSeconds {
		session.LastSeen = curTime
		authProvider.Database.Save(&session)
	}
}

//CheckPermission Returns true if the user has the provided permission
func (authProvider AuthProvider) CheckPermission(userID uint, permission string) (bool, error) {
	user, err := authProvider.GetUserByID(userID)
	if err != nil {
		return false, err
	}
	return authProvider.CheckPermissionLogic(permission, user.Permissions), err

}

//CheckPermissionLogic method that contains logic used to process permission checks
func (authProvider AuthProvider) CheckPermissionLogic(permissionReq string, userPermissions []Permission) bool {
	//Split Permission Request
	permReqParts := strings.Split(permissionReq, ".")
	for _, userPerm := range userPermissions {
		userPermParts := strings.Split(userPerm.Permission, ".")
		userPermPartCount := len(userPermParts)
		for ri, permReqPart := range permReqParts {
			//Check if the requested permission is too long
			if (ri + 1) > userPermPartCount {
				break
			}
			//Check if the user permission at this section is a wildcard
			if userPermParts[ri] == "*" {
				return true
			}
			//Check if the indexed parts match
			if permReqPart != userPermParts[ri] {
				break
			}
			//If all other tests pass and this is the last piece, this permission works
			if (ri + 1) == len(permReqParts) {
				return true
			}
		}
	}
	return false
}
<commit_msg>New sessions should have their last seen set.<commit_after>/*
 * Copyright 2017 Manuel Gauto (github.com/twa16)
 *
 * 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 simpleauth

import (
	"github.com/jinzhu/gorm"
	"github.com/satori/go.uuid"
	"golang.org/x/crypto/bcrypt"
	"strings"
	"time"
	"fmt"
)

type AuthProvider struct {
	Database                 *gorm.DB //Database that the auth provider uses to store user information
	SessionExpireTimeSeconds int64    //The time the sessions created by this provider should live
}

type User struct {
	gorm.Model                  //All DB fields
	Username     string         //The username of the user
	PasswordHash []byte         //BCrypt hash of the user's password
	FirstName    string         //First name of the user
	LastName     string         //Last name of the user
	Email        string         //Email of the user
	PhoneNumber  string         //Phone number of the users
	Role         string         //String that represents a user's role
	Permissions  []Permission   `gorm:"ForeignKey:AuthUserID"` //The permissions the user has
	UserMetaData []UserMetadata `gorm:"ForeignKey:AuthUserID"` //The metadata of the user
	Sessions     []Session      `gorm:"ForeignKey:AuthUserID"` //Sessions associated with this user
}

type Permission struct {
	gorm.Model        //DB Fields
	AuthUserID uint   //ID of the user this belongs to
	Permission string //Permission string
}

type UserMetadata struct {
	gorm.Model        //DB Fields
	AuthUserID uint   //ID of the user this belongs to
	Key        string //Key for the metadata field
	Value      string //Value for this metadata field
}

type Session struct {
	gorm.Model                 //DB Fields
	AuthenticationToken string //Session key used to authorize requests
	AuthUserID          uint   //ID of user that this token belongs to
	LastSeen            int64  //Linux time of last API Call
	Persistent          bool   //If this is set to true, the key never expires.
}

type SessionCheckResponse struct {
	AuthSession *Session //Session pointer. Set if the session exists
	IsExpired   bool     //True if the session is expired
}

//Startup This method migrates all models and does all needed one time setup for the authentication provider
func (authProvider AuthProvider) Startup() {
	authProvider.Database.AutoMigrate(&User{})
	authProvider.Database.AutoMigrate(&Permission{})
	authProvider.Database.AutoMigrate(&UserMetadata{})
	authProvider.Database.AutoMigrate(&Session{})
}

//CreateUser Persists the user in the database
func (authProvider AuthProvider) CreateUser(user User) (User, error) {
	err := authProvider.Database.Save(&user).Error
	if err != nil {
		fmt.Println(err)
	}
	return user, err
}

//UpdateUser Update a user's data. This is just a wrapper around CreateUser.
func (authProvider AuthProvider) UpdateUser(user User) (User, error) {
	return authProvider.CreateUser(user)
}

//GetUser Retrieves a user from the database by their username
func (authProvider AuthProvider) GetUser(username string) (User, error) {
	var user User
	err := authProvider.Database.Where("username = ?", username).First(&user).Error
	if err != nil {
		return user, err
	}
	authProvider.Database.Model(&user).Association("Permissions").Find(&user.Permissions)
	authProvider.Database.Model(&user).Association("UserMetaData").Find(&user.UserMetaData)
	authProvider.Database.Model(&user).Association("Sessions").Find(&user.Sessions)
	return user, err
}

//GetUserByID Gets a user from the database by their ID
func (authProvider AuthProvider) GetUserByID(userID uint) (User, error) {
	var user User
	err := authProvider.Database.First(&user, userID).Error
	authProvider.Database.Model(&user).Association("Permissions").Find(&user.Permissions)
	authProvider.Database.Model(&user).Association("UserMetaData").Find(&user.UserMetaData)
	authProvider.Database.Model(&user).Association("Sessions").Find(&user.Sessions)
	return user, err
}

//SetUserPassword Sets the user's password
func (authProvider AuthProvider) SetUserPassword(user User, password string) error {
	passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.PasswordHash = passwordHash
	authProvider.Database.Save(user)
	return nil
}

//CheckLogin This function returns the user true if the credentials correspond to a user
func (authProvider AuthProvider) CheckLogin(username string, password string) (bool, error) {
	userObject, err := authProvider.GetUser(username)
	//Check if there is an error
	if err != nil {
		return false, err
	}
	//Check if the user exists
	if userObject.Username == "" {
		return false, nil
	}
	compareResultError := bcrypt.CompareHashAndPassword(userObject.PasswordHash, []byte(password))
	return compareResultError == nil, nil
}

//GenerateSessionKey Generates a Session for a user. If 'persistent' is set to true the session will never expire.
func (authProvider AuthProvider) GenerateSessionKey(userID uint, persistent bool) (Session, error) {
	sessionKey := Session{}
	sessionKey.AuthUserID = userID
	sessionKey.Persistent = persistent
	sessionKey.AuthenticationToken = uuid.NewV4().String()
	sessionKey.LastSeen = time.Now().Unix()
	err := authProvider.Database.Create(&sessionKey).Error
	return sessionKey, err
}

//CheckSessionKey Checks a session key and returns the session if it exists
func (authProvider AuthProvider) CheckSessionKey(sessionKey string) (SessionCheckResponse, error) {
	var session Session
	err := authProvider.Database.Where("authentication_token = ?", sessionKey).First(&session).Error

	curTime := time.Now().Unix()
	checkResponse := SessionCheckResponse{}
	checkResponse.AuthSession = &session
	checkResponse.IsExpired = (curTime - session.LastSeen) < authProvider.SessionExpireTimeSeconds
	return checkResponse, err
}

//UpdateSessionAccessTime Sets the last access time on a session to the current time.
func (authProvider AuthProvider) UpdateSessionAccessTime(session Session) {
	curTime := time.Now().Unix()
	if (curTime - session.LastSeen) > authProvider.SessionExpireTimeSeconds {
		session.LastSeen = curTime
		authProvider.Database.Save(&session)
	}
}

//CheckPermission Returns true if the user has the provided permission
func (authProvider AuthProvider) CheckPermission(userID uint, permission string) (bool, error) {
	user, err := authProvider.GetUserByID(userID)
	if err != nil {
		return false, err
	}
	return authProvider.CheckPermissionLogic(permission, user.Permissions), err

}

//CheckPermissionLogic method that contains logic used to process permission checks
func (authProvider AuthProvider) CheckPermissionLogic(permissionReq string, userPermissions []Permission) bool {
	//Split Permission Request
	permReqParts := strings.Split(permissionReq, ".")
	for _, userPerm := range userPermissions {
		userPermParts := strings.Split(userPerm.Permission, ".")
		userPermPartCount := len(userPermParts)
		for ri, permReqPart := range permReqParts {
			//Check if the requested permission is too long
			if (ri + 1) > userPermPartCount {
				break
			}
			//Check if the user permission at this section is a wildcard
			if userPermParts[ri] == "*" {
				return true
			}
			//Check if the indexed parts match
			if permReqPart != userPermParts[ri] {
				break
			}
			//If all other tests pass and this is the last piece, this permission works
			if (ri + 1) == len(permReqParts) {
				return true
			}
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

/*
# azan.go
# Anda boleh menggunakan dan menyebarkan file ini dengan menyebutkan sumbernya:
# Nara Sumber awal:
# Dr. T. Djamaluddin
# Lembaga Penerbangan dan Antariksa Nasional (LAPAN) Bandung
# Phone 022-6012602. Fax 022-6014998
# e-mail: t_djamal@lapan.go.id  t_djamal@hotmail.com
# Porting ke Perl:
# Wastono ST
# Jl Taman Cilandak Rt:001 Rw:04 No.4 Jakarta 12430
# Phone 021-75909268. was.tono@gmail.com
# Porting ke Golang:
# Wicaksono Trihatmaja
# trihatmaja@gmail.com
*/

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

import (
	"github.com/droundy/goopt"
)

var latitiude float64
var longitude float64
var timezone float64
var city string
var t [7]float64

var mydate = [12]int{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
var mymonth = [12]string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}

const PI float64 = 3.14159
const rad float64 = PI / 180.0

func init() {
	goopt.ReqArg([]string{"--latitude"}, "LAT", "Latitude Value",
		func(to string) error {
			var err error
			latitiude, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})
	goopt.ReqArg([]string{"--longitude"}, "LONG", "Longitude Value",
		func(to string) error {
			var err error
			longitude, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})

	goopt.ReqArg([]string{"--timezone"}, "TZ", "Time Zone Value",
		func(to string) error {
			var err error
			timezone, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})

	goopt.ReqArg([]string{"--city"}, "CT", "City",
		func(to string) error {
			city = strings.ToUpper(to)
			return nil
		})

	goopt.Author = "Wicaksono Trihatmaja <trihatmaja@gmail.com>"

	goopt.Version = "1.0"

	goopt.Suite = "Azan Schedule"

	goopt.Summary = "Azan Schedule based on location latitude and longitude"

	goopt.Description = func() string {
		return "Azan Schedule"
	}

}

func calculation() {
	lamd := longitude / 15.0
	phi := latitiude * rad
	tdif := timezone - lamd

	h := 0.0
	zd := 0.0
	n := 0.0
	for i := 0; i < 12; i++ {
		fmt.Println("\n" + mymonth[i] + "\nTgl\tSubuh\tTerbit\tZuhur\tAshar\tMagrib\tIsya")
		for k := 0; k < mydate[i]; k++ {
			n = n + 1.0
			a := 6.0
			z := 110.0 * rad
			for w := 1; w < 7; w++ {
				st := n + (a-lamd)/24.0
				L := (0.9856*st - 3.289) * rad
				L = L + 1.916*rad*math.Sin(L) + 0.02*rad*math.Sin(2*L) + 282.634*rad
				RA := float64(int(((L/PI)*12.0)/6.0) + 1)
				if int(RA/2)*2-int(RA) != 0 {
					RA--
				}
				RA = (math.Atan(0.91746*math.Tan(L)) / PI * 12.0) + float64(RA*6.0)
				X := 0.39782 * math.Sin(L)
				ATNX := math.Sqrt(1 - X*X)
				dek := math.Atan(X / ATNX)
				if a == 15 {
					z = math.Atan(math.Tan(zd) + 1)
				}
				X = (math.Cos(z) - X*math.Sin(phi)) / (ATNX * math.Cos(phi))
				if X <= 1.0 && X >= -1.0 {
					ATNX = math.Atan(math.Sqrt(1-X*X)/X) / rad
					if ATNX < 0.0 {
						ATNX = ATNX + 180.0
					}
					h = (360.0 - ATNX) * 24.0 / 360.0
					if a == 18 {
						h = 24.0 - h
					}
					if a == 12 {
						h = 0.0
					}
				}
				if a == 15 {
					h = 24.0 - h
				}
				st = h + RA - 0.06571*st - 6.622 + 24.0
				st = st - float64(int(st/24.0)*24.0)
				st = st + tdif
				if w == 1 {
					if math.Abs(X) <= 1.0 {
						t[1] = st // t[1] = subuh
					}
					z = (90.0 + 5.0/6.0) * rad
				} else if w == 2 {
					t[2] = st // t[2] = sunrise
					a = 18.0
					z = (90.0 + 5.0/6.0) * rad
				} else if w == 3 {
					t[5] = st + 2.0/60.0 // t[5] = maghrib
					z = 108.0 * rad
				} else if w == 4 {
					if math.Abs(X) <= 1.0 {
						t[6] = st // t[6] = isya
					}
					a = 12.0
				} else if w == 5 {
					t[3] = st + 2.0/60.0 // t[3] = dhuhur
					zd = math.Abs((dek - phi))
					a = 15.0
				} else {
					t[4] = st // t[4] = ashar
				}

				if n == 59.0 {
					if k == 27 {
						n = n - 1.0
					}
				}
			}
			fmt.Printf("%d\t", k+1)
			for j := 1; j < 7; j++ {
				th := int32(t[j])
				tm := int32((t[j] - float64(th)) * 60.0)
				if tm < 10 {
					fmt.Printf("%d:0%d\t", th, tm)
				} else {
					fmt.Printf("%d:%d\t", th, tm)
				}
				if j == 6 {
					fmt.Printf("\n")
				}
			}
			if int(n) == 59 {
				if k == 27 {
					n--
				}
			}
		}
	}

}

func main() {
	goopt.Parse(nil)
	fmt.Println("Jadwal Waktu Azan untuk wilayah", city)
	if timezone > 0 {
		fmt.Printf("GMT+%v Latitude=%v Longitude=%v\n", timezone, latitiude, longitude)
	} else {
		fmt.Printf("GMT-%v Latitude=%v Longitude=%v\n", timezone, latitiude, longitude)
	}
	calculation()
}
<commit_msg>fix logic<commit_after>package main

/*
# azan.go
# Anda boleh menggunakan dan menyebarkan file ini dengan menyebutkan sumbernya:
# Nara Sumber awal:
# Dr. T. Djamaluddin
# Lembaga Penerbangan dan Antariksa Nasional (LAPAN) Bandung
# Phone 022-6012602. Fax 022-6014998
# e-mail: t_djamal@lapan.go.id  t_djamal@hotmail.com
# Porting ke Perl:
# Wastono ST
# Jl Taman Cilandak Rt:001 Rw:04 No.4 Jakarta 12430
# Phone 021-75909268. was.tono@gmail.com
# Porting ke Golang:
# Wicaksono Trihatmaja
# trihatmaja@gmail.com
*/

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

import (
	"github.com/droundy/goopt"
)

var latitiude float64
var longitude float64
var timezone float64
var city string
var t [7]float64

var mydate = [12]int{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
var mymonth = [12]string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}

const PI float64 = 3.14159
const rad float64 = PI / 180.0

func init() {
	goopt.ReqArg([]string{"--latitude"}, "LAT", "Latitude Value",
		func(to string) error {
			var err error
			latitiude, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})
	goopt.ReqArg([]string{"--longitude"}, "LONG", "Longitude Value",
		func(to string) error {
			var err error
			longitude, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})

	goopt.ReqArg([]string{"--timezone"}, "TZ", "Time Zone Value",
		func(to string) error {
			var err error
			timezone, err = strconv.ParseFloat(to, 64)
			if err != nil {
				return errors.New("value not an float")
			}
			return nil
		})

	goopt.ReqArg([]string{"--city"}, "CT", "City",
		func(to string) error {
			city = strings.ToUpper(to)
			return nil
		})

	goopt.Author = "Wicaksono Trihatmaja <trihatmaja@gmail.com>"

	goopt.Version = "1.0"

	goopt.Suite = "Azan Schedule"

	goopt.Summary = "Azan Schedule based on location latitude and longitude"

	goopt.Description = func() string {
		return "Azan Schedule"
	}
}

func calculation() {
	lamd := longitude / 15.0
	phi := latitiude * rad
	tdif := timezone - lamd

	h := 0.0
	zd := 0.0
	n := 0.0
	for i := 0; i < 12; i++ {
		fmt.Println("\n" + mymonth[i] + "\nTgl\tSubuh\tTerbit\tZuhur\tAshar\tMagrib\tIsya")
		for k := 0; k < mydate[i]; k++ {
			n = n + 1.0
			a := 6.0
			z := 110.0 * rad
			for w := 1; w < 7; w++ {
				st := n + (a-lamd)/24.0
				L := (0.9856*st - 3.289) * rad
				L = L + 1.916*rad*math.Sin(L) + 0.02*rad*math.Sin(2*L) + 282.634*rad
				RA := float64(int(((L/PI)*12.0)/6.0) + 1)
				if int(RA/2)*2-int(RA) != 0 {
					RA--
				}
				RA = (math.Atan(0.91746*math.Tan(L)) / PI * 12.0) + float64(RA*6.0)
				X := 0.39782 * math.Sin(L)
				ATNX := math.Sqrt(1 - X*X)
				dek := math.Atan(X / ATNX)
				if a == 15 {
					z = math.Atan(math.Tan(zd) + 1)
				}
				X = (math.Cos(z) - X*math.Sin(phi)) / (ATNX * math.Cos(phi))
				if X <= 1.0 && X >= -1.0 {
					ATNX = math.Atan(math.Sqrt(1-X*X)/X) / rad
					if ATNX < 0.0 {
						ATNX = ATNX + 180.0
					}
					h = (360.0 - ATNX) * 24.0 / 360.0
					if a == 18 {
						h = 24.0 - h
					}
					if a == 12 {
						h = 0.0
					}
				}
				if a == 15 {
					h = 24.0 - h
				}
				st = h + RA - 0.06571*st - 6.622 + 24.0
				st = st - float64(int(st/24.0)*24.0)
				st = st + tdif
				switch w {
				case 1:
					if math.Abs(X) <= 1.0 {
						t[1] = st // t[1] = subuh
					}
					z = (90.0 + 5.0/6.0) * rad
				case 2:
					t[2] = st // t[2] = sunrise
					a = 18.0
					z = (90.0 + 5.0/6.0) * rad
				case 3:
					t[5] = st + 2.0/60.0 // t[5] = maghrib
					z = 108.0 * rad
				case 4:
					if math.Abs(X) <= 1.0 {
						t[6] = st // t[6] = isya
					}
					a = 12.0
				case 5:
					t[3] = st + 2.0/60.0 // t[3] = dhuhur
					zd = math.Abs((dek - phi))
					a = 15.0
				case 6:
					t[4] = st // t[4] = ashar
				}

				if n == 59.0 {
					if k == 27 {
						n = n - 1.0
					}
				}
			}
			fmt.Printf("%d\t", k+1)
			for j := 1; j < 7; j++ {
				th := int32(t[j])
				tm := int32((t[j] - float64(th)) * 60.0)
				if tm < 10 {
					fmt.Printf("%d:0%d\t", th, tm)
				} else {
					fmt.Printf("%d:%d\t", th, tm)
				}
				if j == 6 {
					fmt.Printf("\n")
				}
			}
			if int(n) == 59 {
				if k == 27 {
					n--
				}
			}
		}
	}

}

func main() {
	goopt.Parse(nil)
	fmt.Println("Jadwal Waktu Azan untuk wilayah", city)
	if timezone > 0 {
		fmt.Printf("GMT+%v Latitude=%v Longitude=%v\n", timezone, latitiude, longitude)
	} else {
		fmt.Printf("GMT-%v Latitude=%v Longitude=%v\n", timezone, latitiude, longitude)
	}
	calculation()
}
<|endoftext|>