<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"syscall"
	"time"
)

type Msg struct {
	channel string
	file    string
	msg     string
}

type Server struct {
	server     string
	conn       net.Conn
	port       string
	nick       string
	realName   string
	channels   map[string]bool
	msgChan    chan Msg
	serverChan chan string
	ssl        bool
	Dir        string
}

type Parsed struct {
	nick     string
	userinfo string
	event    string
	channel  string
	raw      string
	args     []string
}

// Thanks Twisted
func parse(s string) Parsed {
	raw := s
	var prefix string
	var command string
	var args []string
	var trailing []string
	var nick string
	var userinfo string

	if string(s[0]) == ":" {
		ret := strings.SplitN(s[1:], " ", 2)
		prefix = ret[0]
		s = ret[1]
	}
	if strings.Index(s, " :") != -1 {
		ret := strings.SplitN(s, " :", 2)
		s = ret[0]
		trailing = ret[1:]

		args = strings.Split(s, " ")
		args = append(args, trailing...)
	} else {
		args = strings.Split(s, " ")
	}
	command = args[0]
	args = args[1:]

	prefixSplit := strings.Split(prefix, "!")
	if len(prefixSplit) == 1 {
		nick = ""
		userinfo = ""
	} else {
		nick = prefixSplit[0]
		userinfo = prefixSplit[1]
	}

	return Parsed{nick: nick,
		channel:  args[0],
		userinfo: userinfo,
		event:    command,
		raw:      raw,
		args:     args}
}

// Creates the fifo files and directories
func createFiles(directory string) bool {
	if _, err := os.Stat(directory); err == nil {
		return false
	}
	err := os.MkdirAll(directory, 0744)
	if err != nil {
		log.Print("Tried making directory:", directory, err)
	}
	f, err := os.OpenFile(directory+"/out", os.O_CREATE, 0660)
	defer f.Close()
	if err != nil {
		log.Print("Tried opening out file for directory:", directory, err)
	}
	err = syscall.Mkfifo(directory+"/in", 0700)
	if err != nil {
		log.Print("Tried creating fifo file for directory:", directory, err)
	}
	return true
}

func (server *Server) writeOutLog(channel string, text Parsed) {
	createFiles(server.Dir + "/" + channel)
	f, _ := os.OpenFile(server.Dir+"/"+channel+"/out", os.O_RDWR|os.O_APPEND, 0660)
	defer f.Close()

	t := time.Now()
	currTime := fmt.Sprintf("%s", t.Format("2006-01-02 15:04:05"))

	msg := ""
	if text.event == "PRIVMSG" {
		msg = fmt.Sprintf("%s <%s> %s", currTime, text.nick, text.args[1])
	} else if text.event == "JOIN" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has joined %s", currTime, text.nick, text.userinfo, text.channel)
	} else if text.event == "PART" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has left %s", currTime, text.nick, text.userinfo, text.channel)
	} else if text.event == "QUIT" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has quit", currTime, text.nick, text.userinfo)
	} else if text.event == "MODE" {
		msg = fmt.Sprintf("%s -!- %s changed mode/%s -> %s", currTime, text.nick, text.channel, text.args[1])
	} else if text.event == "NOTICE" {
		msg = fmt.Sprintf("%s -!- NOTICE %s", currTime, text.args[1])
	} else if text.event == "KICK" {
		msg = fmt.Sprintf("%s -!- %s kicked %s (\"%s\")", currTime, text.nick, text.args[1], text.args[2])
	} else if text.event == "TOPIC" {
		msg = fmt.Sprintf("%s -!- %s changed topic to \"%s\"", currTime, text.nick, text.args[1])
	}
	if msg != "" {
		_, _ = f.WriteString(msg + "\n")
	}
}

func (server *Server) Write(msg string) {
	server.conn.Write([]byte(msg + "\n"))
}

func (server *Server) listenFile(channel string) {
	channel = strings.ToLower(channel)
	filePath := server.Dir + "/" + channel
	if channel != "" {
		filePath = filePath + "/"
	}

	createFiles(filePath)
	file, err := os.OpenFile(filePath+"in", os.O_CREATE|syscall.O_RDONLY|syscall.O_NONBLOCK, os.ModeNamedPipe)
	defer file.Close()
	if err != nil {
		log.Print("Tried listening on channel:", channel, err)
	}
	buffer := bufio.NewReader(file)
	for {
		bytes, _, _ := buffer.ReadLine()
		if len(bytes) != 0 {
			server.msgChan <- Msg{channel: channel, msg: string(bytes), file: filePath}
		}
		time.Sleep(10 * time.Millisecond)
	}
}

func (server *Server) listenServer() {
	userMsg := fmt.Sprintf("USER %s %s %s :Go FTW", server.nick, server.nick, server.nick)
	server.Write(userMsg)
	nickMsg := fmt.Sprintf("NICK %s", server.nick)
	server.Write(nickMsg)
	buffer := bufio.NewScanner(server.conn)
	for {
		for buffer.Scan() {
			server.serverChan <- buffer.Text()
		}
	}
}

func (server *Server) createServer() {
	var conn net.Conn
	var err error
	if server.ssl {
		conf := &tls.Config{
			InsecureSkipVerify: true,
		}
		conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%s", server.server, server.port), conf)
	} else {
		conn, err = net.Dial("tcp", fmt.Sprintf("%s:%s", server.server, server.port))
	}
	if err != nil {
		log.Fatal("Connection blew up:", err)
		os.Exit(1)
	}
	server.conn = conn
}

func (server *Server) handleMsg(msg Msg) {
	events := strings.SplitN(msg.msg, " ", 3)
	// Events
	if "/j" == events[0] {
		_, ok := server.channels[events[1]]
		if ok == false {
			server.Write(fmt.Sprintf("JOIN :%s", events[1]))
			go server.listenFile(events[1])
			server.channels[events[1]] = true
			if len(events) > 2 {
				server.Write(fmt.Sprintf("PRIVMSG %s :%s", events[1], events[2]))
			}
		}
	} else if "/a" == events[0] {
		server.Write(fmt.Sprintf("AWAY :%s", strings.Join(events[1:], " ")))
	} else if "/n" == events[0] {
		server.Write(fmt.Sprintf("NICK %s", events[1]))
	} else if "/t" == events[0] {
		server.Write(fmt.Sprintf("TOPIC %s :%s", events[1], strings.Join(events[2:], " ")))
	} else if "/l" == events[0] {
		server.Write(fmt.Sprintf("PART %s", events[1]))
		delete(server.channels, events[1])
	} else {
		server.Write(fmt.Sprintf("PRIVMSG %s :%s", msg.channel, msg.msg) + "\n")
	}
}

func (server *Server) handleServer(s string) {
	msg := parse(s)

	if msg.event == "PING" {
		server.Write(fmt.Sprintf("PONG %s", msg.args[0]))
		return
	}
	if len(msg.nick) == 0 && msg.channel == server.nick || msg.channel == "*" {
		server.writeOutLog("", msg)
		return
	}
	var channel string
	if msg.channel == server.nick {
		channel = strings.ToLower(msg.nick)
	} else {
		channel = strings.ToLower(msg.channel)
	}
	// Check if we have a thread on the channel
	// Create if there isnt
	_, ok := server.channels[channel]
	if ok == false {
		go server.listenFile(channel)
		server.channels[channel] = true
	}
	server.writeOutLog(channel, msg)
}

func (server *Server) Run() {
	go server.listenServer()
	go server.listenFile("")
	for {
		select {
		case s := <-server.serverChan:
			server.handleServer(s)
		case s := <-server.msgChan:
			server.handleMsg(s)
		}
	}
}

func main() {
	server := flag.String("s", "irc.freenode.net", "Specify server")
	port := flag.String("p", "", "Server port (default 6667, SSL default 6697)")
	ssl := flag.Bool("tls", false, "Use TLS for the connection (default false)")
	_ = flag.String("k", "IIPASS", "Specify a environment variable for your IRC password")
	path := flag.String("i", "~/irc", "Specify a path for the IRC connection")
	nick := flag.String("n", "iii", "Speciy a default nick")
	realName := flag.String("f", "ii Improved", "Speciy a default real name")
	flag.Parse()

	serverRun := Server{
		server:     *server,
		port:       *port,
		nick:       *nick,
		realName:   *realName,
		channels:   map[string]bool{},
		msgChan:    make(chan Msg),
		serverChan: make(chan string),
		ssl:        *ssl,
		Dir:        *path + "/" + *server}
	serverRun.createServer()
	serverRun.Run()
}
<commit_msg>Added server & channel rejoin<commit_after>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"syscall"
	"time"
)

type Msg struct {
	channel string
	file    string
	msg     string
}

type Server struct {
	server     string
	conn       net.Conn
	port       string
	nick       string
	realName   string
	channels   map[string]bool
	msgChan    chan Msg
	serverChan chan string
	ssl        bool
	Dir        string
}

type Parsed struct {
	nick     string
	userinfo string
	event    string
	channel  string
	raw      string
	args     []string
}

// Thanks Twisted
func parse(s string) Parsed {
	raw := s
	var prefix string
	var command string
	var args []string
	var trailing []string
	var nick string
	var userinfo string

	if string(s[0]) == ":" {
		ret := strings.SplitN(s[1:], " ", 2)
		prefix = ret[0]
		s = ret[1]
	}
	if strings.Index(s, " :") != -1 {
		ret := strings.SplitN(s, " :", 2)
		s = ret[0]
		trailing = ret[1:]

		args = strings.Split(s, " ")
		args = append(args, trailing...)
	} else {
		args = strings.Split(s, " ")
	}
	command = args[0]
	args = args[1:]

	prefixSplit := strings.Split(prefix, "!")
	if len(prefixSplit) == 1 {
		nick = ""
		userinfo = ""
	} else {
		nick = prefixSplit[0]
		userinfo = prefixSplit[1]
	}

	return Parsed{nick: nick,
		channel:  args[0],
		userinfo: userinfo,
		event:    command,
		raw:      raw,
		args:     args}
}

// Creates the fifo files and directories
func createFiles(directory string) bool {
	if _, err := os.Stat(directory); err == nil {
		return false
	}
	err := os.MkdirAll(directory, 0744)
	if err != nil {
		log.Print("Tried making directory:", directory, err)
	}
	f, err := os.OpenFile(directory+"/out", os.O_CREATE, 0660)
	defer f.Close()
	if err != nil {
		log.Print("Tried opening out file for directory:", directory, err)
	}
	err = syscall.Mkfifo(directory+"/in", 0700)
	if err != nil {
		log.Print("Tried creating fifo file for directory:", directory, err)
	}
	return true
}

func (server *Server) writeOutLog(channel string, text Parsed) {
	createFiles(server.Dir + "/" + channel)
	f, _ := os.OpenFile(server.Dir+"/"+channel+"/out", os.O_RDWR|os.O_APPEND, 0660)
	defer f.Close()

	t := time.Now()
	currTime := fmt.Sprintf("%s", t.Format("2006-01-02 15:04:05"))

	msg := ""
	if text.event == "PRIVMSG" {
		msg = fmt.Sprintf("%s <%s> %s", currTime, text.nick, text.args[1])
	} else if text.event == "JOIN" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has joined %s", currTime, text.nick, text.userinfo, text.channel)
	} else if text.event == "PART" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has left %s", currTime, text.nick, text.userinfo, text.channel)
	} else if text.event == "QUIT" {
		msg = fmt.Sprintf("%s -!- %s(~%s) has quit", currTime, text.nick, text.userinfo)
	} else if text.event == "MODE" {
		msg = fmt.Sprintf("%s -!- %s changed mode/%s -> %s", currTime, text.nick, text.channel, text.args[1])
	} else if text.event == "NOTICE" {
		msg = fmt.Sprintf("%s -!- NOTICE %s", currTime, text.args[1])
	} else if text.event == "KICK" {
		msg = fmt.Sprintf("%s -!- %s kicked %s (\"%s\")", currTime, text.nick, text.args[1], text.args[2])
	} else if text.event == "TOPIC" {
		msg = fmt.Sprintf("%s -!- %s changed topic to \"%s\"", currTime, text.nick, text.args[1])
	}
	if msg != "" {
		_, _ = f.WriteString(msg + "\n")
	}
}

func (server *Server) Write(msg string) {
	server.conn.Write([]byte(msg + "\n"))
}

func (server *Server) listenFile(channel string) {
	channel = strings.ToLower(channel)
	filePath := server.Dir + "/" + channel
	if channel != "" {
		filePath = filePath + "/"
	}

	createFiles(filePath)
	file, err := os.OpenFile(filePath+"in", os.O_CREATE|syscall.O_RDONLY|syscall.O_NONBLOCK, os.ModeNamedPipe)
	defer file.Close()
	if err != nil {
		log.Print("Tried listening on channel:", channel, err)
	}
	buffer := bufio.NewReader(file)
	for {
		bytes, _, _ := buffer.ReadLine()
		if len(bytes) != 0 {
			server.msgChan <- Msg{channel: channel, msg: string(bytes), file: filePath}
		}
		time.Sleep(10 * time.Millisecond)
	}
}

func (server *Server) listenServer() {
	userMsg := fmt.Sprintf("USER %s %s %s :Go FTW", server.nick, server.nick, server.nick)
	server.Write(userMsg)
	nickMsg := fmt.Sprintf("NICK %s", server.nick)
	server.Write(nickMsg)
	buffer := bufio.NewScanner(server.conn)
	for {
		for buffer.Scan() {
			server.serverChan <- buffer.Text()
			if strings.Split(buffer.Text(), " :")[0] == "ERROR" {
				return
			}
		}
	}
}

func (server *Server) createServer() {
	var conn net.Conn
	var err error
	if server.ssl {
		conf := &tls.Config{
			InsecureSkipVerify: true,
		}
		conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%s", server.server, server.port), conf)
	} else {
		conn, err = net.Dial("tcp", fmt.Sprintf("%s:%s", server.server, server.port))
	}
	if err != nil {
		log.Fatal("Connection blew up:", err)
		os.Exit(1)
	}
	server.conn = conn
}

func (server *Server) handleMsg(msg Msg) {
	events := strings.SplitN(msg.msg, " ", 3)
	// Events
	if "/j" == events[0] {
		_, ok := server.channels[events[1]]
		if ok == false {
			server.Write(fmt.Sprintf("JOIN :%s", events[1]))
			go server.listenFile(events[1])
			server.channels[events[1]] = true
			if len(events) > 2 {
				server.Write(fmt.Sprintf("PRIVMSG %s :%s", events[1], events[2]))
			}
		}
	} else if "/a" == events[0] {
		server.Write(fmt.Sprintf("AWAY :%s", strings.Join(events[1:], " ")))
	} else if "/n" == events[0] {
		server.Write(fmt.Sprintf("NICK %s", events[1]))
	} else if "/t" == events[0] {
		server.Write(fmt.Sprintf("TOPIC %s :%s", events[1], strings.Join(events[2:], " ")))
	} else if "/l" == events[0] {
		server.Write(fmt.Sprintf("PART %s", events[1]))
		delete(server.channels, events[1])
	} else {
		server.Write(fmt.Sprintf("PRIVMSG %s :%s", msg.channel, msg.msg) + "\n")
	}
}

func (server *Server) rejoinChannels() {
	for channel, _ := range server.channels {
		server.Write(fmt.Sprintf("JOIN :%s", channel))
	}
}

func (server *Server) handleServer(s string) {
	msg := parse(s)
	if msg.event == "ERROR" {
		server.createServer()
		go server.listenServer()
		return
	}
	if msg.event == "266" {
		// Rejoin channels
		server.rejoinChannels()
		return
	}
	if msg.event == "PING" {
		server.Write(fmt.Sprintf("PONG %s", msg.args[0]))
		return
	}
	if len(msg.nick) == 0 && msg.channel == server.nick || msg.channel == "*" {
		server.writeOutLog("", msg)
		return
	}
	var channel string
	if msg.channel == server.nick {
		channel = strings.ToLower(msg.nick)
	} else {
		channel = strings.ToLower(msg.channel)
	}
	// Check if we have a thread on the channel
	// Create if there isnt
	_, ok := server.channels[channel]
	if ok == false {
		go server.listenFile(channel)
		server.channels[channel] = true
	}
	server.writeOutLog(channel, msg)
}

func (server *Server) Run() {
	go server.listenServer()
	go server.listenFile("")
	for {
		select {
		case s := <-server.serverChan:
			server.handleServer(s)
		case s := <-server.msgChan:
			server.handleMsg(s)
		}
	}
}

func main() {
	server := flag.String("s", "irc.freenode.net", "Specify server")
	port := flag.String("p", "", "Server port (default 6667, SSL default 6697)")
	ssl := flag.Bool("tls", false, "Use TLS for the connection (default false)")
	_ = flag.String("k", "IIPASS", "Specify a environment variable for your IRC password")
	path := flag.String("i", "~/irc", "Specify a path for the IRC connection")
	nick := flag.String("n", "iii", "Speciy a default nick")
	realName := flag.String("f", "ii Improved", "Speciy a default real name")
	flag.Parse()

	serverRun := Server{
		server:     *server,
		port:       *port,
		nick:       *nick,
		realName:   *realName,
		channels:   map[string]bool{},
		msgChan:    make(chan Msg),
		serverChan: make(chan string),
		ssl:        *ssl,
		Dir:        *path + "/" + *server}
	serverRun.createServer()
	serverRun.Run()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Betalo AB
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"
)

func main() {
	var (
		forceFlag    = flag.Bool("f", false, "Force running the command even after giving up")
		quietFlag    = flag.Bool("q", false, "Set quiet mode")
		timeoutFlag  = flag.Duration("t", 1*time.Minute, "Set timeout duration before giving up")
		verbose1Flag = flag.Bool("v", false, "Set verbose output mode")
		verbose2Flag = flag.Bool("vv", false, "Set more verbose output mode")
	)
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: await [options...] <res>... [ -- <cmd>]")
		fmt.Fprintln(os.Stderr, "Await availability of resources.")
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
	}
	flag.Parse()

	var logLevel int
	switch {
	case *quietFlag:
		logLevel = silentLevel
	case *verbose1Flag:
		logLevel = infoLevel
	case *verbose2Flag:
		logLevel = debugLevel
	default:
		logLevel = errorLevel
	}
	logger := NewLogger(logLevel)

	resArgs, cmdArgs := splitArgs(flag.Args())
	ress, err := parseResources(resArgs)
	if err != nil {
		logger.Fatalln("Error: failed to parse resources: %v", err)
	}

	awaiter := &awaiter{
		logger:  logger,
		timeout: *timeoutFlag,
	}

	if err := awaiter.run(ress); err != nil {
		if e, ok := err.(*unavailabilityError); ok {
			logger.Errorf("Resource unavailable: %v", e)
			logger.Errorln("Timeout exceeded")
		} else {
			logger.Fatalln("Error: %v", err)
		}
		if !*forceFlag {
			os.Exit(1)
		}
	} else {
		logger.Infoln("All resources available")
	}

	if len(cmdArgs) > 0 {
		logger.Infof("Runnning command: %v", cmdArgs)
		if err := execCmd(cmdArgs); err != nil {
			logger.Fatalf("Error: failed to execute command: %v", err)
		}
	}
}

func splitArgs(args []string) ([]string, []string) {
	if i := indexOf(args, "--"); i >= 0 {
		return args[0:i], args[i+1:]
	}

	// We haven't seen a resource|command separator ('--'). This can either be
	// because of Go's flag parser removing the separator if no args were given,
	// or because there actually was none given.
	// Fallback to the original (unparsed) flag argument list and see if a
	// separator was given there and if, assume all arguments given are part of
	// the command, i.e. no resources at all were provided.
	if i := indexOf(os.Args, "--"); i >= 0 {
		return []string{}, args
	}

	// We still haven't seen a resource|command separator ('--'). Now finally
	// assume because there actually was none given and use all arguments as
	// resources.
	return args, []string{}
}

func indexOf(l []string, s string) int {
	for i, e := range l {
		if e == "--" {
			return i
		}
	}
	return -1
}

func execCmd(cmdArgs []string) error {
	path, err := exec.LookPath(cmdArgs[0])
	if err != nil {
		return err
	}
	return syscall.Exec(path, cmdArgs, os.Environ())
}
<commit_msg>Fix grammar in comment<commit_after>// Copyright (c) 2016 Betalo AB
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"
)

func main() {
	var (
		forceFlag    = flag.Bool("f", false, "Force running the command even after giving up")
		quietFlag    = flag.Bool("q", false, "Set quiet mode")
		timeoutFlag  = flag.Duration("t", 1*time.Minute, "Set timeout duration before giving up")
		verbose1Flag = flag.Bool("v", false, "Set verbose output mode")
		verbose2Flag = flag.Bool("vv", false, "Set more verbose output mode")
	)
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: await [options...] <res>... [ -- <cmd>]")
		fmt.Fprintln(os.Stderr, "Await availability of resources.")
		fmt.Fprintln(os.Stderr)
		flag.PrintDefaults()
	}
	flag.Parse()

	var logLevel int
	switch {
	case *quietFlag:
		logLevel = silentLevel
	case *verbose1Flag:
		logLevel = infoLevel
	case *verbose2Flag:
		logLevel = debugLevel
	default:
		logLevel = errorLevel
	}
	logger := NewLogger(logLevel)

	resArgs, cmdArgs := splitArgs(flag.Args())
	ress, err := parseResources(resArgs)
	if err != nil {
		logger.Fatalln("Error: failed to parse resources: %v", err)
	}

	awaiter := &awaiter{
		logger:  logger,
		timeout: *timeoutFlag,
	}

	if err := awaiter.run(ress); err != nil {
		if e, ok := err.(*unavailabilityError); ok {
			logger.Errorf("Resource unavailable: %v", e)
			logger.Errorln("Timeout exceeded")
		} else {
			logger.Fatalln("Error: %v", err)
		}
		if !*forceFlag {
			os.Exit(1)
		}
	} else {
		logger.Infoln("All resources available")
	}

	if len(cmdArgs) > 0 {
		logger.Infof("Runnning command: %v", cmdArgs)
		if err := execCmd(cmdArgs); err != nil {
			logger.Fatalf("Error: failed to execute command: %v", err)
		}
	}
}

func splitArgs(args []string) ([]string, []string) {
	if i := indexOf(args, "--"); i >= 0 {
		return args[0:i], args[i+1:]
	}

	// We haven't seen a resource|command separator ('--'). This can either be
	// because of Go's flag parser removing the separator if no args were given,
	// or because there actually was none given.
	// Fallback to the original (unparsed) flag argument list and see if a
	// separator was given there and if, assume all arguments given are part of
	// the command, i.e. no resources at all were provided.
	if i := indexOf(os.Args, "--"); i >= 0 {
		return []string{}, args
	}

	// We still haven't seen a resource|command separator ('--'). Now finally
	// assume none was given and use all arguments as resources.
	return args, []string{}
}

func indexOf(l []string, s string) int {
	for i, e := range l {
		if e == "--" {
			return i
		}
	}
	return -1
}

func execCmd(cmdArgs []string) error {
	path, err := exec.LookPath(cmdArgs[0])
	if err != nil {
		return err
	}
	return syscall.Exec(path, cmdArgs, os.Environ())
}
<|endoftext|>


<commit_before>//go:generate esc -o static.go -prefix static static

package main

import (
	"encoding/json"
	"flag"
	"github.com/fatih/structs"
	"github.com/nfnt/resize"
	"gopkg.in/yaml.v2"
	"image/jpeg"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"time"
)

var photos = make(map[string]struct{})
var dirToMetadata = make(map[string]metadata)
var photoDir string
var cacheDir string

type metadata struct {
	Event        string
	Photographer string
	Date         string
	Location     string
	Directory    string `json:"-" structs:"directory"`
}

func handleFilters(w http.ResponseWriter, r *http.Request) {
	keys := []string{"Event", "Photographer", "Date", "Location"}

	filters := make(map[string]map[string]struct{})
	for _, k := range keys {
		filters[k] = make(map[string]struct{})
	}

	for _, meta := range dirToMetadata {
		m := structs.Map(meta)
		for _, k := range keys {
			if _, ok := m[k]; ok {
				filters[k][m[k].(string)] = struct{}{}
			}
		}
	}

	jFilters := make(map[string][]string)
	for _, k := range keys {
		jFilters[k] = make([]string, 0)
	}

	for i := range filters {
		for j := range filters[i] {
			jFilters[i] = append(jFilters[i], j)
		}
		sort.Strings(jFilters[i])
		if len(jFilters[i]) == 0 {
			delete(jFilters, i)
		}
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(jFilters); err != nil {
		log.Print(err)
		return
	}
}

func handleFilter(w http.ResponseWriter, r *http.Request) {
	filterToEligible := make(map[string][]string)

	filters := make(map[string][]string)
	for filterKey := range r.URL.Query() {
		filters[filterKey] = r.URL.Query()[filterKey]
	}

	// find all directories with matching filters
	for filterKey, filterValues := range filters {
		for dir, meta := range dirToMetadata {
			m := structs.Map(meta)
			for k, v := range m {
				if filterKey == k {
					for _, filterValue := range filterValues {
						if filterValue == v {
							filterToEligible[filterKey] = append(filterToEligible[filterKey], dir)
						}
					}
				}
			}
		}
	}

	// find intersection of all filter matches
	eligible := make(map[string]bool)

	for _, dirs := range filterToEligible {
		for _, dir := range dirs {
			count := 0
			for _, dirTests := range filterToEligible {
				for _, dirTest := range dirTests {
					if dir == dirTest {
						count += 1
					}
				}
			}
			if count == len(filterToEligible) {
				eligible[dir] = true
			}
		}
	}

	eligiblePhotos := make([]string, 0)
	for photo := range photos {
		dir := filepath.Dir(photo)
		if _, ok := eligible[dir]; ok {
			eligiblePhotos = append(eligiblePhotos, photo)
		}
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(eligiblePhotos); err != nil {
		log.Print(err)
		return
	}
}

func handlePhoto(w http.ResponseWriter, r *http.Request) {
	if filepath.Ext(r.URL.Path) != ".jpg" {
		http.Error(w, http.StatusText(404), 404)
		return
	}

	// serve photo
	photoFilepath := filepath.Join(photoDir, r.URL.Path[len("/photo/"):])
	http.ServeFile(w, r, photoFilepath)
}

func handleThumb(w http.ResponseWriter, r *http.Request) {
	if filepath.Ext(r.URL.Path) != ".jpg" {
		http.Error(w, http.StatusText(404), 404)
		return
	}

	photoFilepath := filepath.Join(photoDir, r.URL.Path[len("/cache/"):])
	cacheFilepath := filepath.Join(cacheDir, r.URL.Path[len("/cache/"):])

	if _, err := os.Stat(cacheFilepath); err != nil {
		if os.IsNotExist(err) {
			// create thumbnail

			file, err := os.Open(photoFilepath)
			if err != nil {
				log.Print(err)
				return
			}

			img, err := jpeg.Decode(file)
			if err != nil {
				log.Print(err)
				return
			}
			file.Close()

			m := resize.Thumbnail(500, 1000, img, resize.Bicubic)

			parentDir, _ := filepath.Split(cacheFilepath)
			err = os.MkdirAll(parentDir, os.FileMode(0764))
			if err != nil {
				log.Print(err)
				return
			}

			out, err := os.Create(cacheFilepath)
			if err != nil {
				log.Print(err)
				return
			}
			defer out.Close()

			jpeg.Encode(out, m, nil)
		} else {
			log.Print(err)
			return
		}
	}

	// serve thumbnail
	http.ServeFile(w, r, cacheFilepath)
}

func walkFunc(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	dir, filename := filepath.Split(path)
	dir, err = filepath.Rel(photoDir, dir)
	if err != nil {
		return err
	}

	if filename == "metadata.yaml" {
		m := metadata{Directory: dir}

		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		err = yaml.Unmarshal(data, &m)
		dirToMetadata[dir] = m
	} else if filepath.Ext(filename) == ".jpg" {
		filename = filepath.Join(dir, filename)
		photos[filename] = struct{}{}
	}
	return nil
}

func walk() {
	for {
		filepath.Walk(photoDir, walkFunc)
		time.Sleep(5 * time.Second)
	}
}

func main() {
	flag.StringVar(&photoDir, "photoDir", "photos", "path to photos")
	flag.StringVar(&cacheDir, "cacheDir", "cache", "path to photo cache directory")
	flag.Parse()

	go walk()

	http.Handle("/", http.FileServer(FS(false))) // esc for static content. true uses local files, false uses embedded
	http.HandleFunc("/photo/", handlePhoto)
	http.HandleFunc("/thumb/", handleThumb)

	http.HandleFunc("/api/filters", handleFilters)
	http.HandleFunc("/api/filter", handleFilter)
	http.ListenAndServe("127.0.0.1:8000", nil)
}
<commit_msg>Set Content-Type header for JSON responses<commit_after>//go:generate esc -o static.go -prefix static static

package main

import (
	"encoding/json"
	"flag"
	"github.com/fatih/structs"
	"github.com/nfnt/resize"
	"gopkg.in/yaml.v2"
	"image/jpeg"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"time"
)

var photos = make(map[string]struct{})
var dirToMetadata = make(map[string]metadata)
var photoDir string
var cacheDir string

type metadata struct {
	Event        string
	Photographer string
	Date         string
	Location     string
	Directory    string `json:"-" structs:"directory"`
}

func handleFilters(w http.ResponseWriter, r *http.Request) {
	keys := []string{"Event", "Photographer", "Date", "Location"}

	filters := make(map[string]map[string]struct{})
	for _, k := range keys {
		filters[k] = make(map[string]struct{})
	}

	for _, meta := range dirToMetadata {
		m := structs.Map(meta)
		for _, k := range keys {
			if _, ok := m[k]; ok {
				filters[k][m[k].(string)] = struct{}{}
			}
		}
	}

	jFilters := make(map[string][]string)
	for _, k := range keys {
		jFilters[k] = make([]string, 0)
	}

	for i := range filters {
		for j := range filters[i] {
			jFilters[i] = append(jFilters[i], j)
		}
		sort.Strings(jFilters[i])
		if len(jFilters[i]) == 0 {
			delete(jFilters, i)
		}
	}

	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	if err := enc.Encode(jFilters); err != nil {
		log.Print(err)
		return
	}
}

func handleFilter(w http.ResponseWriter, r *http.Request) {
	filterToEligible := make(map[string][]string)

	filters := make(map[string][]string)
	for filterKey := range r.URL.Query() {
		filters[filterKey] = r.URL.Query()[filterKey]
	}

	// find all directories with matching filters
	for filterKey, filterValues := range filters {
		for dir, meta := range dirToMetadata {
			m := structs.Map(meta)
			for k, v := range m {
				if filterKey == k {
					for _, filterValue := range filterValues {
						if filterValue == v {
							filterToEligible[filterKey] = append(filterToEligible[filterKey], dir)
						}
					}
				}
			}
		}
	}

	// find intersection of all filter matches
	eligible := make(map[string]bool)

	for _, dirs := range filterToEligible {
		for _, dir := range dirs {
			count := 0
			for _, dirTests := range filterToEligible {
				for _, dirTest := range dirTests {
					if dir == dirTest {
						count += 1
					}
				}
			}
			if count == len(filterToEligible) {
				eligible[dir] = true
			}
		}
	}

	eligiblePhotos := make([]string, 0)
	for photo := range photos {
		dir := filepath.Dir(photo)
		if _, ok := eligible[dir]; ok {
			eligiblePhotos = append(eligiblePhotos, photo)
		}
	}

	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	if err := enc.Encode(eligiblePhotos); err != nil {
		log.Print(err)
		return
	}
}

func handlePhoto(w http.ResponseWriter, r *http.Request) {
	if filepath.Ext(r.URL.Path) != ".jpg" {
		http.Error(w, http.StatusText(404), 404)
		return
	}

	// serve photo
	photoFilepath := filepath.Join(photoDir, r.URL.Path[len("/photo/"):])
	http.ServeFile(w, r, photoFilepath)
}

func handleThumb(w http.ResponseWriter, r *http.Request) {
	if filepath.Ext(r.URL.Path) != ".jpg" {
		http.Error(w, http.StatusText(404), 404)
		return
	}

	photoFilepath := filepath.Join(photoDir, r.URL.Path[len("/cache/"):])
	cacheFilepath := filepath.Join(cacheDir, r.URL.Path[len("/cache/"):])

	if _, err := os.Stat(cacheFilepath); err != nil {
		if os.IsNotExist(err) {
			// create thumbnail

			file, err := os.Open(photoFilepath)
			if err != nil {
				log.Print(err)
				return
			}

			img, err := jpeg.Decode(file)
			if err != nil {
				log.Print(err)
				return
			}
			file.Close()

			m := resize.Thumbnail(500, 1000, img, resize.Bicubic)

			parentDir, _ := filepath.Split(cacheFilepath)
			err = os.MkdirAll(parentDir, os.FileMode(0764))
			if err != nil {
				log.Print(err)
				return
			}

			out, err := os.Create(cacheFilepath)
			if err != nil {
				log.Print(err)
				return
			}
			defer out.Close()

			jpeg.Encode(out, m, nil)
		} else {
			log.Print(err)
			return
		}
	}

	// serve thumbnail
	http.ServeFile(w, r, cacheFilepath)
}

func walkFunc(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	dir, filename := filepath.Split(path)
	dir, err = filepath.Rel(photoDir, dir)
	if err != nil {
		return err
	}

	if filename == "metadata.yaml" {
		m := metadata{Directory: dir}

		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		err = yaml.Unmarshal(data, &m)
		dirToMetadata[dir] = m
	} else if filepath.Ext(filename) == ".jpg" {
		filename = filepath.Join(dir, filename)
		photos[filename] = struct{}{}
	}
	return nil
}

func walk() {
	for {
		filepath.Walk(photoDir, walkFunc)
		time.Sleep(5 * time.Second)
	}
}

func main() {
	flag.StringVar(&photoDir, "photoDir", "photos", "path to photos")
	flag.StringVar(&cacheDir, "cacheDir", "cache", "path to photo cache directory")
	flag.Parse()

	go walk()

	http.Handle("/", http.FileServer(FS(false))) // esc for static content. true uses local files, false uses embedded
	http.HandleFunc("/photo/", handlePhoto)
	http.HandleFunc("/thumb/", handleThumb)

	http.HandleFunc("/api/filters", handleFilters)
	http.HandleFunc("/api/filter", handleFilter)
	http.ListenAndServe("127.0.0.1:8000", nil)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/olekukonko/tablewriter"
	"github.com/optiopay/klar/clair"
	"github.com/optiopay/klar/docker"
)

const (
	ColorCritical = "\033[1;31m%s\033[0m"
	ColorHigh     = "\033[0;31m%s\033[0m"
	ColorMedium   = "\033[0;33m%s\033[0m"
	ColorLow      = "\033[0;94m%s\033[0m"
	ColorDefault  = "\033[0;97m%s\033[0m"
)

var store = make(map[string][]*clair.Vulnerability)

var Severity = map[string]int{
	"Defcon1":    7,
	"Critical":   6,
	"High":       5,
	"Medium":     4,
	"Low":        3,
	"Negligible": 2,
	"Unknown":    1,
}

func getSeverityStyle(status string) string {
	var colorStyle = ColorDefault
	if Severity[status] >= 6 {
		colorStyle = ColorCritical
	} else if Severity[status] >= 5 {
		colorStyle = ColorHigh
	} else if Severity[status] >= 4 {
		colorStyle = ColorMedium
	} else if Severity[status] >= 2 {
		colorStyle = ColorLow
	}

	return fmt.Sprintf(colorStyle, status)
}

func main() {
	fail := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", format), a...)
		os.Exit(2)
	}

	if len(os.Args) != 2 {
		fail("Image name must be provided")
	}

	conf, err := newConfig(os.Args)
	if err != nil {
		fail("Invalid options: %s", err)
	}

	if !conf.JSONOutput {
		fmt.Fprintf(os.Stderr, "clair timeout %s\n", conf.ClairTimeout)
		fmt.Fprintf(os.Stderr, "docker timeout: %s\n", conf.DockerConfig.Timeout)
	}
	whitelist := &vulnerabilitiesWhitelist{}
	if conf.WhiteListFile != "" {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "whitelist file: %s\n", conf.WhiteListFile)
		}
		whitelist, err = parseWhitelistFile(conf.WhiteListFile)
		if err != nil {
			fail("Could not parse whitelist file: %s", err)
		}
	} else {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "no whitelist file\n")
		}
	}

	image, err := docker.NewImage(&conf.DockerConfig)
	if err != nil {
		fail("Can't parse qname: %s", err)
	}

	err = image.Pull()
	if err != nil {
		fail("Can't pull image: %s", err)
	}

	output := jsonOutput{
		Vulnerabilities: make(map[string][]*clair.Vulnerability),
	}

	if len(image.FsLayers) == 0 {
		fail("Can't pull fsLayers")
	} else {
		if conf.JSONOutput {
			output.LayerCount = len(image.FsLayers)
		} else {
			fmt.Printf("Analysing %d layers\n", len(image.FsLayers))
		}
	}

	var vs []*clair.Vulnerability
	for _, ver := range []int{1, 3} {
		c := clair.NewClair(conf.ClairAddr, ver, conf.ClairTimeout)
		vs, err = c.Analyse(image)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to analyze using API v%d: %s\n", ver, err)
		} else {
			if !conf.JSONOutput {
				fmt.Printf("Got results from Clair API v%d\n", ver)
			}
			break
		}
	}
	if err != nil {
		fail("Failed to analyze, exiting")
	}

	//apply whitelist
	numVulnerabilites := len(vs)
	vs = filterWhitelist(whitelist, vs, image.Name)
	numVulnerabilitiesAfterWhitelist := len(vs)

	groupBySeverity(vs)
	vsNumber := 0

	if conf.JSONOutput {
		iteratePriorities(conf.ClairOutput, func(sev string) {
			if conf.IgnoreUnfixed {
				// need to iterate over store[sev]
				for _, v := range store[sev] {
					if v.FixedBy != "" {
						vsNumber++
					}
				}
			} else {
				vsNumber += len(store[sev])
			}
			output.Vulnerabilities[sev] = store[sev]
		})
		enc := json.NewEncoder(os.Stdout)
		enc.Encode(output)
	} else {
		if numVulnerabilitiesAfterWhitelist < numVulnerabilites {
			//display how many vulnerabilities were whitelisted
			fmt.Printf("Whitelisted %d vulnerabilities\n", numVulnerabilites-numVulnerabilitiesAfterWhitelist)
		}
		fmt.Printf("Found %d vulnerabilities\n", len(vs))
		iteratePriorities(priorities[0], func(sev string) { fmt.Printf("%s: %d\n", sev, len(store[sev])) })
		fmt.Printf("\n")

		table := tablewriter.NewWriter(os.Stdout)
		header := []string{
			"Severity", "Name", "FeatureName", "FeatureVersion", "FixedBy", "Description", "Link",
		}
		table.SetHeader(header)
		table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
		table.SetRowSeparator("-")
		table.SetRowLine(true)
		table.SetAlignment(tablewriter.ALIGN_LEFT)

		var data [][]string

		iteratePriorities(conf.ClairOutput, func(sev string) {
			for _, v := range store[sev] {
				data = append(data, []string{
					getSeverityStyle(v.Severity),
					v.Name,
					v.FeatureName,
					v.FeatureVersion,
					v.FixedBy,
					v.Description,
					v.Link,
				})

				if conf.IgnoreUnfixed {
					if v.FixedBy != "" {
						vsNumber++
					}
				} else {
					vsNumber++
				}
			}
		})

		table.AppendBulk(data)

		if len(data) > 0 {
			table.Render()
		}

	}

	if vsNumber > conf.Threshold {
		os.Exit(1)
	}
}

func iteratePriorities(output string, f func(sev string)) {
	filtered := true
	for _, sev := range priorities {
		if filtered {
			if sev != output {
				continue
			} else {
				filtered = false
			}
		}

		if len(store[sev]) != 0 {
			f(sev)
		}
	}
}

func groupBySeverity(vs []*clair.Vulnerability) {
	for _, v := range vs {
		sevRow := vulnsBy(v.Severity, store)
		store[v.Severity] = append(sevRow, v)
	}
}

func vulnsBy(sev string, store map[string][]*clair.Vulnerability) []*clair.Vulnerability {
	items, found := store[sev]
	if !found {
		items = make([]*clair.Vulnerability, 0)
		store[sev] = items
	}
	return items
}

//Filter out whitelisted vulnerabilites
func filterWhitelist(whitelist *vulnerabilitiesWhitelist, vs []*clair.Vulnerability, imageName string) []*clair.Vulnerability {
	generalWhitelist := whitelist.General
	imageWhitelist := whitelist.Images

	filteredVs := make([]*clair.Vulnerability, 0, len(vs))

	for _, v := range vs {
		if _, exists := generalWhitelist[v.Name]; !exists {
			if _, exists := imageWhitelist[imageName][v.Name]; !exists {
				//vulnerability is not in the image whitelist, so add it to the list to return
				filteredVs = append(filteredVs, v)
			}
		}
	}

	return filteredVs
}
<commit_msg>Define severity styles directly against their associated values<commit_after>package main

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

	"github.com/olekukonko/tablewriter"
	"github.com/optiopay/klar/clair"
	"github.com/optiopay/klar/docker"
)

var store = make(map[string][]*clair.Vulnerability)

var SeverityStyle = map[string]string{
	"Defcon1":    "\033[1;31m%s\033[0m",
	"Critical":   "\033[1;31m%s\033[0m",
	"High":       "\033[0;31m%s\033[0m",
	"Medium":     "\033[0;33m%s\033[0m",
	"Low":        "\033[0;94m%s\033[0m",
	"Negligible": "\033[0;94m%s\033[0m",
	"Unknown":    "\033[0;97m%s\033[0m",
}

func getSeverityStyle(status string) string {
	if val, ok := SeverityStyle[status]; ok {
		// Return matched style
		return fmt.Sprintf(val, status)
	}

	// Return default style Unknown if not matched
	return fmt.Sprintf(SeverityStyle["Unknown"], status)
}

func main() {
	fail := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", format), a...)
		os.Exit(2)
	}

	if len(os.Args) != 2 {
		fail("Image name must be provided")
	}

	conf, err := newConfig(os.Args)
	if err != nil {
		fail("Invalid options: %s", err)
	}

	if !conf.JSONOutput {
		fmt.Fprintf(os.Stderr, "clair timeout %s\n", conf.ClairTimeout)
		fmt.Fprintf(os.Stderr, "docker timeout: %s\n", conf.DockerConfig.Timeout)
	}
	whitelist := &vulnerabilitiesWhitelist{}
	if conf.WhiteListFile != "" {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "whitelist file: %s\n", conf.WhiteListFile)
		}
		whitelist, err = parseWhitelistFile(conf.WhiteListFile)
		if err != nil {
			fail("Could not parse whitelist file: %s", err)
		}
	} else {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "no whitelist file\n")
		}
	}

	image, err := docker.NewImage(&conf.DockerConfig)
	if err != nil {
		fail("Can't parse qname: %s", err)
	}

	err = image.Pull()
	if err != nil {
		fail("Can't pull image: %s", err)
	}

	output := jsonOutput{
		Vulnerabilities: make(map[string][]*clair.Vulnerability),
	}

	if len(image.FsLayers) == 0 {
		fail("Can't pull fsLayers")
	} else {
		if conf.JSONOutput {
			output.LayerCount = len(image.FsLayers)
		} else {
			fmt.Printf("Analysing %d layers\n", len(image.FsLayers))
		}
	}

	var vs []*clair.Vulnerability
	for _, ver := range []int{1, 3} {
		c := clair.NewClair(conf.ClairAddr, ver, conf.ClairTimeout)
		vs, err = c.Analyse(image)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to analyze using API v%d: %s\n", ver, err)
		} else {
			if !conf.JSONOutput {
				fmt.Printf("Got results from Clair API v%d\n", ver)
			}
			break
		}
	}
	if err != nil {
		fail("Failed to analyze, exiting")
	}

	//apply whitelist
	numVulnerabilites := len(vs)
	vs = filterWhitelist(whitelist, vs, image.Name)
	numVulnerabilitiesAfterWhitelist := len(vs)

	groupBySeverity(vs)
	vsNumber := 0

	if conf.JSONOutput {
		iteratePriorities(conf.ClairOutput, func(sev string) {
			if conf.IgnoreUnfixed {
				// need to iterate over store[sev]
				for _, v := range store[sev] {
					if v.FixedBy != "" {
						vsNumber++
					}
				}
			} else {
				vsNumber += len(store[sev])
			}
			output.Vulnerabilities[sev] = store[sev]
		})
		enc := json.NewEncoder(os.Stdout)
		enc.Encode(output)
	} else {
		if numVulnerabilitiesAfterWhitelist < numVulnerabilites {
			//display how many vulnerabilities were whitelisted
			fmt.Printf("Whitelisted %d vulnerabilities\n", numVulnerabilites-numVulnerabilitiesAfterWhitelist)
		}
		fmt.Printf("Found %d vulnerabilities\n", len(vs))
		iteratePriorities(priorities[0], func(sev string) { fmt.Printf("%s: %d\n", sev, len(store[sev])) })
		fmt.Printf("\n")

		table := tablewriter.NewWriter(os.Stdout)
		header := []string{
			"Severity", "Name", "FeatureName", "FeatureVersion", "FixedBy", "Description", "Link",
		}
		table.SetHeader(header)
		table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
		table.SetRowSeparator("-")
		table.SetRowLine(true)
		table.SetAlignment(tablewriter.ALIGN_LEFT)

		var data [][]string

		iteratePriorities(conf.ClairOutput, func(sev string) {
			for _, v := range store[sev] {
				data = append(data, []string{
					getSeverityStyle(v.Severity),
					v.Name,
					v.FeatureName,
					v.FeatureVersion,
					v.FixedBy,
					v.Description,
					v.Link,
				})

				if conf.IgnoreUnfixed {
					if v.FixedBy != "" {
						vsNumber++
					}
				} else {
					vsNumber++
				}
			}
		})

		table.AppendBulk(data)

		if len(data) > 0 {
			table.Render()
		}

	}

	if vsNumber > conf.Threshold {
		os.Exit(1)
	}
}

func iteratePriorities(output string, f func(sev string)) {
	filtered := true
	for _, sev := range priorities {
		if filtered {
			if sev != output {
				continue
			} else {
				filtered = false
			}
		}

		if len(store[sev]) != 0 {
			f(sev)
		}
	}
}

func groupBySeverity(vs []*clair.Vulnerability) {
	for _, v := range vs {
		sevRow := vulnsBy(v.Severity, store)
		store[v.Severity] = append(sevRow, v)
	}
}

func vulnsBy(sev string, store map[string][]*clair.Vulnerability) []*clair.Vulnerability {
	items, found := store[sev]
	if !found {
		items = make([]*clair.Vulnerability, 0)
		store[sev] = items
	}
	return items
}

//Filter out whitelisted vulnerabilites
func filterWhitelist(whitelist *vulnerabilitiesWhitelist, vs []*clair.Vulnerability, imageName string) []*clair.Vulnerability {
	generalWhitelist := whitelist.General
	imageWhitelist := whitelist.Images

	filteredVs := make([]*clair.Vulnerability, 0, len(vs))

	for _, v := range vs {
		if _, exists := generalWhitelist[v.Name]; !exists {
			if _, exists := imageWhitelist[imageName][v.Name]; !exists {
				//vulnerability is not in the image whitelist, so add it to the list to return
				filteredVs = append(filteredVs, v)
			}
		}
	}

	return filteredVs
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dimg"
	"github.com/llgcode/draw2d/draw2dkit"
	"html/template"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"log"
	"net/http"
	"path/filepath"
	"strconv"
	"sync"
)

const (
	// ImageJpeg は出力画像のタイプが jpg
	ImageJpeg = iota
	// ImagePng は出力画像のタイプが png
	ImagePng
	// ImageGif は出力画像のタイプが gif
	ImageGif
)

// ImageType は出力画像タイプの型
type ImageType int

// ImageProp は出力画像のプロパティを保持する
type ImageProp struct {
	Width     int
	Height    int
	TextColor color.RGBA
	FillColor color.RGBA
	Text      string
	FontSize  float64
	HasSize   bool
	Type      ImageType
}

// StringAt はテキストが中心に表示される x, y 座標の値を返す
func (ip *ImageProp) StringAt(gc *draw2dimg.GraphicContext) (float64, float64) {
	left, top, right, bottom := gc.GetStringBounds(ip.Text)
	x := (float64(ip.Width) - (right - left)) / 2
	var fontHeight float64
	if !ip.HasSize {
		fontHeight = (bottom - top) / 4
	}
	y := (float64(ip.Height) / 2) + fontHeight
	return x, y
}

// PropAt は画像サイズ(幅x高さ)のテキストが中心に表示される x, y 座標の値を返す
func (ip *ImageProp) PropAt(text string, gc *draw2dimg.GraphicContext) (float64, float64) {
	left, top, right, bottom := gc.GetStringBounds(text)
	x := (float64(ip.Width) - (right - left)) / 2
	y := (float64(ip.Height) / 2) + ((bottom - top) * 2)
	return x, y
}

// makeImage は ImageProp のプロパティから画像(image.RGBA)を生成して返すl
func makeImage(ip *ImageProp) *image.RGBA {
	// ベース画像を作成
	img := image.NewRGBA(image.Rect(0, 0, ip.Width, ip.Height))
	gc := draw2dimg.NewGraphicContext(img)

	// 背景を描画
	gc.SetFillColor(ip.FillColor)
	draw2dkit.Rectangle(gc, 0, 0, float64(ip.Width), float64(ip.Height))
	gc.Fill()

	// フォント設定
	draw2d.SetFontFolder("./fonts")
	gc.SetFontData(draw2d.FontData{
		Name:   "mplus",
		Family: draw2d.FontFamilyMono,
	})
	// フォント色
	gc.SetFillColor(ip.TextColor)
	// フォントサイズ
	gc.SetFontSize(ip.FontSize)

	// テキストを配置
	x, y := ip.StringAt(gc)
	gc.FillStringAt(ip.Text, x, y)

	// 画像サイズ(幅x高さ)を表示
	if ip.HasSize {
		gc.SetFontSize(ip.FontSize * 0.8)
		propText := fmt.Sprintf("%d x %d", ip.Width, ip.Height)
		x, y := ip.PropAt(propText, gc)
		gc.FillStringAt(propText, x, y)
	}

	gc.Close()

	return img
}

func makeImageHandler(w http.ResponseWriter, r *http.Request) {
	// ImageProp の初期化
	ip := ImageProp{
		Width:     180,
		Height:    120,
		TextColor: color.RGBA{0xff, 0xff, 0xff, 0xff},
		FillColor: color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
		Text:      "",
		FontSize:  14,
		HasSize:   false,
		Type:      ImageJpeg,
	}

	// URI 引数を取得して ImageProp の値を更新する
	query := r.URL.Query()
	// 幅
	if newWidth, err := strconv.Atoi(query.Get("w")); err == nil {
		if newWidth > 0 {
			ip.Width = newWidth
		}
	}
	// 高さ
	if newHeight, err := strconv.Atoi(query.Get("h")); err == nil {
		if newHeight > 0 {
			ip.Height = newHeight
		}
	}
	// フォントサイズ
	if newFs, err := strconv.ParseFloat(query.Get("fs"), 64); err == nil {
		if newFs > 0 {
			ip.FontSize = newFs
		}
	}
	// テキスト
	if newText := query.Get("s"); len(newText) > 0 {
		ip.Text = newText
	}
	// 画像サイズ(幅x高さ)の表示
	ip.HasSize = (query.Get("p") == "1")
	// 画像タイプ
	switch query.Get("t") {
	case "png":
		ip.Type = ImagePng
	case "gif":
		ip.Type = ImageGif
	}

	// ImageProp のプロパティを元に画像を作成し、レスポンスに出力する
	img := makeImage(&ip)
	switch ip.Type {
	case ImagePng:
		png.Encode(w, img)
	case ImageGif:
		gif.Encode(w, img, nil)
	default:
		jpeg.Encode(w, img, nil)
	}
}

type templateHandler struct {
	once     sync.Once
	filename string
	templ    *template.Template
}

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	t.once.Do(func() {
		t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
	})
	if err := t.templ.Execute(w, nil); err != nil {
		log.Fatalf("templateHandler.ServeHTTP:", err)
	}
}

func main() {
	var addr = flag.String("addr", ":8080", "アプリケーションのアドレス")
	flag.Parse() // フラグを解析

	http.Handle("/", &templateHandler{filename: "home.html"})
	http.HandleFunc("/lorem", makeImageHandler)

	// Web サーバを開始
	log.Println("Webサーバを開始します。ポート：", *addr)
	if err := http.ListenAndServe(*addr, nil); err != nil {
		log.Fatalf("ListenAndServe:", err)
	}
}
<commit_msg>Modify default port setting<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dimg"
	"github.com/llgcode/draw2d/draw2dkit"
	"html/template"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"log"
	"net/http"
	"path/filepath"
	"strconv"
	"sync"
)

const (
	// ImageJpeg は出力画像のタイプが jpg
	ImageJpeg = iota
	// ImagePng は出力画像のタイプが png
	ImagePng
	// ImageGif は出力画像のタイプが gif
	ImageGif
)

// ImageType は出力画像タイプの型
type ImageType int

// ImageProp は出力画像のプロパティを保持する
type ImageProp struct {
	Width     int
	Height    int
	TextColor color.RGBA
	FillColor color.RGBA
	Text      string
	FontSize  float64
	HasSize   bool
	Type      ImageType
}

// StringAt はテキストが中心に表示される x, y 座標の値を返す
func (ip *ImageProp) StringAt(gc *draw2dimg.GraphicContext) (float64, float64) {
	left, top, right, bottom := gc.GetStringBounds(ip.Text)
	x := (float64(ip.Width) - (right - left)) / 2
	var fontHeight float64
	if !ip.HasSize {
		fontHeight = (bottom - top) / 4
	}
	y := (float64(ip.Height) / 2) + fontHeight
	return x, y
}

// PropAt は画像サイズ(幅x高さ)のテキストが中心に表示される x, y 座標の値を返す
func (ip *ImageProp) PropAt(text string, gc *draw2dimg.GraphicContext) (float64, float64) {
	left, top, right, bottom := gc.GetStringBounds(text)
	x := (float64(ip.Width) - (right - left)) / 2
	y := (float64(ip.Height) / 2) + ((bottom - top) * 2)
	return x, y
}

// makeImage は ImageProp のプロパティから画像(image.RGBA)を生成して返すl
func makeImage(ip *ImageProp) *image.RGBA {
	// ベース画像を作成
	img := image.NewRGBA(image.Rect(0, 0, ip.Width, ip.Height))
	gc := draw2dimg.NewGraphicContext(img)

	// 背景を描画
	gc.SetFillColor(ip.FillColor)
	draw2dkit.Rectangle(gc, 0, 0, float64(ip.Width), float64(ip.Height))
	gc.Fill()

	// フォント設定
	draw2d.SetFontFolder("./fonts")
	gc.SetFontData(draw2d.FontData{
		Name:   "mplus",
		Family: draw2d.FontFamilyMono,
	})
	// フォント色
	gc.SetFillColor(ip.TextColor)
	// フォントサイズ
	gc.SetFontSize(ip.FontSize)

	// テキストを配置
	x, y := ip.StringAt(gc)
	gc.FillStringAt(ip.Text, x, y)

	// 画像サイズ(幅x高さ)を表示
	if ip.HasSize {
		gc.SetFontSize(ip.FontSize * 0.8)
		propText := fmt.Sprintf("%d x %d", ip.Width, ip.Height)
		x, y := ip.PropAt(propText, gc)
		gc.FillStringAt(propText, x, y)
	}

	gc.Close()

	return img
}

func makeImageHandler(w http.ResponseWriter, r *http.Request) {
	// ImageProp の初期化
	ip := ImageProp{
		Width:     180,
		Height:    120,
		TextColor: color.RGBA{0xff, 0xff, 0xff, 0xff},
		FillColor: color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
		Text:      "",
		FontSize:  14,
		HasSize:   false,
		Type:      ImageJpeg,
	}

	// URI 引数を取得して ImageProp の値を更新する
	query := r.URL.Query()
	// 幅
	if newWidth, err := strconv.Atoi(query.Get("w")); err == nil {
		if newWidth > 0 {
			ip.Width = newWidth
		}
	}
	// 高さ
	if newHeight, err := strconv.Atoi(query.Get("h")); err == nil {
		if newHeight > 0 {
			ip.Height = newHeight
		}
	}
	// フォントサイズ
	if newFs, err := strconv.ParseFloat(query.Get("fs"), 64); err == nil {
		if newFs > 0 {
			ip.FontSize = newFs
		}
	}
	// テキスト
	if newText := query.Get("s"); len(newText) > 0 {
		ip.Text = newText
	}
	// 画像サイズ(幅x高さ)の表示
	ip.HasSize = (query.Get("p") == "1")
	// 画像タイプ
	switch query.Get("t") {
	case "png":
		ip.Type = ImagePng
	case "gif":
		ip.Type = ImageGif
	}

	// ImageProp のプロパティを元に画像を作成し、レスポンスに出力する
	img := makeImage(&ip)
	switch ip.Type {
	case ImagePng:
		png.Encode(w, img)
	case ImageGif:
		gif.Encode(w, img, nil)
	default:
		jpeg.Encode(w, img, nil)
	}
}

type templateHandler struct {
	once     sync.Once
	filename string
	templ    *template.Template
}

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	t.once.Do(func() {
		t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
	})
	if err := t.templ.Execute(w, nil); err != nil {
		log.Fatalf("templateHandler.ServeHTTP:", err)
	}
}

func main() {
	var addr = flag.String("addr", "", "アプリケーションのアドレス")
	flag.Parse() // フラグを解析

	http.Handle("/", &templateHandler{filename: "home.html"})
	http.HandleFunc("/lorem", makeImageHandler)

	// Web サーバを開始
	log.Println("Webサーバを開始します。ポート：", *addr)
	if err := http.ListenAndServe(*addr, nil); err != nil {
		log.Fatalf("ListenAndServe:", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"os"
	"strconv"
)

type scanner struct {
	sc *bufio.Scanner
}

func (sc *scanner) next() string {
	sc.sc.Scan()
	return sc.sc.Text()
}

func (sc *scanner) nextInt() int {
	i, err := strconv.Atoi(sc.next())
	if err != nil {
		panic(err)
	}
	return i
}

func newScanner(r io.Reader) *scanner {
	sc := bufio.NewScanner(r)
	sc.Split(bufio.ScanWords)
	return &scanner{
		sc: sc,
	}
}

var sc = newScanner(os.Stdin)

func main() {
}
<commit_msg>add "max" and "min" functions<commit_after>package main

import (
	"bufio"
	"io"
	"os"
	"strconv"
)

type scanner struct {
	sc *bufio.Scanner
}

func (sc *scanner) next() string {
	sc.sc.Scan()
	return sc.sc.Text()
}

func (sc *scanner) nextInt() int {
	i, err := strconv.Atoi(sc.next())
	if err != nil {
		panic(err)
	}
	return i
}

func newScanner(r io.Reader) *scanner {
	sc := bufio.NewScanner(r)
	sc.Split(bufio.ScanWords)
	return &scanner{
		sc: sc,
	}
}

var sc = newScanner(os.Stdin)

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func main() {
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log"
	"strings"

	"flag"
)

var (
	n          = flag.Int("n", 8, "n queens, in an nxn grid")
	CantBeDone = errors.New("Can't be done")
)

type Board struct {
	grid   [][]bool
	queens []Location
}

type Location struct {
	X int
	Y int
}

func main() {
	flag.Parse()

	board := createBoard(*n)

	err := board.PlaceQueens(*n)
	fmt.Println(board.String())
	if err != nil {
		log.Fatalln("What the actual fuck:", err)
	}

}

// Simple, but used here
func abs(n int) int {
	if n < 0 {
		return -n
	} else {
		return n
	}
}

// Returns an nxn grid off booleans
// The boolean is true if there's a queen placed there
func createBoard(n int) Board {
	grid := make([][]bool, n)
	for i, _ := range grid {
		row := make([]bool, n)
		grid[i] = row
	}

	locations := make([]Location, 0)

	return Board{
		grid:   grid,
		queens: locations,
	}
}

// Attempts to place n queens on the board.
// Returns an error if it can't be done
func (b *Board) PlaceQueens(n int) error {
	// check for freeness
	if n <= 0 {
		return nil
	}

	// Since len(queens) == len(grid), and they can't share rows,
	// we'll just assign it one by it's number
	y := n - 1
	row := b.grid[y]

placements:
	for x := range row {

		// Already a queen here
		if row[x] {
			continue placements
		}

		// Check if this location violates the rules
		for _, queen := range b.queens {
			// See if the x or y match (same row/column), or diagonals (differences of x and y match)
			if x == queen.X || y == queen.Y || abs(x-queen.X) == abs(y-queen.Y) {
				continue placements
			}
		}

		// Place the queen
		row[x] = true
		b.queens = append(b.queens, Location{X: x, Y: y})

		// Recurse!
		err := b.PlaceQueens(n - 1)
		// If we couldn't place the queens
		if err != nil {
			// Remove our queen
			row[x] = false
			b.queens = b.queens[:len(b.queens)-1]

			// Continue to next option
			continue placements
		}

		// We did place the queens, we did!
		return nil
	}

	// Couldn't find a place for the queen :(
	return CantBeDone
}

// For pretty printing the board
func (b *Board) String() string {
	toPrint := make([]string, len(b.grid)+2)
	toPrint[0] = strings.Repeat("_", len(b.grid)+2)
	toPrint[len(toPrint)-1] = strings.Repeat("-", len(b.grid)+2)
	for y, row := range b.grid {
		rowText := make([]string, len(row)+2)
		rowText[0] = "|"
		rowText[len(rowText)-1] = "|"

		for x, element := range row {
			if element {
				rowText[x+1] = "Q"
			} else {
				rowText[x+1] = "x"
			}
		}

		toPrint[y+1] = strings.Join(rowText, "")
	}
	return strings.Join(toPrint, "\n")
}
<commit_msg>optimization: dont compare assigned row<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"strings"

	"flag"
)

var (
	n          = flag.Int("n", 8, "n queens, in an nxn grid")
	CantBeDone = errors.New("Can't be done")
)

type Board struct {
	grid [][]bool

	// The columns where there are existing queens
	queens []int
}

func main() {
	flag.Parse()

	board := createBoard(*n)

	err := board.PlaceQueens(*n)
	fmt.Println(board.String())
	if err != nil {
		log.Fatalln("What the actual fuck:", err)
	}

}

// Simple, but used here
func abs(n int) int {
	if n < 0 {
		return -n
	} else {
		return n
	}
}

// Returns an nxn grid off booleans
// The boolean is true if there's a queen placed there
func createBoard(n int) Board {
	grid := make([][]bool, n)
	for i, _ := range grid {
		row := make([]bool, n)
		grid[i] = row
	}

	locations := make([]int, 0)

	return Board{
		grid:   grid,
		queens: locations,
	}
}

// Attempts to place n queens on the board.
// Returns an error if it can't be done
func (b *Board) PlaceQueens(n int) error {
	// check for freeness
	if n <= 0 {
		return nil
	}

	// Since len(queens) == len(grid), and they can't share rows,
	// we'll just assign it one by it's number
	y := len(b.grid) - n
	row := b.grid[y]

placements:
	for x := range row {

		// Already a queen here
		if row[x] {
			continue placements
		}

		// Check if this location violates the rules
		for queenY, queenX := range b.queens {
			// See if the x or y match (same row/column), or diagonals (differences of x and y match)
			// Y should never match, because it's assigned
			if x == queenX || abs(x-queenX) == abs(y-queenY) {
				continue placements
			}
		}

		// Place the queen
		row[x] = true
		b.queens = append(b.queens, x)

		// Recurse!
		err := b.PlaceQueens(n - 1)
		// If we couldn't place the queens
		if err != nil {
			// Remove our queen
			row[x] = false
			b.queens = b.queens[:len(b.queens)-1]

			// Continue to next option
			continue placements
		}

		// We did place the queens, we did!
		return nil
	}

	// Couldn't find a place for the queen :(
	return CantBeDone
}

// For pretty printing the board
func (b *Board) String() string {
	toPrint := make([]string, len(b.grid)+2)
	toPrint[0] = strings.Repeat("_", len(b.grid)+2)
	toPrint[len(toPrint)-1] = strings.Repeat("-", len(b.grid)+2)
	for y, row := range b.grid {
		rowText := make([]string, len(row)+2)
		rowText[0] = "|"
		rowText[len(rowText)-1] = "|"

		for x, element := range row {
			if element {
				rowText[x+1] = "Q"
			} else {
				rowText[x+1] = "x"
			}
		}

		toPrint[y+1] = strings.Join(rowText, "")
	}
	return strings.Join(toPrint, "\n")
}
<|endoftext|>


<commit_before>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * 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.
 *
 * main.go: http server application for cassandra-summit-cfp-review
 *
 */

import (
	"fmt"
	"github.com/gocql/gocql"
	"github.com/gorilla/mux"
	"net/http"
)

var cass *gocql.Session
var store *CQLStore

const sessCookie string = "cfp2014"
const audience string = "localhost:8080"

var privKey []byte = []byte("2213AA86-CEB4-48FA-A65B-4AC37687131E")

func main() {
	// connect to Cassandra
	cluster := gocql.NewCluster("127.0.0.1")
	cluster.Keyspace = "ccfp"
	cluster.Consistency = gocql.Quorum

	var err error
	cass, err = cluster.CreateSession()
	if err != nil {
		panic(fmt.Sprintf("Error creating Cassandra session: %v", err))
	}
	defer cass.Close()

	store = NewCQLStore(cass, privKey)

	r := mux.NewRouter()

	r.HandleFunc("/", RootHandler)
	r.HandleFunc("/abstracts/", AbstractsHandler)
	r.HandleFunc("/abstracts/{id:[-a-f0-9]+}", AbstractHandler)
	r.HandleFunc("/comments/", CommentsHandler)
	r.HandleFunc("/comments/{abstract_id:[-a-f0-9]+}", CommentsHandler)
	r.HandleFunc("/updatescores", ScoreUpdateHandler)
	r.HandleFunc("/login", LoginHandler)
	r.HandleFunc("/logout", LogoutHandler)

	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))

	http.Handle("/", r)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>add command-line flags<commit_after>package main

/*
 * Copyright 2014 Albert P. Tobey <atobey@datastax.com> @AlTobey
 *
 * 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.
 *
 * main.go: http server application for cassandra-summit-cfp-review
 *
 */

import (
	"flag"
	"fmt"
	"github.com/gocql/gocql"
	"github.com/gorilla/mux"
	"net/http"
)

const sessCookie string = "cfpeu2014"
const audience string = "localhost:8080"

var privKey []byte = []byte("2213AA86-CEB4-48FA-A65B-4AC37687131E")
var store *CQLStore
var addrFlag, cqlFlag, ksFlag string
var cass *gocql.Session

func init() {
	flag.StringVar(&addrFlag, "addr", ":8080", "IP:PORT or :PORT address to listen on")
	flag.StringVar(&cqlFlag, "cql", "127.0.0.1", "IP or IP:port of the Cassandra CQL service")
	flag.StringVar(&ksFlag, "ks", "ccfp", "keyspace containing the f7u12 schema")
}

func main() {
	flag.Parse()
	// connect to Cassandra
	cluster := gocql.NewCluster(cqlFlag)
	cluster.Keyspace = ksFlag
	cluster.Consistency = gocql.Quorum

	var err error
	cass, err = cluster.CreateSession()
	if err != nil {
		panic(fmt.Sprintf("Error creating Cassandra session: %v", err))
	}
	defer cass.Close()

	store = NewCQLStore(cass, privKey)

	r := mux.NewRouter()

	r.HandleFunc("/", RootHandler)
	r.HandleFunc("/abstracts/", AbstractsHandler)
	r.HandleFunc("/abstracts/{id:[-a-f0-9]+}", AbstractHandler)
	r.HandleFunc("/comments/", CommentsHandler)
	r.HandleFunc("/comments/{abstract_id:[-a-f0-9]+}", CommentsHandler)
	r.HandleFunc("/updatescores", ScoreUpdateHandler)
	r.HandleFunc("/login", LoginHandler)
	r.HandleFunc("/logout", LogoutHandler)

	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))

	http.Handle("/", r)

	http.ListenAndServe(addrFlag, nil)
}
<|endoftext|>


<commit_before>// Enhanced Markdown template processor.
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/mh-cbon/emd/cli"
	"github.com/mh-cbon/emd/deprecated"
	"github.com/mh-cbon/emd/emd"
	gostd "github.com/mh-cbon/emd/go"
	gononstd "github.com/mh-cbon/emd/go-nonstd"
	"github.com/mh-cbon/emd/provider"
	"github.com/mh-cbon/emd/std"
)

// VERSION defines the running build id.
var VERSION = "0.0.0"

var program = cli.NewProgram("emd", VERSION)

func main() {
	program.Bind()
	if err := program.Run(os.Args); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

// gen sub command
type gencommand struct {
	*cli.Command
	in        string
	out       string
	data      string
	help      bool
	shortHelp bool
}

// init sub command
type initcommand struct {
	*cli.Command
	help      bool
	shortHelp bool
	out       string
	force     bool
}

func init() {
	gen := &gencommand{Command: cli.NewCommand("gen", "Process an emd file.", Generate)}
	gen.Set.StringVar(&gen.in, "in", "", "Input src file")
	gen.Set.StringVar(&gen.out, "out", "-", "Output destination, defaults to stdout")
	gen.Set.StringVar(&gen.data, "data", "", "JSON map of data")
	gen.Set.BoolVar(&gen.help, "help", false, "Show help")
	gen.Set.BoolVar(&gen.shortHelp, "h", false, "Show help")

	program.Add(gen)

	ini := &initcommand{Command: cli.NewCommand("init", "Init a basic emd file.", InitFile)}
	ini.Set.BoolVar(&ini.help, "help", false, "Show help")
	ini.Set.BoolVar(&ini.shortHelp, "h", false, "Show help")
	ini.Set.BoolVar(&ini.force, "force", false, "Force write")
	ini.Set.StringVar(&ini.out, "out", "README.e.md", "Out file")
	program.Add(ini)
}

// Generate is the cli command implementation of gen.
func Generate(s cli.Commander) error {

	cmd, ok := s.(*gencommand)
	if ok == false {
		return fmt.Errorf("Invalid command type %T", s)
	}

	if cmd.help || cmd.shortHelp {
		return program.ShowCmdUsage(cmd)
	}

	out, err := getStdout(cmd.out)
	if err != nil {
		return err
	}
	if x, ok := out.(io.Closer); ok {
		defer x.Close()
	}

	cwd, err := getCwd()
	if err != nil {
		return err
	}
	gopath := filepath.Join(os.Getenv("GOPATH"), "src")
	gopath = strings.Replace(gopath, "\\", "/", -1)
	projectPath := cwd[len(gopath):]

	plugins := getPlugins()
	data := getData(projectPath)

	if cmd.data != "" {
		if err := json.Unmarshal([]byte(cmd.data), &data); err != nil {
			return fmt.Errorf("Cannot decode JSON data string: %v", err)
		}
	}

	gen := emd.NewGenerator()

	gen.SetDataMap(data)

	if cmd.in != "" {
		if err := gen.AddFileTemplate(cmd.in); err != nil {
			return err
		}
	} else if s, err := os.Stat("README.e.md"); !os.IsNotExist(err) && s.IsDir() == false {
		if err := gen.AddFileTemplate("README.e.md"); err != nil {
			return err
		}
	} else {
		gen.AddTemplate(defTemplate)
	}

	for name, plugin := range plugins {
		if err := plugin(gen); err != nil {
			return fmt.Errorf("Failed to register %v package: %v", name, err)
		}
	}

	if err := gen.Execute(out); err != nil {
		return fmt.Errorf("Generator failed: %v", err)
	}

	return nil
}

func getData(cwd string) map[string]interface{} {
	p := provider.Default(cwd)
	if p.Match() == false {
		log.Printf("Failed to identify this project url %v\n", cwd)
	}
	return map[string]interface{}{
		"Name":         p.GetProjectName(),
		"User":         p.GetUserName(),
		"ProviderURL":  p.GetProviderURL(),
		"ProviderName": p.GetProviderID(),
		"URL":          p.GetURL(),
		"ProjectURL":   p.GetProjectURL(),
		"Branch":       "master",
	}
}

func getPlugins() map[string]func(*emd.Generator) error {
	return map[string]func(*emd.Generator) error{
		"std":        std.Register,
		"gostd":      gostd.Register,
		"gononstd":   gononstd.Register,
		"deprecated": deprecated.Register,
	}
}

func getStdout(out string) (io.Writer, error) {

	ret := os.Stdout

	if out != "-" {
		f, err := os.Create(out)
		if err != nil {
			f, err = os.Open(out)
			if err != nil {
				return nil, fmt.Errorf("Cannot open out destination: %v", err)
			}
		}
		ret = f
	}
	return ret, nil
}

func getCwd() (string, error) {
	cwd, err := os.Getwd()
	if err != nil {
		return "", fmt.Errorf("Failed to determmine cwd: %v", err)
	}
	// for those who uses symlinks to relocate their code,
	// the path must be evaluated.
	cwd, err = filepath.EvalSymlinks(cwd)
	if err != nil {
		return "", fmt.Errorf("Failed to determmine eval path: %v", err)
	}
	return cwd, nil
}

// InitFile creates a basic emd file if none exits.
func InitFile(s cli.Commander) error {

	cmd, ok := s.(*initcommand)
	if ok == false {
		return fmt.Errorf("Invalid command type %T", s)
	}

	if cmd.help || cmd.shortHelp {
		return program.ShowCmdUsage(cmd)
	}

	out := cmd.out
	if cmd.out == "" {
		out = "README.e.md"
	}
	if _, err := os.Stat(out); !cmd.force && !os.IsNotExist(err) {
		return fmt.Errorf("File exits at %q", out)
	}
	return ioutil.WriteFile(out, []byte(defTemplate), os.ModePerm)
}

var defTemplate = `# {{.Name}}

{{template "badge/goreport" .}} {{template "badge/godoc" .}}

{{pkgdoc}}

# {{toc 5}}

# Install

{{template "gh/releases" .}}

#### go
{{template "go/install" .}}
`
<commit_msg>Add verbosity support, Add stdin support, fix path detection close #15<commit_after>// Enhanced Markdown template processor.
package main

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

	"github.com/mh-cbon/emd/cli"
	"github.com/mh-cbon/emd/deprecated"
	"github.com/mh-cbon/emd/emd"
	gostd "github.com/mh-cbon/emd/go"
	gononstd "github.com/mh-cbon/emd/go-nonstd"
	"github.com/mh-cbon/emd/provider"
	"github.com/mh-cbon/emd/std"
)

// VERSION defines the running build id.
var VERSION = "0.0.0"

var program = cli.NewProgram("emd", VERSION)

var verbose bool

func logMsg(f string, args ...interface{}) {
	if verbose {
		log.Printf(f+"\n", args...)
	}
}

func main() {
	program.Bind()
	if err := program.Run(os.Args); err != nil {
		log.Println(err)
		os.Exit(1)
	}
}

// gen sub command
type gencommand struct {
	*cli.Command
	in        string
	out       string
	data      string
	help      bool
	shortHelp bool
}

// init sub command
type initcommand struct {
	*cli.Command
	help      bool
	shortHelp bool
	out       string
	force     bool
}

func init() {
	gen := &gencommand{Command: cli.NewCommand("gen", "Process an emd file.", Generate)}
	gen.Set.StringVar(&gen.in, "in", "", "Input src file")
	gen.Set.StringVar(&gen.out, "out", "-", "Output destination, defaults to stdout")
	gen.Set.StringVar(&gen.data, "data", "", "JSON map of data")
	gen.Set.BoolVar(&gen.help, "help", false, "Show help")
	gen.Set.BoolVar(&gen.shortHelp, "h", false, "Show help")
	program.Add(gen)

	ini := &initcommand{Command: cli.NewCommand("init", "Init a basic emd file.", InitFile)}
	ini.Set.BoolVar(&ini.help, "help", false, "Show help")
	ini.Set.BoolVar(&ini.shortHelp, "h", false, "Show help")
	ini.Set.BoolVar(&ini.force, "force", false, "Force write")
	ini.Set.StringVar(&ini.out, "out", "README.e.md", "Out file")
	program.Add(ini)

	verbose = os.Getenv("VERBOSE") != ""
}

// Generate is the cli command implementation of gen.
func Generate(s cli.Commander) error {

	cmd, ok := s.(*gencommand)
	if ok == false {
		return fmt.Errorf("Invalid command type %T", s)
	}

	if cmd.help || cmd.shortHelp {
		return program.ShowCmdUsage(cmd)
	}

	out, err := getStdout(cmd.out)
	if err != nil {
		return err
	}
	if x, ok := out.(io.Closer); ok {
		defer x.Close()
	}

	cwd, err := os.Getwd()
	if err != nil {
		return err
	}
	logMsg("cwd %q", cwd)

	gopath := filepath.Join(os.Getenv("GOPATH"), "src")
	gopath = strings.Replace(gopath, "\\", "/", -1)

	if cwd[:len(gopath)] != gopath {
		cwd, err = filepath.EvalSymlinks(cwd)
		if err != nil {
			return err
		}
		if cwd[:len(gopath)] != gopath {
			return fmt.Errorf("Invalid working directory %q", cwd)
		}
	}

	projectPath := cwd[len(gopath):]
	logMsg("projectPath %q", projectPath)

	plugins := getPlugins()
	data, err := getData(projectPath)
	if err != nil {
		return err
	}

	if cmd.data != "" {
		if err := json.Unmarshal([]byte(cmd.data), &data); err != nil {
			return fmt.Errorf("Cannot decode JSON data string: %v", err)
		}
	}

	gen := emd.NewGenerator()

	gen.SetDataMap(data)

	if cmd.in != "" {
		if err := gen.AddFileTemplate(cmd.in); err != nil {
			return err
		}
	} else if s, err := os.Stat("README.e.md"); !os.IsNotExist(err) && s.IsDir() == false {
		if err := gen.AddFileTemplate("README.e.md"); err != nil {
			return err
		}
	} else {
		var b bytes.Buffer
		io.Copy(&b, os.Stdin)
		if b.Len() > 0 {
			gen.AddTemplate(b.String())
		} else {
			gen.AddTemplate(defTemplate)
		}
	}

	for name, plugin := range plugins {
		if err := plugin(gen); err != nil {
			return fmt.Errorf("Failed to register %v package: %v", name, err)
		}
	}

	if err := gen.Execute(out); err != nil {
		return fmt.Errorf("Generator failed: %v", err)
	}

	return nil
}

func getData(cwd string) (map[string]interface{}, error) {
	p := provider.Default(cwd)
	if p.Match() == false {
		return nil, fmt.Errorf("Failed to identify this path %q\n", cwd)
	}
	return map[string]interface{}{
		"Name":         p.GetProjectName(),
		"User":         p.GetUserName(),
		"ProviderURL":  p.GetProviderURL(),
		"ProviderName": p.GetProviderID(),
		"URL":          p.GetURL(),
		"ProjectURL":   p.GetProjectURL(),
		"Branch":       "master",
	}, nil
}

func getPlugins() map[string]func(*emd.Generator) error {
	return map[string]func(*emd.Generator) error{
		"std":        std.Register,
		"gostd":      gostd.Register,
		"gononstd":   gononstd.Register,
		"deprecated": deprecated.Register,
	}
}

func getStdout(out string) (io.Writer, error) {

	ret := os.Stdout

	if out != "-" {
		f, err := os.Create(out)
		if err != nil {
			f, err = os.Open(out)
			if err != nil {
				return nil, fmt.Errorf("Cannot open out destination: %v", err)
			}
		}
		ret = f
	}
	return ret, nil
}

// InitFile creates a basic emd file if none exits.
func InitFile(s cli.Commander) error {

	cmd, ok := s.(*initcommand)
	if ok == false {
		return fmt.Errorf("Invalid command type %T", s)
	}

	if cmd.help || cmd.shortHelp {
		return program.ShowCmdUsage(cmd)
	}

	out := cmd.out
	if cmd.out == "" {
		out = "README.e.md"
	}
	if _, err := os.Stat(out); !cmd.force && !os.IsNotExist(err) {
		return fmt.Errorf("File exits at %q", out)
	}
	return ioutil.WriteFile(out, []byte(defTemplate), os.ModePerm)
}

var defTemplate = `# {{.Name}}

{{template "badge/goreport" .}} {{template "badge/godoc" .}}

{{pkgdoc}}

# {{toc 5}}

# Install

{{template "gh/releases" .}}

#### go
{{template "go/install" .}}
`
<|endoftext|>


<commit_before>package main

import (
	"flag"
)

func main() {
	flag.Parse()

	/*
	  $> golang2pkg labix.org/v2/mgo
	  - check if arg is in the current GOROOT or GOPATH or build.IsLocalImport
	   -- no:
	      ** mktmpdir and set GOPATH env
	      ** invoke `go get -d arg`
	   -- yes:
	    ** cp to mktmpdir
	  - scan for deps to cp to mktmpdir
	  - scan tmpdir for root import to package
	  - deduce the type of build artificat to generate
	  - for each root import
	    ** render a relavant version string (git, hg, bzr, etc)
	    ** make a *.tar.gz like `filepath.Base(path)-Version().tar.gz`
	    ** is the source-only flag was passed
	     -- no: render the build artifact.
	     -- yes: then print source name

	  - rendering the build artifact
	    ** *build.Package.IsCommand() wiil show whether the import results in an executable.
	    ** this means for a tree with source directories, that multiple rpms/debs may need to be generated
	    ** _any_ final executable build ought to be packaged with no runtime deps (unless linked to C libs)
	      -- thankfully there is a post rpm job that will append runtime requires based on ldd linkage
	*/
}
<commit_msg>initial working fetch of args<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path"

	"github.com/vbatts/golang2pkg/imports"
)

func main() {
	var (
		output string
		root   string
		debug  bool
		//importname string
	)

	cwd, err := os.Getwd()
	if err != nil {
		cwd = os.TempDir()
	}

	root = fmt.Sprintf("%s/golang2pkg-%d", os.TempDir(), os.Getpid())

	//flag.StringVar(&importname, "importname", "", "overide the qualified import path (for a relative path packaging)")
	flag.StringVar(&root, "root", root, "root directory to treat as GOPATH for imports collected")
	flag.StringVar(&output, "output", cwd, "output directory for artifacts")
	flag.BoolVar(&debug, "debug", false, "debugging output")
	flag.Parse()

	if err = os.MkdirAll(path.Join(root, "src"), 0755); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}

	// if we can get the collection of current pkgs,
	// then symlink those present to our root, unless they're already there
	if pkgs, err := imports.FindImportsDefault(); err == nil {
		for _, pkg := range pkgs {
			for _, arg := range flag.Args() {
				if pkg.ImportPath == arg {
					if _, err = os.Stat(path.Join(root, "src", arg)); os.IsNotExist(err) {
            dest := path.Join(root,"src",arg)
            if debug {
              fmt.Printf("making dir '%s'\n", path.Dir(dest))
            }
						if err = os.MkdirAll(path.Dir(dest), 0755); err != nil {
							fmt.Fprintf(os.Stderr, "WARN: %s\n", err)
							continue
						}
						err = os.Symlink(path.Join(pkg.SrcRoot, pkg.ImportPath), dest)
						if err != nil {
							fmt.Fprintf(os.Stderr, "WARN: %s\n", err)
						}
					}
				}
			}
		}
	}
	fmt.Println(root)

	for _, arg := range flag.Args() {
		err = imports.GetPkgSource(arg, root)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
	}

	pkgs, err := imports.FindImports(root)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
	for _, pkg := range pkgs {
		fmt.Println(path.Join(pkg.SrcRoot, pkg.ImportPath))
	}

	/*
	  $> golang2pkg labix.org/v2/mgo
	  - check if arg is in the current GOROOT or GOPATH or build.IsLocalImport
	   -- no:
	      ** mktmpdir and set GOPATH env
	      ** invoke `go get -d arg`
	   -- yes:
	    ** cp to mktmpdir
	  - scan for deps to cp to mktmpdir
	  - scan tmpdir for root import to package
	  - deduce the type of build artificat to generate
	  - for each root import
	    ** render a relavant version string (git, hg, bzr, etc)
	    ** make a *.tar.gz like `filepath.Base(path)-Version().tar.gz`
	    ** is the source-only flag was passed
	     -- no: render the build artifact.
	     -- yes: then print source name

	  - rendering the build artifact
	    ** *build.Package.IsCommand() wiil show whether the import results in an executable.
	    ** this means for a tree with source directories, that multiple rpms/debs may need to be generated
	    ** _any_ final executable build ought to be packaged with no runtime deps (unless linked to C libs)
	      -- thankfully there is a post rpm job that will append runtime requires based on ldd linkage
	*/
}
<|endoftext|>