<commit_before>package main

/*
 * Written: Dave Bevan
 * Date   : 23 Oct '17
 *
 * Purpose: To monitor a local folder, watching for file events using iNotify.
 * Specifically, trigger when CLOSE events have been received.
 *
 * Configured via 3 environment variables:
 *
 *   WATCHFOLDER=/path/to/be/monitored - can ONLY be a local folder, not network shares (as inotify events are absent from anything other than local paths)
 *
 *   %%PATH%% will be replaced with the full pathname to the file concerned:
 *
 *   E.g. WORKFLOWURL=http://something.url/some/endpoint.php?path=%%PATH%%
 *        WORKFLOWURL=http://something.url/rest/endpoint/action/%%PATH%%
 *
 *   FILESUFFIX=.xml - only call WORKFLOWURL for CLOSE events on files ending in $FILESUFFIX
 *
 */
import (
	"github.com/betim/fsnotify"
	"github.com/yookoala/realpath"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

func main() {
	log.SetFlags(log.LstdFlags | log.Lmicroseconds)

	watchfolder, ok := os.LookupEnv("WATCHFOLDER")
	if !ok {
		log.Fatal("Env WATCHFOLDER unset!")
	}

	watchfolder, err := realpath.Realpath(watchfolder)
	if err != nil {
		log.Fatal(error(err))
	}

	workflowurl, ok := os.LookupEnv("WORKFLOWURL")
	if !ok {
		log.Fatal("Env WORKFLOWURL unset!\n",
			"  E.g. WORKFLOWURL=http://something.url/some/endpoint.php?path=%%PATH%%\n",
			"       WORKFLOWURL=http://something.url/rest/endpoint/action/%%PATH%%")
	}

	filesuffix, ok := os.LookupEnv("FILESUFFIX")
	if !ok {
		log.Fatal("Env FILESUFFIX unset!")
	}

	startWatching(watchfolder, workflowurl, filesuffix)
}

func startWatching(watchfolder, workflowurl string, filesuffix string) {

	log.Println("WATCHFOLDER=" + watchfolder)
	log.Println("WORKFLOWURL=" + workflowurl)
	log.Println("FILESUFFIX=" + filesuffix)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	defer watcher.Close()

	done := make(chan bool)

	go func() {
		for {
			select {
			case event := <-watcher.Events:
				procEvent(event, workflowurl, filesuffix)
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add(watchfolder)
	if err != nil {
		log.Fatal(err)
	}

	<-done
}

func procEvent(event fsnotify.Event, workflowurl string, filesuffix string) {

	if event.Op&fsnotify.Close == fsnotify.Close {

		log.Println("CLOSE:", event.Name)

		if strings.HasSuffix(event.Name, filesuffix) {

			p := strings.LastIndex(event.Name, filesuffix)

			wfurl := strings.Replace(workflowurl, "%%PATH%%", url.PathEscape(event.Name[:p]), -1)

			if strings.Contains(wfurl, "?") {
				wfurl += "&FILESUFFIX=" + filesuffix
			} else {
				wfurl += "?FILESUFFIX=" + filesuffix
			}
			log.Println("WORKFLOW:", wfurl)

			var client = &http.Client{
				Timeout: time.Second * 5,
			}

			retval, err := client.Get(wfurl)
			if err != nil {

				log.Println("Error:", err)

			} else {

				defer retval.Body.Close()
				body, err := ioutil.ReadAll(retval.Body)
				if err != nil {
					log.Println("Error:", err)
				}

				log.Println("RESPONSE:", string(body))
			}
		}
	}
}
<commit_msg>1st attempt to move to a std cmd pkg layout<commit_after><|endoftext|>


<commit_before>package pinboardchecker

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

func debug(format string, args ...interface{}) {
	if debugEnabled {
		log.Printf(format+"\n", args...)
	}
}

var debugEnabled bool

func readUrlsFromFile(source string) []string {
	urls := make([]string, 0)

	if file, err := os.Open(source); err == nil {
		defer file.Close()

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			url := strings.TrimSpace(scanner.Text())
			urls = append(urls, url)
		}

		if err = scanner.Err(); err != nil {
			log.Fatal(err)
		}
	} else {
		log.Fatalf("ERROR: %s", err)
	}
	return urls
}

func deleteAll(token string, reader io.Reader) {
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		url := strings.TrimSpace(scanner.Text())
		deleteBookmark(token, Bookmark{url, ""})
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
}

func handleDownloadAction(token string) {
	bookmarks, err := downloadBookmarks(token)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s", string(bookmarks))
}

func handleDeleteAction(token string, resultsFileName string) {
	if resultsFileName == "-" {
		debug("Using stdin")
		deleteAll(token, os.Stdin)
	} else {
		debug("Using bookmarks from %s\n", resultsFileName)
		file, err := os.Open(resultsFileName)
		if err != nil {
			log.Fatal("Could not read file with bookmarks to delete")
		} else {
			deleteAll(token, file)
		}
	}
}

func handleCheckAction(token string, inputFile string, outputFile string) {
	var bookmarkJson []byte
	if len(inputFile) > 0 {
		bookmarkJson, _ = ioutil.ReadFile(inputFile)
	} else {
		bookmarkJson, _ = downloadBookmarks(token)
	}

	// different failure reporter depending on setting of outputFile, default to
	// stderr simple error printing for now
	var reporter FailureReporter
	switch {
	default:
		reporter = stdoutFailureReporter
	}

	checkAll(bookmarkJson, reporter)
}

func main() {
	var downloadAction bool
	flag.BoolVar(&downloadAction, "download", false, "Download all bookmarks, write them to stdout")

	var deleteAction bool
	flag.BoolVar(&deleteAction, "delete", false, "Use this to delete bookmarks. Requires passing a list of links to delete.")

	var token string
	flag.StringVar(&token, "token", "", "Mandatory authentication token")

	flag.BoolVar(&debugEnabled, "debug", false, "Enable debug logs, will be printed on stderr")

	var outputFile string
	flag.StringVar(&outputFile, "outputFile", "-", "File to store results of check operation in, defaults to stdout")

	var inputFile string
	flag.StringVar(&inputFile, "inputFile", "", "File containing bookmarks to check. If empty it will download all bookmarks from pinboard.")

	var inputFormat string
	flag.StringVar(&inputFormat, "inputFormat", "text", "Which format the input file is in (can be 'text', 'json')")

	var checkAction bool
	flag.BoolVar(&checkAction, "check", false, "Check the links of all bookmarks")

	flag.Parse()

	// at least one action flag needs to be set, print usage if no flags are present
	if flag.NFlag() == 0 {
		flag.Usage()
		return
	}

	if len(token) == 0 {
		log.Fatal("-token parameter has to be set")
	}

	if downloadAction {
		handleDownloadAction(token)
	}

	if deleteAction {
		handleDeleteAction(token, outputFile)
	}

	if checkAction {
		handleCheckAction(token, inputFile, outputFile)
	}
}
<commit_msg>Instantiate struct using tags for fields<commit_after>package pinboardchecker

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

func debug(format string, args ...interface{}) {
	if debugEnabled {
		log.Printf(format+"\n", args...)
	}
}

var debugEnabled bool

func readUrlsFromFile(source string) []string {
	urls := make([]string, 0)

	if file, err := os.Open(source); err == nil {
		defer file.Close()

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			url := strings.TrimSpace(scanner.Text())
			urls = append(urls, url)
		}

		if err = scanner.Err(); err != nil {
			log.Fatal(err)
		}
	} else {
		log.Fatalf("ERROR: %s", err)
	}
	return urls
}

func deleteAll(token string, reader io.Reader) {
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		url := strings.TrimSpace(scanner.Text())
		deleteBookmark(token, Bookmark{Href: url, Description: ""})
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
}

func handleDownloadAction(token string) {
	bookmarks, err := downloadBookmarks(token)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s", string(bookmarks))
}

func handleDeleteAction(token string, resultsFileName string) {
	if resultsFileName == "-" {
		debug("Using stdin")
		deleteAll(token, os.Stdin)
	} else {
		debug("Using bookmarks from %s\n", resultsFileName)
		file, err := os.Open(resultsFileName)
		if err != nil {
			log.Fatal("Could not read file with bookmarks to delete")
		} else {
			deleteAll(token, file)
		}
	}
}

func handleCheckAction(token string, inputFile string, outputFile string) {
	var bookmarkJson []byte
	if len(inputFile) > 0 {
		bookmarkJson, _ = ioutil.ReadFile(inputFile)
	} else {
		bookmarkJson, _ = downloadBookmarks(token)
	}

	// different failure reporter depending on setting of outputFile, default to
	// stderr simple error printing for now
	var reporter FailureReporter
	switch {
	default:
		reporter = stdoutFailureReporter
	}

	checkAll(bookmarkJson, reporter)
}

func main() {
	var downloadAction bool
	flag.BoolVar(&downloadAction, "download", false, "Download all bookmarks, write them to stdout")

	var deleteAction bool
	flag.BoolVar(&deleteAction, "delete", false, "Use this to delete bookmarks. Requires passing a list of links to delete.")

	var token string
	flag.StringVar(&token, "token", "", "Mandatory authentication token")

	flag.BoolVar(&debugEnabled, "debug", false, "Enable debug logs, will be printed on stderr")

	var outputFile string
	flag.StringVar(&outputFile, "outputFile", "-", "File to store results of check operation in, defaults to stdout")

	var inputFile string
	flag.StringVar(&inputFile, "inputFile", "", "File containing bookmarks to check. If empty it will download all bookmarks from pinboard.")

	var inputFormat string
	flag.StringVar(&inputFormat, "inputFormat", "text", "Which format the input file is in (can be 'text', 'json')")

	var checkAction bool
	flag.BoolVar(&checkAction, "check", false, "Check the links of all bookmarks")

	flag.Parse()

	// at least one action flag needs to be set, print usage if no flags are present
	if flag.NFlag() == 0 {
		flag.Usage()
		return
	}

	if len(token) == 0 {
		log.Fatal("-token parameter has to be set")
	}

	if downloadAction {
		handleDownloadAction(token)
	}

	if deleteAction {
		handleDeleteAction(token, outputFile)
	}

	if checkAction {
		handleCheckAction(token, inputFile, outputFile)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"unicode"
)

var debugFile string
var logFile string
var cmdsFile string

// Header defines the struct of the header in the i3bar protocol.
type Header struct {
	Version     int  `json:"version"`
	StopSignal  int  `json:"stop_signal,omitempty"`
	ContSignal  int  `json:"cont_signal,omitempty"`
	ClickEvents bool `json:"click_events,omitempty"`
}

// Block defines the struct of blocks in the i3bar protocol.
type Block struct {
	FullText            string `json:"full_text"`
	ShortText           string `json:"short_text,omitempty"`
	Color               string `json:"color,omitempty"`
	MinWidth            int    `json:"min_width,omitempty"`
	Align               string `json:"align,omitempty"`
	Name                string `json:"name,omitempty"`
	Instance            string `json:"instance,omitempty"`
	Urgent              bool   `json:"urgent,omitempty"`
	Separator           bool   `json:"separator,omitempty"`
	SeparatorBlockWidth int    `json:"separator_block_width,omitempty"`
}

// String implements Stringer interface.
func (b Block) String() string {
	return b.FullText
}

// A CmdIO defines a cmd that will feed the i3bar.
type CmdIO struct {
	// Cmd is the command being run
	Cmd *exec.Cmd
	// reader is the underlying stream where Cmd outputs data.
	reader io.ReadCloser
}

// BlockAggregate relates a CmdIO to the Blocks it produced during one update.
type BlockAggregate struct {
	CmdIO  *CmdIO
	Blocks []*Block
}

// NewCmdIO creates a new CmdIO from command c.
// c must be properly quoted for a shell as it's passed to sh -c.
func NewCmdIO(c string) (*CmdIO, error) {
	cmd := exec.Command("sh", "-c", c)
	reader, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	cmdio := CmdIO{
		Cmd:    cmd,
		reader: reader,
	}
	return &cmdio, nil
}

// Start runs the command of CmdIO and feeds the BlockAggregatesCh channel
// with the Blocks it produces.
func (c *CmdIO) Start(blockAggregatesCh chan<- *BlockAggregate) error {
	if err := c.Cmd.Start(); err != nil {
		return err
	}
	go func() {
		// We'll handle a few cases here.
		// If JSON is output from i3status, then we need
		// to ignore the i3bar header and opening [,
		// then ignore leading comma on each line.
		// If JSON is output from a script, it assumes the
		// author will not have the header and [, but maybe the comma
		r := bufio.NewReader(c.reader)
		// try Read a header first
		ruune, _, err := r.ReadRune()
		if err != nil {
			log.Println(err)
			return
		}
		if ruune == '{' {
			// Consume the header line
			if _, err := r.ReadString('\n'); err != nil {
				log.Println(err)
				return
			}
			// Consume the next line (opening bracket)
			if _, err := r.ReadString('\n'); err != nil {
				log.Println(err)
				return
			}
		} else {
			r.UnreadRune()
		}
		dec := json.NewDecoder(r)
		for {
			var b []*Block
			// Ignore unwanted chars first
		IgnoreChars:
			for {
				ruune, _, err := r.ReadRune()
				if err != nil {
					log.Println(err)
					continue
				}
				switch {
				case unicode.IsSpace(ruune):
					// Loop again
				case ruune == ',':
					break IgnoreChars
				default:
					r.UnreadRune()
					break IgnoreChars
				}
			}
			if err := dec.Decode(&b); err != nil {
				log.Printf("Invalid JSON input: all decoding methods failed (%v)\n", err)
			}
			blockAggregatesCh <- &BlockAggregate{c, b}
		}
		c.reader.Close()
	}()
	return nil
}

// BlockAggregator fans-in all Blocks produced by a list of CmdIO and sends it to the writer W.
type BlockAggregator struct {
	// Blocks keeps track of which CmdIO produced which Block list.
	Blocks map[*CmdIO][]*Block
	// CmdIOs keeps an ordered list of the CmdIOs being aggregated.
	CmdIOs []*CmdIO
	// W is where multiplexed input blocks are written to.
	W io.Writer
}

// NewBlockAggregator returns a BlockAggregator which will write to w.
func NewBlockAggregator(w io.Writer) *BlockAggregator {
	return &BlockAggregator{
		Blocks: make(map[*CmdIO][]*Block),
		CmdIOs: make([]*CmdIO, 0),
		W:      w,
	}
}

// Aggregate starts aggregating data coming from the BlockAggregates channel.
func (ba *BlockAggregator) Aggregate(blockAggregates <-chan *BlockAggregate) {
	jw := json.NewEncoder(ba.W)
	for blockAggregate := range blockAggregates {
		ba.Blocks[blockAggregate.CmdIO] = blockAggregate.Blocks
		blocksUpdate := make([]*Block, 0)
		for _, cmdio := range ba.CmdIOs {
			blocksUpdate = append(blocksUpdate, ba.Blocks[cmdio]...)
		}
		if err := jw.Encode(blocksUpdate); err != nil {
			log.Println(err)
		}
		ba.W.Write([]byte(","))
	}
}

func init() {
	flag.StringVar(&debugFile, "debug-file", "", "Outputs JSON to this file as well -- for debugging")
	flag.StringVar(&logFile, "log-file", "", "Log i3cat events in this file")
	flag.StringVar(&cmdsFile, "cmd-file", "$HOME/.i3/i3cat.conf", "File listing of the commands to run")
	flag.Parse()
}

func main() {
	// Read and parse commands to run.
	var cmdsReader io.ReadCloser
	if cmdsFile == "-" {
		cmdsReader = ioutil.NopCloser(os.Stdin)
	} else {
		f, err := os.Open(os.ExpandEnv(cmdsFile))
		if err != nil {
			log.Fatal(err)
		}
		cmdsReader = f
	}
	commands := make([]string, 0)
	scanner := bufio.NewScanner(cmdsReader)
	for scanner.Scan() {
		cmd := strings.TrimSpace(scanner.Text())
		if cmd != "" && !strings.HasPrefix(cmd, "#") {
			commands = append(commands, cmd)
		}
	}
	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	cmdsReader.Close()

	// Init log output.
	if logFile != "" {
		f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	// Init where i3cat will print its output.
	var out io.Writer
	if debugFile != "" {
		f, err := os.OpenFile(debugFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		out = io.MultiWriter(os.Stdout, f)
	} else {
		out = os.Stdout
	}

	// We print the header of i3bar
	header := Header{1, 10, 12, true}
	hb, err := json.Marshal(header)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Fprintf(out, "%s\n[\n", hb)

	// Create the block aggregator and start the commands
	blocksCh := make(chan *BlockAggregate)
	ba := NewBlockAggregator(out)
	for _, c := range commands {
		cmdio, err := NewCmdIO(c)
		if err != nil {
			log.Fatal(err)
		}
		ba.CmdIOs = append(ba.CmdIOs, cmdio)
		if err := cmdio.Start(blocksCh); err != nil {
			log.Fatal(err)
		}
	}

	go ba.Aggregate(blocksCh)

	// Listen for worthy signals
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	for {
		// TODO handle sigcont and sigstop received from i3bar, and forward to cmds
		s := <-c
		switch s {
		case os.Interrupt:
			// Kill all processes on interrupt
			log.Println("SIGINT received: terminating all processes...")
			for _, cmdio := range ba.CmdIOs {
				if err := cmdio.Cmd.Process.Signal(syscall.SIGTERM); err != nil {
					log.Println(err)
					if err := cmdio.Cmd.Process.Kill(); err != nil {
						log.Println(err)
					}
				}
			}
			os.Exit(0)
		}
	}
}
<commit_msg>Add flags to configure the i3bar header<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"unicode"
)

var debugFile string
var logFile string
var cmdsFile string
var header Header

// Header defines the struct of the header in the i3bar protocol.
type Header struct {
	Version     int  `json:"version"`
	StopSignal  int  `json:"stop_signal,omitempty"`
	ContSignal  int  `json:"cont_signal,omitempty"`
	ClickEvents bool `json:"click_events,omitempty"`
}

// Block defines the struct of blocks in the i3bar protocol.
type Block struct {
	FullText            string `json:"full_text"`
	ShortText           string `json:"short_text,omitempty"`
	Color               string `json:"color,omitempty"`
	MinWidth            int    `json:"min_width,omitempty"`
	Align               string `json:"align,omitempty"`
	Name                string `json:"name,omitempty"`
	Instance            string `json:"instance,omitempty"`
	Urgent              bool   `json:"urgent,omitempty"`
	Separator           bool   `json:"separator,omitempty"`
	SeparatorBlockWidth int    `json:"separator_block_width,omitempty"`
}

// String implements Stringer interface.
func (b Block) String() string {
	return b.FullText
}

// A CmdIO defines a cmd that will feed the i3bar.
type CmdIO struct {
	// Cmd is the command being run
	Cmd *exec.Cmd
	// reader is the underlying stream where Cmd outputs data.
	reader io.ReadCloser
}

// BlockAggregate relates a CmdIO to the Blocks it produced during one update.
type BlockAggregate struct {
	CmdIO  *CmdIO
	Blocks []*Block
}

// NewCmdIO creates a new CmdIO from command c.
// c must be properly quoted for a shell as it's passed to sh -c.
func NewCmdIO(c string) (*CmdIO, error) {
	cmd := exec.Command("sh", "-c", c)
	reader, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	cmdio := CmdIO{
		Cmd:    cmd,
		reader: reader,
	}
	return &cmdio, nil
}

// Start runs the command of CmdIO and feeds the BlockAggregatesCh channel
// with the Blocks it produces.
func (c *CmdIO) Start(blockAggregatesCh chan<- *BlockAggregate) error {
	if err := c.Cmd.Start(); err != nil {
		return err
	}
	go func() {
		// We'll handle a few cases here.
		// If JSON is output from i3status, then we need
		// to ignore the i3bar header and opening [,
		// then ignore leading comma on each line.
		// If JSON is output from a script, it assumes the
		// author will not have the header and [, but maybe the comma
		r := bufio.NewReader(c.reader)
		// try Read a header first
		ruune, _, err := r.ReadRune()
		if err != nil {
			log.Println(err)
			return
		}
		if ruune == '{' {
			// Consume the header line
			if _, err := r.ReadString('\n'); err != nil {
				log.Println(err)
				return
			}
			// Consume the next line (opening bracket)
			if _, err := r.ReadString('\n'); err != nil {
				log.Println(err)
				return
			}
		} else {
			r.UnreadRune()
		}
		dec := json.NewDecoder(r)
		for {
			var b []*Block
			// Ignore unwanted chars first
		IgnoreChars:
			for {
				ruune, _, err := r.ReadRune()
				if err != nil {
					log.Println(err)
					continue
				}
				switch {
				case unicode.IsSpace(ruune):
					// Loop again
				case ruune == ',':
					break IgnoreChars
				default:
					r.UnreadRune()
					break IgnoreChars
				}
			}
			if err := dec.Decode(&b); err != nil {
				log.Printf("Invalid JSON input: all decoding methods failed (%v)\n", err)
			}
			blockAggregatesCh <- &BlockAggregate{c, b}
		}
		c.reader.Close()
	}()
	return nil
}

// BlockAggregator fans-in all Blocks produced by a list of CmdIO and sends it to the writer W.
type BlockAggregator struct {
	// Blocks keeps track of which CmdIO produced which Block list.
	Blocks map[*CmdIO][]*Block
	// CmdIOs keeps an ordered list of the CmdIOs being aggregated.
	CmdIOs []*CmdIO
	// W is where multiplexed input blocks are written to.
	W io.Writer
}

// NewBlockAggregator returns a BlockAggregator which will write to w.
func NewBlockAggregator(w io.Writer) *BlockAggregator {
	return &BlockAggregator{
		Blocks: make(map[*CmdIO][]*Block),
		CmdIOs: make([]*CmdIO, 0),
		W:      w,
	}
}

// Aggregate starts aggregating data coming from the BlockAggregates channel.
func (ba *BlockAggregator) Aggregate(blockAggregates <-chan *BlockAggregate) {
	jw := json.NewEncoder(ba.W)
	for blockAggregate := range blockAggregates {
		ba.Blocks[blockAggregate.CmdIO] = blockAggregate.Blocks
		blocksUpdate := make([]*Block, 0)
		for _, cmdio := range ba.CmdIOs {
			blocksUpdate = append(blocksUpdate, ba.Blocks[cmdio]...)
		}
		if err := jw.Encode(blocksUpdate); err != nil {
			log.Println(err)
		}
		ba.W.Write([]byte(","))
	}
}

func init() {
	flag.StringVar(&debugFile, "debug-file", "", "Outputs JSON to this file as well; for debugging what is sent to i3bar.")
	flag.StringVar(&logFile, "log-file", "", "Logs i3cat events in this file. Defaults to STDERR")
	flag.StringVar(&cmdsFile, "cmd-file", "$HOME/.i3/i3cat.conf", "File listing of the commands to run. It will read from STDIN if - is provided")
	flag.IntVar(&header.Version, "header-version", 1, "The i3bar header version")
	flag.IntVar(&header.StopSignal, "header-stopsignal", 0, "The i3bar header stop_signal")
	flag.IntVar(&header.ContSignal, "header-contsignal", 0, "The i3bar header cont_signal")
	flag.BoolVar(&header.ClickEvents, "header-clickevents", false, "The i3bar header click_events")
	flag.Parse()
}

func main() {
	// Read and parse commands to run.
	var cmdsReader io.ReadCloser
	if cmdsFile == "-" {
		cmdsReader = ioutil.NopCloser(os.Stdin)
	} else {
		f, err := os.Open(os.ExpandEnv(cmdsFile))
		if err != nil {
			log.Fatal(err)
		}
		cmdsReader = f
	}
	commands := make([]string, 0)
	scanner := bufio.NewScanner(cmdsReader)
	for scanner.Scan() {
		cmd := strings.TrimSpace(scanner.Text())
		if cmd != "" && !strings.HasPrefix(cmd, "#") {
			commands = append(commands, cmd)
		}
	}
	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	cmdsReader.Close()

	// Init log output.
	if logFile != "" {
		f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	// Init where i3cat will print its output.
	var out io.Writer
	if debugFile != "" {
		f, err := os.OpenFile(debugFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		out = io.MultiWriter(os.Stdout, f)
	} else {
		out = os.Stdout
	}

	// We print the header of i3bar
	hb, err := json.Marshal(header)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Fprintf(out, "%s\n[\n", hb)

	// Create the block aggregator and start the commands
	blocksCh := make(chan *BlockAggregate)
	ba := NewBlockAggregator(out)
	for _, c := range commands {
		cmdio, err := NewCmdIO(c)
		if err != nil {
			log.Fatal(err)
		}
		ba.CmdIOs = append(ba.CmdIOs, cmdio)
		if err := cmdio.Start(blocksCh); err != nil {
			log.Fatal(err)
		}
	}

	go ba.Aggregate(blocksCh)

	// Listen for worthy signals
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	for {
		// TODO handle sigcont and sigstop received from i3bar, and forward to cmds
		s := <-c
		switch s {
		case os.Interrupt:
			// Kill all processes on interrupt
			log.Println("SIGINT received: terminating all processes...")
			for _, cmdio := range ba.CmdIOs {
				if err := cmdio.Cmd.Process.Signal(syscall.SIGTERM); err != nil {
					log.Println(err)
					if err := cmdio.Cmd.Process.Kill(); err != nil {
						log.Println(err)
					}
				}
			}
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"anonymous-messaging/client"
	"anonymous-messaging/config"
	"anonymous-messaging/logging"
	"anonymous-messaging/pki"
	"anonymous-messaging/server"
	"anonymous-messaging/sphinx"

	"flag"
	"fmt"

	"github.com/protobuf/proto"
	"time"
)

var logLocal = logging.PackageLogger()

const (
	PKI_DIR = "pki/database.db"
)

func pkiPreSetting(pkiDir string) error {
	db, err := pki.OpenDatabase(pkiDir, "sqlite3")
	if err != nil {
		return err
	}
	defer db.Close()

	params := make(map[string]string)
	params["Id"] = "TEXT"
	params["Typ"] = "TEXT"
	params["Config"] = "BLOB"

	err = pki.CreateTable(db, "Pki", params)
	if err != nil {
		return err
	}

	return nil
}

func FakeAdding(c *client.Client) {
	logLocal.Info("Adding simulated traffic of a client")
	for {
		sphinxPacket, err := c.CreateSphinxPacket("hello world", c.Config)
		if err != nil {
		}
		packet, err := config.WrapWithFlag("\xc6", sphinxPacket)
		if err != nil {
			logLocal.Info("Something went wrong")
		}
		c.OutQueue <- packet
		time.Sleep(10 * time.Second)
	}
}

// ReadInClientsPKI reads in the public information about users
// from the PKI database and stores them locally. In case
// the connection or fetching data from the PKI went wrong,
// an error is returned.
func ReadInClientsPKI(pkiName string) error {
	logLocal.Info(fmt.Sprintf(" Reading network users information from the PKI: %s", pkiName))
	var users []config.ClientConfig

	db, err := pki.OpenDatabase(pkiName, "sqlite3")

	if err != nil {
		return err
	}

	records, err := pki.QueryDatabase(db, "Pki", "Client")

	if err != nil {
		logLocal.WithError(err).Error("Error during Querying the Clients PKI")
		return err
	}

	for records.Next() {
		result := make(map[string]interface{})
		err := records.MapScan(result)

		if err != nil {
			logLocal.WithError(err).Error("Error in scanning table PKI record")
			return err
		}

		var pubs config.ClientConfig
		err = proto.Unmarshal(result["Config"].([]byte), &pubs)
		if err != nil {
			logLocal.WithError(err).Error(" Error during unmarshal function for client config")
			return err
		}
		users = append(users, pubs)
	}
	logLocal.Info(" Information about other users uploaded")
	return nil
}

func main() {

	typ := flag.String("typ", "", "A type of entity we want to run")
	id := flag.String("id", "", "Id of the entity we want to run")
	host := flag.String("host", "", "The host on which the entity is running")
	port := flag.String("port", "", "The port on which the entity is running")
	providerId := flag.String("provider", "", "The port on which the entity is running")
	flag.Parse()

	err := pkiPreSetting(PKI_DIR)
	if err != nil {
		panic(err)
	}

	switch *typ {
	case "client":
		db, err := pki.OpenDatabase(PKI_DIR, "sqlite3")

		if err != nil {
			panic(err)
		}

		row := db.QueryRow("SELECT Config FROM Pki WHERE Id = ? AND Typ = ?", providerId, "Provider")

		var results []byte
		err = row.Scan(&results)
		if err != nil {
			fmt.Println(err)
		}
		var providerInfo config.MixConfig
		err = proto.Unmarshal(results, &providerInfo)

		pubC, privC, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		client, err := client.NewClient(*id, *host, *port, pubC, privC, PKI_DIR, providerInfo)
		if err != nil {
			panic(err)
		}

		err = client.Start()
		if err != nil {
			panic(err)
		}

	case "mix":
		pubM, privM, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		mixServer, err := server.NewMixServer(*id, *host, *port, pubM, privM, PKI_DIR)
		if err != nil {
			panic(err)
		}

		err = mixServer.Start()
		if err != nil {
			panic(err)
		}
	case "provider":
		pubP, privP, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		providerServer, err := server.NewProviderServer(*id, *host, *port, pubP, privP, PKI_DIR)
		if err != nil {
			panic(err)
		}

		err = providerServer.Start()
		if err != nil {
			panic(err)
		}
	}
}
<commit_msg>Disable tmp function for fake traffic generation<commit_after>package main

import (
	"anonymous-messaging/client"
	"anonymous-messaging/config"
	"anonymous-messaging/logging"
	"anonymous-messaging/pki"
	"anonymous-messaging/server"
	"anonymous-messaging/sphinx"

	"flag"
	"fmt"

	"github.com/protobuf/proto"
)

var logLocal = logging.PackageLogger()

const (
	PKI_DIR = "pki/database.db"
)

func pkiPreSetting(pkiDir string) error {
	db, err := pki.OpenDatabase(pkiDir, "sqlite3")
	if err != nil {
		return err
	}
	defer db.Close()

	params := make(map[string]string)
	params["Id"] = "TEXT"
	params["Typ"] = "TEXT"
	params["Config"] = "BLOB"

	err = pki.CreateTable(db, "Pki", params)
	if err != nil {
		return err
	}

	return nil
}

//func FakeAdding(c *client.Client) {
//	logLocal.Info("Adding simulated traffic of a client")
//	for {
//		sphinxPacket, err := c.EncodeMessage("hello world", c.Config)
//		if err != nil {
//		}
//		packet, err := config.WrapWithFlag("\xc6", sphinxPacket)
//		if err != nil {
//			logLocal.Info("Something went wrong")
//		}
//		c.OutQueue <- packet
//		time.Sleep(10 * time.Second)
//	}
//}

// ReadInClientsPKI reads in the public information about users
// from the PKI database and stores them locally. In case
// the connection or fetching data from the PKI went wrong,
// an error is returned.
func ReadInClientsPKI(pkiName string) error {
	logLocal.Info(fmt.Sprintf(" Reading network users information from the PKI: %s", pkiName))
	var users []config.ClientConfig

	db, err := pki.OpenDatabase(pkiName, "sqlite3")

	if err != nil {
		return err
	}

	records, err := pki.QueryDatabase(db, "Pki", "Client")

	if err != nil {
		logLocal.WithError(err).Error("Error during Querying the Clients PKI")
		return err
	}

	for records.Next() {
		result := make(map[string]interface{})
		err := records.MapScan(result)

		if err != nil {
			logLocal.WithError(err).Error("Error in scanning table PKI record")
			return err
		}

		var pubs config.ClientConfig
		err = proto.Unmarshal(result["Config"].([]byte), &pubs)
		if err != nil {
			logLocal.WithError(err).Error(" Error during unmarshal function for client config")
			return err
		}
		users = append(users, pubs)
	}
	logLocal.Info(" Information about other users uploaded")
	return nil
}

func main() {

	typ := flag.String("typ", "", "A type of entity we want to run")
	id := flag.String("id", "", "Id of the entity we want to run")
	host := flag.String("host", "", "The host on which the entity is running")
	port := flag.String("port", "", "The port on which the entity is running")
	providerId := flag.String("provider", "", "The port on which the entity is running")
	flag.Parse()

	err := pkiPreSetting(PKI_DIR)
	if err != nil {
		panic(err)
	}

	switch *typ {
	case "client":
		db, err := pki.OpenDatabase(PKI_DIR, "sqlite3")

		if err != nil {
			panic(err)
		}

		row := db.QueryRow("SELECT Config FROM Pki WHERE Id = ? AND Typ = ?", providerId, "Provider")

		var results []byte
		err = row.Scan(&results)
		if err != nil {
			fmt.Println(err)
		}
		var providerInfo config.MixConfig
		err = proto.Unmarshal(results, &providerInfo)

		pubC, privC, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		client, err := client.NewClient(*id, *host, *port, pubC, privC, PKI_DIR, providerInfo)
		if err != nil {
			panic(err)
		}

		err = client.Start()
		if err != nil {
			panic(err)
		}

	case "mix":
		pubM, privM, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		mixServer, err := server.NewMixServer(*id, *host, *port, pubM, privM, PKI_DIR)
		if err != nil {
			panic(err)
		}

		err = mixServer.Start()
		if err != nil {
			panic(err)
		}
	case "provider":
		pubP, privP, err := sphinx.GenerateKeyPair()
		if err != nil {
			panic(err)
		}

		providerServer, err := server.NewProviderServer(*id, *host, *port, pubP, privP, PKI_DIR)
		if err != nil {
			panic(err)
		}

		err = providerServer.Start()
		if err != nil {
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>package main

// Inspired by the noaa firehose sample script
// https://github.com/cloudfoundry/noaa/blob/master/firehose_sample/main.go

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"sync/atomic"

	"github.com/cloudcredo/graphite-nozzle/metrics"
	"github.com/cloudcredo/graphite-nozzle/processors"
	"github.com/cloudfoundry/noaa"
	"github.com/cloudfoundry/noaa/events"
	"github.com/krujos/uaaclientcredentials"
	"github.com/quipo/statsd"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	cfPush            = kingpin.Flag("cf-push", "Deploy to Cloud Foundry.").Default("true").Bool()
	domain            = kingpin.Flag("domain", "Domain of your CF installation.").Default("10.244.0.34.xip.io").OverrideDefaultFromEnvar("CF_DOMAIN").String()
	dopplerPort       = kingpin.Flag("doppler-port", "Custom port for doppler / loggregator endpoint").Default("443").Int()
	subscriptionId    = kingpin.Flag("subscription-id", "ID for the firehose subscription.").Default("watchman").OverrideDefaultFromEnvar("FIREHOSE_SUBSCRIPTION_ID").String()
	clientID          = kingpin.Flag("client-id", "CF UAA OAuth client ID with 'doppler.firehose' permissions.").Default("CLIENT_ID").OverrideDefaultFromEnvar("CLIENT_ID").String()
	clientSecret      = kingpin.Flag("client-secret", "CF UAA OAuth client secret of client with 'doppler.firehose' permissions.").Default("CLIENT_SECRET").OverrideDefaultFromEnvar("CLIENT_SECRET").String()
	skipSSLValidation = kingpin.Flag("skip-ssl-validation", "Please don't").Bool()
	statsdAddress     = kingpin.Flag("statsd-address", "IP and port to the statsd endpoint.").Default("STATSD_ADDRESS").OverrideDefaultFromEnvar("STATSD_ADDRESS").String()
	statsdPrefix      = kingpin.Flag("statsd-prefix", "The prefix to use for statsd metrics.").Default("cf").OverrideDefaultFromEnvar("STATSD_PREFIX").String()
)

var count = uint64(0)

func hello(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(w,
		"Hello!\nWe have processed", atomic.LoadUint64(&count), "events",
		"\nWe're pushing to StatsD at", statsdAddress, "with a prefix of",
		statsdPrefix,
		"\nWe have tapped the firehose at ", fmt.Sprintf("wss://doppler.%s:%d", *domain, *dopplerPort))
}

func setupHTTP() {
	http.HandleFunc("/", hello)

	go func() {
		err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
		if err != nil {
			log.Fatal("ListenAndServe:", err)
		}
	}()
}

func main() {
	kingpin.Version("0.0.1")
	kingpin.Parse()

	if *cfPush == true {
		setupHTTP()
	}

	uaaURL, err := url.Parse(fmt.Sprintf("https://uaa.%s", *domain))

	if nil != err {
		panic("Failed to parse uaa url!")
	}

	creds, err := uaaclientcredentials.New(uaaURL, true, *clientID, *clientSecret)

	if nil != err {
		panic("Failed to obtain creds!")
	}

	dopplerAddress := fmt.Sprintf("wss://doppler.%s:%d", *domain, *dopplerPort)
	consumer := noaa.NewConsumer(dopplerAddress, &tls.Config{InsecureSkipVerify: true}, nil)

	httpStartStopProcessor := processors.NewHttpStartStopProcessor()
	sender := statsd.NewStatsdClient(*statsdAddress, *statsdPrefix)
	sender.CreateSocket()

	var processedMetrics []metrics.Metric

	msgChan := make(chan *events.Envelope)
	go func() {
		defer close(msgChan)
		errorChan := make(chan error)
		token, err := creds.GetBearerToken()
		if nil != err {
			panic(err)
		}
		go consumer.Firehose(*subscriptionId, token, msgChan, errorChan, nil)

		for err := range errorChan {
			fmt.Fprintf(os.Stderr, "%v\n", err.Error())
		}
	}()

	for msg := range msgChan {
		eventType := msg.GetEventType()

		switch eventType {
		case events.Envelope_HttpStartStop:
			processedMetrics = httpStartStopProcessor.Process(msg)
		default:
			atomic.AddUint64(&count, 1)
			// do nothing
		}

		if len(processedMetrics) > 0 {
			for _, metric := range processedMetrics {
				metric.Send(sender)
			}
		}
		processedMetrics = nil
	}
}
<commit_msg>Left period off default prefix<commit_after>package main

// Inspired by the noaa firehose sample script
// https://github.com/cloudfoundry/noaa/blob/master/firehose_sample/main.go

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"sync/atomic"

	"github.com/cloudcredo/graphite-nozzle/metrics"
	"github.com/cloudcredo/graphite-nozzle/processors"
	"github.com/cloudfoundry/noaa"
	"github.com/cloudfoundry/noaa/events"
	"github.com/krujos/uaaclientcredentials"
	"github.com/quipo/statsd"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	cfPush            = kingpin.Flag("cf-push", "Deploy to Cloud Foundry.").Default("true").Bool()
	domain            = kingpin.Flag("domain", "Domain of your CF installation.").Default("10.244.0.34.xip.io").OverrideDefaultFromEnvar("CF_DOMAIN").String()
	dopplerPort       = kingpin.Flag("doppler-port", "Custom port for doppler / loggregator endpoint").Default("443").Int()
	subscriptionID    = kingpin.Flag("subscription-id", "ID for the firehose subscription.").Default("watchman").OverrideDefaultFromEnvar("FIREHOSE_SUBSCRIPTION_ID").String()
	clientID          = kingpin.Flag("client-id", "CF UAA OAuth client ID with 'doppler.firehose' permissions.").Default("CLIENT_ID").OverrideDefaultFromEnvar("CLIENT_ID").String()
	clientSecret      = kingpin.Flag("client-secret", "CF UAA OAuth client secret of client with 'doppler.firehose' permissions.").Default("CLIENT_SECRET").OverrideDefaultFromEnvar("CLIENT_SECRET").String()
	skipSSLValidation = kingpin.Flag("skip-ssl-validation", "Please don't").Bool()
	statsdAddress     = kingpin.Flag("statsd-address", "IP and port to the statsd endpoint.").Default("STATSD_ADDRESS").OverrideDefaultFromEnvar("STATSD_ADDRESS").String()
	statsdPrefix      = kingpin.Flag("statsd-prefix", "The prefix to use for statsd metrics.").Default("cf.").OverrideDefaultFromEnvar("STATSD_PREFIX").String()
)

var count = uint64(0)

func hello(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(w,
		"Hello!\nWe have processed", atomic.LoadUint64(&count), "events",
		"\nWe're pushing to StatsD at", statsdAddress, "with a prefix of",
		statsdPrefix,
		"\nWe have tapped the firehose at ", fmt.Sprintf("wss://doppler.%s:%d", *domain, *dopplerPort))
}

func setupHTTP() {
	http.HandleFunc("/", hello)

	go func() {
		err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
		if err != nil {
			log.Fatal("ListenAndServe:", err)
		}
	}()
}

func main() {
	kingpin.Version("0.0.1")
	kingpin.Parse()

	if *cfPush == true {
		setupHTTP()
	}

	uaaURL, err := url.Parse(fmt.Sprintf("https://uaa.%s", *domain))

	if nil != err {
		panic("Failed to parse uaa url!")
	}

	creds, err := uaaclientcredentials.New(uaaURL, true, *clientID, *clientSecret)

	if nil != err {
		panic("Failed to obtain creds!")
	}

	dopplerAddress := fmt.Sprintf("wss://doppler.%s:%d", *domain, *dopplerPort)
	consumer := noaa.NewConsumer(dopplerAddress, &tls.Config{InsecureSkipVerify: true}, nil)

	httpStartStopProcessor := processors.NewHttpStartStopProcessor()
	sender := statsd.NewStatsdClient(*statsdAddress, *statsdPrefix)
	sender.CreateSocket()

	var processedMetrics []metrics.Metric

	msgChan := make(chan *events.Envelope)
	go func() {
		defer close(msgChan)
		errorChan := make(chan error)
		token, err := creds.GetBearerToken()
		if nil != err {
			panic(err)
		}
		go consumer.Firehose(*subscriptionID, token, msgChan, errorChan, nil)

		for err := range errorChan {
			fmt.Fprintf(os.Stderr, "%v\n", err.Error())
		}
	}()

	for msg := range msgChan {
		eventType := msg.GetEventType()

		switch eventType {
		case events.Envelope_HttpStartStop:
			processedMetrics = httpStartStopProcessor.Process(msg)
		default:
			atomic.AddUint64(&count, 1)
			// do nothing
		}

		if len(processedMetrics) > 0 {
			for _, metric := range processedMetrics {
				metric.Send(sender)
			}
		}
		processedMetrics = nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/codeignition/recon"
	"github.com/nats-io/nats"

	"gopkg.in/mgo.v2"
)

const (
	metricsAPIPath = "/api/metrics"
	agentsAPIPath  = "/api/agents"
)

// TODO: Instead of using a global for each collection,
// abstract this into an interface, which makes it
// easier for testing.
var (
	// agents collection
	agentsC *mgo.Collection
)

// Command line flags
// prepend flag to variable names to not pollute the global namespace.
var (
	flagAddr    = flag.String("addr", ":8080", "serve HTTP on `address`")
	flagNatsURL = flag.String("nats", nats.DefaultURL, "nats URL")
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("marksman: ")

	flag.Parse()

	http.HandleFunc(metricsAPIPath, metricsHandler)
	http.HandleFunc(agentsAPIPath, agentsHandler)
	http.Handle("/", http.FileServer(http.Dir("./public")))

	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	agentsC = session.DB("recon-dev").C("agents")

	log.Println("Server started: http://localhost" + *flagAddr)
	log.Fatal(http.ListenAndServe(*flagAddr, nil))
}

func metricsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "TODO")
}

func agentsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	switch r.Method {
	case "GET":
		var R []recon.Agent
		err := agentsC.Find(nil).All(&R)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		enc := json.NewEncoder(w)
		if err := enc.Encode(R); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	case "POST":
		var a recon.Agent
		dec := json.NewDecoder(r.Body)
		if err := dec.Decode(&a); err != nil {
			http.Error(w, "unable to decode json", http.StatusBadRequest)
			return
		}
		if a.UID == "" {
			http.Error(w, "UID can't be empty", http.StatusBadRequest)
			return
		}
		err := agentsC.Insert(a)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusCreated)
		nurl := struct {
			NatsURL string `json:"nats_url"`
		}{
			NatsURL: *flagNatsURL,
		}
		enc := json.NewEncoder(w)
		if err := enc.Encode(nurl); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
}

// Agent represents a recon agent running on
// a machine.
type Agent struct {
	UID string
}
<commit_msg>fix naming nit<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/codeignition/recon"
	"github.com/nats-io/nats"

	"gopkg.in/mgo.v2"
)

const (
	metricsAPIPath = "/api/metrics"
	agentsAPIPath  = "/api/agents"
)

// TODO: Instead of using a global for each collection,
// abstract this into an interface, which makes it
// easier for testing.
var (
	// agents collection
	agentsC *mgo.Collection
)

// Command line flags
// prepend flag to variable names to not pollute the global namespace.
var (
	flagAddr    = flag.String("addr", ":8080", "serve HTTP on `address`")
	flagNatsURL = flag.String("nats", nats.DefaultURL, "nats URL")
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("marksman: ")

	flag.Parse()

	http.HandleFunc(metricsAPIPath, metricsHandler)
	http.HandleFunc(agentsAPIPath, agentsHandler)
	http.Handle("/", http.FileServer(http.Dir("./public")))

	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}
	defer session.Close()

	// Optional. Switch the session to a monotonic behavior.
	session.SetMode(mgo.Monotonic, true)
	agentsC = session.DB("recon-dev").C("agents")

	log.Println("Server started: http://localhost" + *flagAddr)
	log.Fatal(http.ListenAndServe(*flagAddr, nil))
}

func metricsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, "TODO")
}

func agentsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	switch r.Method {
	case "GET":
		var agents []recon.Agent
		err := agentsC.Find(nil).All(&agents)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		enc := json.NewEncoder(w)
		if err := enc.Encode(agents); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	case "POST":
		var a recon.Agent
		dec := json.NewDecoder(r.Body)
		if err := dec.Decode(&a); err != nil {
			http.Error(w, "unable to decode json", http.StatusBadRequest)
			return
		}
		if a.UID == "" {
			http.Error(w, "UID can't be empty", http.StatusBadRequest)
			return
		}
		err := agentsC.Insert(a)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusCreated)
		nurl := struct {
			NatsURL string `json:"nats_url"`
		}{
			NatsURL: *flagNatsURL,
		}
		enc := json.NewEncoder(w)
		if err := enc.Encode(nurl); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
}

// Agent represents a recon agent running on
// a machine.
type Agent struct {
	UID string
}
<|endoftext|>


<commit_before>// Copyright 2015 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Go-import-redirector is an HTTP server for a custom Go import domain.
// It responds to requests in a given import path root with a meta tag
// specifying the source repository for the ``go get'' command and an
// HTML redirect to the godoc.org documentation page for that package.
//
// Usage:
//
//	go-import-redirector [-addr address] [-tls] [-vcs sys] <import> <repo>
//
// Go-import-redirector listens on address (default ``:80'')
// and responds to requests for URLs in the given import path root
// with one meta tag specifying the given source repository for ``go get''
// and another meta tag causing a redirect to the corresponding
// godoc.org documentation page.
//
// For example, if invoked as:
//
//	go-import-redirector 9fans.net/go https://github.com/9fans/go
//
// then the response for 9fans.net/go/acme/editinacme will include these tags:
//
//	<meta name="go-import" content="9fans.net/go git github.com/9fans/go">
//	<meta http-equiv="refresh" content="0; url=https://godoc.org/9fans.net/go/acme/editinacme">
//
// If both <import> and <repo> end in /*, the corresponding path element
// is taken from the import path and substituted in repo on each request.
// For example, if invoked as:
//
//	go-import-redirector rsc.io/* https://github.com/rsc/*
//
// then the response for rsc.io/x86/x86asm will include these tags:
//
//	<meta name="go-import" content="rsc.io/x86 git github.com/rsc/x86">
//	<meta http-equiv="refresh" content="0; url=https://godoc.org/rsc.io/x86/x86asm">
//
// Note that the wildcard element (x86) has been included in the Git repo path.
//
// The -addr option specifies the HTTP address to serve (default ``:http'').
//
// The -tls option causes go-import-redirector to serve HTTPS on port 443,
// loading an X.509 certificate and key pair from files in the current directory
// named after the host in the import path with .crt and .key appended
// (for example, rsc.io.crt and rsc.io.key).
// Like for http.ListenAndServeTLS, the certificate file should contain the
// concatenation of the server's certificate and the signing certificate authority's certificate.
//
// The -vcs option specifies the version control system, git, hg, or svn (default ``git'').
//
// Deployment on Google Cloud Platform
//
// For the case of a redirector for an entire domain (such as rsc.io above),
// the Makefile in this directory contains recipes to deploy a trivial VM running
// just this program, using a static IP address that can be loaded into the
// DNS configuration for the target domain.
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
)

var (
	addr       = flag.String("addr", ":http", "serve http on `address`")
	serveTLS   = flag.Bool("tls", false, "serve https on :443")
	vcs        = flag.String("vcs", "git", "set version control `system`")
	importPath string
	repoPath   string
	wildcard   bool
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: go-import-redirector <import> <repo>\n")
	fmt.Fprintf(os.Stderr, "options:\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "examples:\n")
	fmt.Fprintf(os.Stderr, "\tgo-import-redirector rsc.io/* https://github.com/rsc/*\n")
	fmt.Fprintf(os.Stderr, "\tgo-import-redirector 9fans.net/go https://github.com/9fans/go\n")
	os.Exit(2)
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("go-import-redirector: ")
	flag.Parse()
	flag.Usage = usage
	if flag.NArg() != 2 {
		flag.Usage()
	}
	importPath = flag.Arg(0)
	repoPath = flag.Arg(1)
	if !strings.Contains(repoPath, "://") {
		log.Fatal("repo path must be full URL")
	}
	if strings.HasSuffix(importPath, "/*") != strings.HasSuffix(repoPath, "/*") {
		log.Fatal("either both import and repo must have /* or neither")
	}
	if strings.HasSuffix(importPath, "/*") {
		wildcard = true
		importPath = strings.TrimSuffix(importPath, "/*")
		repoPath = strings.TrimSuffix(repoPath, "/*")
	}
	http.HandleFunc(strings.TrimSuffix(importPath, "/")+"/", redirect)
	if *serveTLS {
		host := importPath
		if i := strings.Index(host, "/"); i >= 0 {
			host = host[:i]
		}
		go func() {
			log.Fatal(http.ListenAndServeTLS(":https", host+".crt", host+".key", nil))
		}()
	}
	log.Fatal(http.ListenAndServe(*addr, nil))
}

var tmpl = template.Must(template.New("main").Parse(`<!DOCTYPE html>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="{{.ImportRoot}} {{.VCS}} {{.VCSRoot}}">
<meta http-equiv="refresh" content="0; url=https://godoc.org/{{.ImportRoot}}{{.Suffix}}">

Nothing to see here; move along.

`))

type data struct {
	ImportRoot string
	VCS        string
	VCSRoot    string
	Suffix     string
}

func redirect(w http.ResponseWriter, req *http.Request) {
	path := strings.TrimSuffix(req.Host+req.URL.Path, "/")
	var importRoot, repoRoot, suffix string
	if wildcard {
		if path == importPath {
			http.Redirect(w, req, "https://godoc.org/"+importPath, 302)
			return
		}
		if !strings.HasPrefix(path, importPath+"/") {
			http.NotFound(w, req)
			return
		}
		elem := path[len(importPath)+1:]
		if i := strings.Index(elem, "/"); i >= 0 {
			elem, suffix = elem[:i], elem[i:]
		}
		importRoot = importPath + "/" + elem
		repoRoot = repoPath + "/" + elem
	} else {
		if path != importPath && !strings.HasPrefix(path, importPath+"/") {
			http.NotFound(w, req)
			return
		}
		importRoot = importPath
		repoRoot = repoPath
		suffix = path[len(importPath):]
	}
	d := &data{
		ImportRoot: importRoot,
		VCS:        *vcs,
		VCSRoot:    repoRoot,
		Suffix:     suffix,
	}
	var buf bytes.Buffer
	err := tmpl.Execute(&buf, d)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	w.Write(buf.Bytes())
}
<commit_msg>go-import-redirector: fix bug in example output<commit_after>// Copyright 2015 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Go-import-redirector is an HTTP server for a custom Go import domain.
// It responds to requests in a given import path root with a meta tag
// specifying the source repository for the ``go get'' command and an
// HTML redirect to the godoc.org documentation page for that package.
//
// Usage:
//
//	go-import-redirector [-addr address] [-tls] [-vcs sys] <import> <repo>
//
// Go-import-redirector listens on address (default ``:80'')
// and responds to requests for URLs in the given import path root
// with one meta tag specifying the given source repository for ``go get''
// and another meta tag causing a redirect to the corresponding
// godoc.org documentation page.
//
// For example, if invoked as:
//
//	go-import-redirector 9fans.net/go https://github.com/9fans/go
//
// then the response for 9fans.net/go/acme/editinacme will include these tags:
//
//	<meta name="go-import" content="9fans.net/go git https://github.com/9fans/go">
//	<meta http-equiv="refresh" content="0; url=https://godoc.org/9fans.net/go/acme/editinacme">
//
// If both <import> and <repo> end in /*, the corresponding path element
// is taken from the import path and substituted in repo on each request.
// For example, if invoked as:
//
//	go-import-redirector rsc.io/* https://github.com/rsc/*
//
// then the response for rsc.io/x86/x86asm will include these tags:
//
//	<meta name="go-import" content="rsc.io/x86 git https://github.com/rsc/x86">
//	<meta http-equiv="refresh" content="0; url=https://godoc.org/rsc.io/x86/x86asm">
//
// Note that the wildcard element (x86) has been included in the Git repo path.
//
// The -addr option specifies the HTTP address to serve (default ``:http'').
//
// The -tls option causes go-import-redirector to serve HTTPS on port 443,
// loading an X.509 certificate and key pair from files in the current directory
// named after the host in the import path with .crt and .key appended
// (for example, rsc.io.crt and rsc.io.key).
// Like for http.ListenAndServeTLS, the certificate file should contain the
// concatenation of the server's certificate and the signing certificate authority's certificate.
//
// The -vcs option specifies the version control system, git, hg, or svn (default ``git'').
//
// Deployment on Google Cloud Platform
//
// For the case of a redirector for an entire domain (such as rsc.io above),
// the Makefile in this directory contains recipes to deploy a trivial VM running
// just this program, using a static IP address that can be loaded into the
// DNS configuration for the target domain.
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
)

var (
	addr       = flag.String("addr", ":http", "serve http on `address`")
	serveTLS   = flag.Bool("tls", false, "serve https on :443")
	vcs        = flag.String("vcs", "git", "set version control `system`")
	importPath string
	repoPath   string
	wildcard   bool
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: go-import-redirector <import> <repo>\n")
	fmt.Fprintf(os.Stderr, "options:\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "examples:\n")
	fmt.Fprintf(os.Stderr, "\tgo-import-redirector rsc.io/* https://github.com/rsc/*\n")
	fmt.Fprintf(os.Stderr, "\tgo-import-redirector 9fans.net/go https://github.com/9fans/go\n")
	os.Exit(2)
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("go-import-redirector: ")
	flag.Parse()
	flag.Usage = usage
	if flag.NArg() != 2 {
		flag.Usage()
	}
	importPath = flag.Arg(0)
	repoPath = flag.Arg(1)
	if !strings.Contains(repoPath, "://") {
		log.Fatal("repo path must be full URL")
	}
	if strings.HasSuffix(importPath, "/*") != strings.HasSuffix(repoPath, "/*") {
		log.Fatal("either both import and repo must have /* or neither")
	}
	if strings.HasSuffix(importPath, "/*") {
		wildcard = true
		importPath = strings.TrimSuffix(importPath, "/*")
		repoPath = strings.TrimSuffix(repoPath, "/*")
	}
	http.HandleFunc(strings.TrimSuffix(importPath, "/")+"/", redirect)
	if *serveTLS {
		host := importPath
		if i := strings.Index(host, "/"); i >= 0 {
			host = host[:i]
		}
		go func() {
			log.Fatal(http.ListenAndServeTLS(":https", host+".crt", host+".key", nil))
		}()
	}
	log.Fatal(http.ListenAndServe(*addr, nil))
}

var tmpl = template.Must(template.New("main").Parse(`<!DOCTYPE html>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="{{.ImportRoot}} {{.VCS}} {{.VCSRoot}}">
<meta http-equiv="refresh" content="0; url=https://godoc.org/{{.ImportRoot}}{{.Suffix}}">

Nothing to see here; move along.

`))

type data struct {
	ImportRoot string
	VCS        string
	VCSRoot    string
	Suffix     string
}

func redirect(w http.ResponseWriter, req *http.Request) {
	path := strings.TrimSuffix(req.Host+req.URL.Path, "/")
	var importRoot, repoRoot, suffix string
	if wildcard {
		if path == importPath {
			http.Redirect(w, req, "https://godoc.org/"+importPath, 302)
			return
		}
		if !strings.HasPrefix(path, importPath+"/") {
			http.NotFound(w, req)
			return
		}
		elem := path[len(importPath)+1:]
		if i := strings.Index(elem, "/"); i >= 0 {
			elem, suffix = elem[:i], elem[i:]
		}
		importRoot = importPath + "/" + elem
		repoRoot = repoPath + "/" + elem
	} else {
		if path != importPath && !strings.HasPrefix(path, importPath+"/") {
			http.NotFound(w, req)
			return
		}
		importRoot = importPath
		repoRoot = repoPath
		suffix = path[len(importPath):]
	}
	d := &data{
		ImportRoot: importRoot,
		VCS:        *vcs,
		VCSRoot:    repoRoot,
		Suffix:     suffix,
	}
	var buf bytes.Buffer
	err := tmpl.Execute(&buf, d)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	w.Write(buf.Bytes())
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"net/http"
	"os"

	"github.com/codegangsta/negroni"
	"github.com/julienschmidt/httprouter"
	"github.com/mitchellh/goamz/aws"
	"github.com/thomaso-mirodin/go-shorten/handlers"
	"github.com/thomaso-mirodin/go-shorten/storage"
)

func main() {
	store, err := storage.NewInmem()
	if err != nil {
		log.Fatalf("Failed to create inmem storage because '%s'", err)

	}

	n := negroni.Classic(negroni.NewStatic(http.Dir("static")))

	r := httprouter.New()

	r.GET("/:short", handlers.GetShortHandler(store))
	r.HEAD("/:short", handlers.GetShortHandler(store))

	r.POST("/", handlers.SetShortHandler(store))
	r.PUT("/", handlers.SetShortHandler(store))
	r.POST("/:short", handlers.SetShortHandler(store))
	r.PUT("/:short", handlers.SetShortHandler(store))

	n.UseHandler(r)

	host := os.Getenv("HOST")
	if host == "" {
		host = "localhost"
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	err = http.ListenAndServe(net.JoinHostPort(host, port), n)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Fix Negroni Classic :S<commit_after>package main

import (
	"log"
	"net"
	"net/http"
	"os"

	"github.com/codegangsta/negroni"
	"github.com/julienschmidt/httprouter"
	"github.com/mitchellh/goamz/aws"
	"github.com/thomaso-mirodin/go-shorten/handlers"
	"github.com/thomaso-mirodin/go-shorten/storage"
)

func main() {
	store, err := storage.NewInmem()
	if err != nil {
		log.Fatalf("Failed to create inmem storage because '%s'", err)

	}

	n := negroni.New(negroni.NewRecovery(), negroni.NewLogger(), negroni.NewStatic(http.Dir("static")))

	r := httprouter.New()

	r.GET("/:short", handlers.GetShortHandler(store))
	r.HEAD("/:short", handlers.GetShortHandler(store))

	r.POST("/", handlers.SetShortHandler(store))
	r.PUT("/", handlers.SetShortHandler(store))
	r.POST("/:short", handlers.SetShortHandler(store))
	r.PUT("/:short", handlers.SetShortHandler(store))

	n.UseHandler(r)

	host := os.Getenv("HOST")
	if host == "" {
		host = "localhost"
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	err = http.ListenAndServe(net.JoinHostPort(host, port), n)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"syscall"
)

var verbose = false

func runGit(args ...string) {
	fullArgs := []string{"git"}
	fullArgs = append(fullArgs, args...)
	if verbose {
		log.Println("Running:", fullArgs)
	}
	syscall.Exec("/usr/bin/git", fullArgs, os.Environ())
}

func main() {

	// if len(sys.argv) <= 1:
	// 	os.execlp("git", "git")

	if len(os.Args) <= 1 {
		runGit()
	}

	/// repo = str(sys.argv[-1])
	repo := os.Args[len(os.Args)-1]

	/// if repo.endswith(".git"):
	/// 	repo = repo[:-4]
	repo = strings.TrimSuffix(repo, ".git")

	/// if "/" not in repo:
	/// 	os.execlp("git", "git")
	if !strings.Contains(repo, "/") {
		runGit()
	}

	gitGetHost := os.Getenv("GIT_GET_HOST")
	if gitGetHost == "" {
		gitGetHost = "github.com"
	}

	verbose = os.Getenv("GIT_GET_VERBOSE") != ""

	path := os.Getenv("GIT_GET_PATH")
	if path == "" {
		path = filepath.Join(os.Getenv("HOME"), "src")
	}

	if verbose {
		log.Println("Using base:", path)
	}

	var repoParts []string
	/// if repo.count(":") == 1:
	if strings.Count(repo, ":") == 1 {
		/// if "@" in repo:
		if strings.Contains(repo, "@") {
			///	repo_parts = repo[repo.find("@")+1:].replace(":", "/").split("/")
			repoParts = strings.Split(strings.Replace(repo[strings.Index(repo, "@")+1:len(repo)-1], ":", "/", -1), "/")
		} else {
			///	repo_parts = repo.replace(":", "/").split("/")
			repoParts = strings.Split(strings.Replace(repo, ":", "/", -1), "/")
			///	repo = "git@" + repo
			repo = "git@" + repo
		}
		/// elif repo.count("/") == 1:
	} else if strings.Count(repo, "/") == 1 {
		///	# Something from github
		///	repo_parts = ["github.com"] + repo.split("/")
		repoParts = []string{gitGetHost}
		repoParts = append(repoParts, strings.Split(repo, "/")...)
		/// repo = "git@github.com:%s.git" % repo
		repo = fmt.Sprintf("git@%s:%s.git", gitGetHost, repo)
		if verbose {
			log.Println("Did build repo:", repo)
		}
	}

	/// else:
	/// 	# http repo?
	/// 	print("TODO...")
	/// 	exit(1)
	///

	targetDir := filepath.Join(repoParts...)
	targetDir = filepath.Join(path, targetDir)

	if verbose {
		log.Println("Using target dir:", targetDir)
	}
	err := os.MkdirAll(targetDir, os.ModePerm)
	if nil != err {
		log.Fatal(err)
	}
	/// target_dir = os.path.join(os.getenv("HOME"), "src", *repo_parts)
	/// try:
	/// 	os.makedirs(target_dir)
	/// except OSError as exc:
	/// 	if exc.errno == errno.EEXIST and os.path.isdir(target_dir):
	/// 		pass
	/// 	else:
	/// 		raise
	///
	/// os.execlp("git", "git", "clone", repo, target_dir)
	runGit("clone", repo, targetDir)
}
<commit_msg>Refactor var<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"syscall"
)

var verbose = false

func runGit(args ...string) {
	fullArgs := []string{"git"}
	fullArgs = append(fullArgs, args...)
	if verbose {
		log.Println("Running:", fullArgs)
	}
	syscall.Exec("/usr/bin/git", fullArgs, os.Environ())
}

func main() {

	// if len(sys.argv) <= 1:
	// 	os.execlp("git", "git")

	if len(os.Args) <= 1 {
		runGit()
	}

	/// repo = str(sys.argv[-1])
	repo := os.Args[len(os.Args)-1]

	/// if repo.endswith(".git"):
	/// 	repo = repo[:-4]
	repo = strings.TrimSuffix(repo, ".git")

	/// if "/" not in repo:
	/// 	os.execlp("git", "git")
	if !strings.Contains(repo, "/") {
		runGit()
	}

	host := os.Getenv("GIT_GET_HOST")
	if host == "" {
		host = "github.com"
	}

	verbose = os.Getenv("GIT_GET_VERBOSE") != ""

	path := os.Getenv("GIT_GET_PATH")
	if path == "" {
		path = filepath.Join(os.Getenv("HOME"), "src")
	}

	if verbose {
		log.Println("Using base:", path)
	}

	var repoParts []string
	/// if repo.count(":") == 1:
	if strings.Count(repo, ":") == 1 {
		/// if "@" in repo:
		if strings.Contains(repo, "@") {
			///	repo_parts = repo[repo.find("@")+1:].replace(":", "/").split("/")
			repoParts = strings.Split(strings.Replace(repo[strings.Index(repo, "@")+1:len(repo)-1], ":", "/", -1), "/")
		} else {
			///	repo_parts = repo.replace(":", "/").split("/")
			repoParts = strings.Split(strings.Replace(repo, ":", "/", -1), "/")
			///	repo = "git@" + repo
			repo = "git@" + repo
		}
		/// elif repo.count("/") == 1:
	} else if strings.Count(repo, "/") == 1 {
		///	# Something from github
		///	repo_parts = ["github.com"] + repo.split("/")
		repoParts = []string{host}
		repoParts = append(repoParts, strings.Split(repo, "/")...)
		/// repo = "git@github.com:%s.git" % repo
		repo = fmt.Sprintf("git@%s:%s.git", host, repo)
		if verbose {
			log.Println("Did build repo:", repo)
		}
	}

	/// else:
	/// 	# http repo?
	/// 	print("TODO...")
	/// 	exit(1)
	///

	targetDir := filepath.Join(repoParts...)
	targetDir = filepath.Join(path, targetDir)

	if verbose {
		log.Println("Using target dir:", targetDir)
	}
	err := os.MkdirAll(targetDir, os.ModePerm)
	if nil != err {
		log.Fatal(err)
	}
	/// target_dir = os.path.join(os.getenv("HOME"), "src", *repo_parts)
	/// try:
	/// 	os.makedirs(target_dir)
	/// except OSError as exc:
	/// 	if exc.errno == errno.EEXIST and os.path.isdir(target_dir):
	/// 		pass
	/// 	else:
	/// 		raise
	///
	/// os.execlp("git", "git", "clone", repo, target_dir)
	runGit("clone", repo, targetDir)
}
<|endoftext|>


<commit_before>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"flag"
	"fmt"
	"go/build"
	"log"
	"os"
	"path/filepath"
	//"net/http/pprof"
	"github.com/kardianos/osext"
	//"github.com/sanbornm/go-selfupdate/selfupdate" #included in update.go to change heavily
	//"github.com/sanderhahn/gozip"
	"github.com/gin-gonic/gin"
	"github.com/itsjamie/gin-cors"
	"github.com/kardianos/service"
	"github.com/vharitonsky/iniflags"
	"runtime/debug"
	"text/template"
	"time"
)

var (
	version      = "1.83"
	versionFloat = float32(1.83)
	addr         = flag.String("addr", ":8989", "http service address")
	addrSSL      = flag.String("addrSSL", ":8990", "https service address")
	//assets       = flag.String("assets", defaultAssetPath(), "path to assets")
	verbose = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	//homeTempl *template.Template
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")

	configIni = flag.String("configFile", "config.ini", "config file path")
	// regular expression to sort the serial port list
	// typically this wouldn't be provided, but if the user wants to clean
	// up their list with a regexp so it's cleaner inside their end-user interface
	// such as ChiliPeppr, this can make the massive list that Linux gives back
	// to you be a bit more manageable
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")

	// allow garbageCollection()
	//isGC = flag.Bool("gc", false, "Is garbage collection on? Off by default.")
	//isGC = flag.Bool("gc", true, "Is garbage collection on? Off by default.")
	gcType = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")

	// whether to do buffer flow debugging
	bufFlowDebugType = flag.String("bufflowdebug", "off", "off = (default) We do not send back any debug JSON, on = We will send back a JSON response with debug info based on the configuration of the buffer flow that the user picked")

	// hostname. allow user to override, otherwise we look it up
	hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")

	updateUrl = flag.String("updateUrl", "", "")
	appName   = flag.String("appName", "", "")
)

var globalConfigMap map[string]interface{}

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

func defaultAssetPath() string {
	//p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
	p, err := build.Default.Import("github.com/johnlauer/serial-port-json-server", "", build.FindOnly)
	if err != nil {
		return "."
	}
	return p.Dir
}

func homeHandler(c *gin.Context) {
	homeTemplate.Execute(c.Writer, c.Request.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 5 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 5 secs. Now launching...")
}

var logger service.Logger

type program struct{}

func (p *program) Start(s service.Service) error {
	// Start should not block. Do the actual work async.
	go p.run()
	return nil
}
func (p *program) run() {
	startDaemon()
}
func (p *program) Stop(s service.Service) error {
	// Stop should not block. Return with a few seconds.
	<-time.After(time.Second * 13)
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "ArduinoCreateBridge",
		DisplayName: "Arduino Create Bridge",
		Description: "A bridge that allows Arduino Create to operate on the boards connected to the computer",
	}

	prg := &program{}
	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	if len(os.Args) > 1 {
		err = service.Control(s, os.Args[1])
		if err != nil {
			log.Fatal(err)
		}
		return
	}

	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}

	err = s.Install()
	if err != nil {
		logger.Error(err)
	}

	err = s.Run()
	if err != nil {
		logger.Error(err)
	}
}

func startDaemon() {
	// setupSysTray()
	go func() {

		// autoextract self
		src, _ := osext.Executable()
		dest := filepath.Dir(src)

		// save the config.ini (if it exists)
		if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
			fmt.Println("First run, unzipping self")
			err := Unzip(src, dest)
			fmt.Println("Self extraction, err:", err)
		}

		if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
			flag.Parse()
			fmt.Println("No config.ini at", *configIni)
		} else {
			flag.Set("config", dest+"/"+*configIni)
			iniflags.Parse()
		}

		// setup logging
		log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

		// see if we are supposed to wait 5 seconds
		if *isLaunchSelf {
			launchSelfLater()
		}

		var updater = &Updater{
			CurrentVersion: version,
			ApiURL:         *updateUrl,
			BinURL:         *updateUrl,
			DiffURL:        "",
			Dir:            "update/",
			CmdName:        *appName,
		}

		if updater != nil {
			go updater.BackgroundRun()
		}

		// data, err := Asset("arduino.zip")
		// if err != nil {
		// 	log.Println("arduino tools not found")
		// }

		createGlobalConfigMap(&globalConfigMap)

		//getList()
		f := flag.Lookup("addr")
		log.Println("Version:" + version)

		// hostname
		hn, _ := os.Hostname()
		if *hostname == "unknown-hostname" {
			*hostname = hn
		}
		log.Println("Hostname:", *hostname)

		// turn off garbage collection
		// this is dangerous, as u could overflow memory
		//if *isGC {
		if *gcType == "std" {
			log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
		} else if *gcType == "max" {
			log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
		} else {
			log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
			debug.SetGCPercent(-1)
		}

		ip := "0.0.0.0"
		log.Print("Starting server and websocket on " + ip + "" + f.Value.String())
		//homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))

		log.Println("The Serial Port JSON Server is now running.")
		log.Println("If you are using ChiliPeppr, you may go back to it and connect to this server.")

		// see if they provided a regex filter
		if len(*regExpFilter) > 0 {
			log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
		}

		// list serial ports
		portList, _ := GetList(false)
		/*if errSys != nil {
			log.Printf("Got system error trying to retrieve serial port list. Err:%v\n", errSys)
			log.Fatal("Exiting")
		}*/
		log.Println("Your serial ports:")
		if len(portList) == 0 {
			log.Println("\tThere are no serial ports to list.")
		}
		for _, element := range portList {
			log.Printf("\t%v\n", element)

		}

		if !*verbose {
			log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
			log.SetOutput(new(NullWriter)) //route all logging to nullwriter
		}

		// launch the hub routine which is the singleton for the websocket server
		go h.run()
		// launch our serial port routine
		go sh.run()
		// launch our dummy data routine
		//go d.run()

		go discoverLoop()

		r := gin.New()

		socketHandler := wsHandler().ServeHTTP

		r.Use(cors.Middleware(cors.Config{
			Origins:         "https://create.arduino.cc, http://create.arduino.cc, https://create-dev.arduino.cc, http://create-dev.arduino.cc, http://webide.arduino.cc:8080",
			Methods:         "GET, PUT, POST, DELETE",
			RequestHeaders:  "Origin, Authorization, Content-Type",
			ExposedHeaders:  "",
			MaxAge:          50 * time.Second,
			Credentials:     true,
			ValidateHeaders: false,
		}))

		r.GET("/", homeHandler)
		r.POST("/upload", uploadHandler)
		r.GET("/socket.io/", socketHandler)
		r.POST("/socket.io/", socketHandler)
		r.Handle("WS", "/socket.io/", socketHandler)
		r.Handle("WSS", "/socket.io/", socketHandler)
		go func() {
			if err := r.RunTLS(*addrSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil {
				fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
				log.Fatal("Error ListenAndServe:", err)
			}
		}()

		if err := r.Run(*addr); err != nil {
			fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()

}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
</form>

`
<commit_msg>Add origins for localhost and staging<commit_after>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"flag"
	"fmt"
	"go/build"
	"log"
	"os"
	"path/filepath"
	//"net/http/pprof"
	"github.com/kardianos/osext"
	//"github.com/sanbornm/go-selfupdate/selfupdate" #included in update.go to change heavily
	//"github.com/sanderhahn/gozip"
	"github.com/gin-gonic/gin"
	"github.com/itsjamie/gin-cors"
	"github.com/kardianos/service"
	"github.com/vharitonsky/iniflags"
	"runtime/debug"
	"text/template"
	"time"
)

var (
	version      = "1.83"
	versionFloat = float32(1.83)
	addr         = flag.String("addr", ":8989", "http service address")
	addrSSL      = flag.String("addrSSL", ":8990", "https service address")
	//assets       = flag.String("assets", defaultAssetPath(), "path to assets")
	verbose = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	//homeTempl *template.Template
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")

	configIni = flag.String("configFile", "config.ini", "config file path")
	// regular expression to sort the serial port list
	// typically this wouldn't be provided, but if the user wants to clean
	// up their list with a regexp so it's cleaner inside their end-user interface
	// such as ChiliPeppr, this can make the massive list that Linux gives back
	// to you be a bit more manageable
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")

	// allow garbageCollection()
	//isGC = flag.Bool("gc", false, "Is garbage collection on? Off by default.")
	//isGC = flag.Bool("gc", true, "Is garbage collection on? Off by default.")
	gcType = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")

	// whether to do buffer flow debugging
	bufFlowDebugType = flag.String("bufflowdebug", "off", "off = (default) We do not send back any debug JSON, on = We will send back a JSON response with debug info based on the configuration of the buffer flow that the user picked")

	// hostname. allow user to override, otherwise we look it up
	hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")

	updateUrl = flag.String("updateUrl", "", "")
	appName   = flag.String("appName", "", "")
)

var globalConfigMap map[string]interface{}

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

func defaultAssetPath() string {
	//p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
	p, err := build.Default.Import("github.com/johnlauer/serial-port-json-server", "", build.FindOnly)
	if err != nil {
		return "."
	}
	return p.Dir
}

func homeHandler(c *gin.Context) {
	homeTemplate.Execute(c.Writer, c.Request.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 5 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 5 secs. Now launching...")
}

var logger service.Logger

type program struct{}

func (p *program) Start(s service.Service) error {
	// Start should not block. Do the actual work async.
	go p.run()
	return nil
}
func (p *program) run() {
	startDaemon()
}
func (p *program) Stop(s service.Service) error {
	// Stop should not block. Return with a few seconds.
	<-time.After(time.Second * 13)
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "ArduinoCreateBridge",
		DisplayName: "Arduino Create Bridge",
		Description: "A bridge that allows Arduino Create to operate on the boards connected to the computer",
	}

	prg := &program{}
	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	if len(os.Args) > 1 {
		err = service.Control(s, os.Args[1])
		if err != nil {
			log.Fatal(err)
		}
		return
	}

	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}

	err = s.Install()
	if err != nil {
		logger.Error(err)
	}

	err = s.Run()
	if err != nil {
		logger.Error(err)
	}
}

func startDaemon() {
	// setupSysTray()
	go func() {

		// autoextract self
		src, _ := osext.Executable()
		dest := filepath.Dir(src)

		// save the config.ini (if it exists)
		if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
			fmt.Println("First run, unzipping self")
			err := Unzip(src, dest)
			fmt.Println("Self extraction, err:", err)
		}

		if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
			flag.Parse()
			fmt.Println("No config.ini at", *configIni)
		} else {
			flag.Set("config", dest+"/"+*configIni)
			iniflags.Parse()
		}

		// setup logging
		log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

		// see if we are supposed to wait 5 seconds
		if *isLaunchSelf {
			launchSelfLater()
		}

		var updater = &Updater{
			CurrentVersion: version,
			ApiURL:         *updateUrl,
			BinURL:         *updateUrl,
			DiffURL:        "",
			Dir:            "update/",
			CmdName:        *appName,
		}

		if updater != nil {
			go updater.BackgroundRun()
		}

		// data, err := Asset("arduino.zip")
		// if err != nil {
		// 	log.Println("arduino tools not found")
		// }

		createGlobalConfigMap(&globalConfigMap)

		//getList()
		f := flag.Lookup("addr")
		log.Println("Version:" + version)

		// hostname
		hn, _ := os.Hostname()
		if *hostname == "unknown-hostname" {
			*hostname = hn
		}
		log.Println("Hostname:", *hostname)

		// turn off garbage collection
		// this is dangerous, as u could overflow memory
		//if *isGC {
		if *gcType == "std" {
			log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
		} else if *gcType == "max" {
			log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
		} else {
			log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
			debug.SetGCPercent(-1)
		}

		ip := "0.0.0.0"
		log.Print("Starting server and websocket on " + ip + "" + f.Value.String())
		//homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))

		log.Println("The Serial Port JSON Server is now running.")
		log.Println("If you are using ChiliPeppr, you may go back to it and connect to this server.")

		// see if they provided a regex filter
		if len(*regExpFilter) > 0 {
			log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
		}

		// list serial ports
		portList, _ := GetList(false)
		/*if errSys != nil {
			log.Printf("Got system error trying to retrieve serial port list. Err:%v\n", errSys)
			log.Fatal("Exiting")
		}*/
		log.Println("Your serial ports:")
		if len(portList) == 0 {
			log.Println("\tThere are no serial ports to list.")
		}
		for _, element := range portList {
			log.Printf("\t%v\n", element)

		}

		if !*verbose {
			log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
			log.SetOutput(new(NullWriter)) //route all logging to nullwriter
		}

		// launch the hub routine which is the singleton for the websocket server
		go h.run()
		// launch our serial port routine
		go sh.run()
		// launch our dummy data routine
		//go d.run()

		go discoverLoop()

		r := gin.New()

		socketHandler := wsHandler().ServeHTTP

		r.Use(cors.Middleware(cors.Config{
			Origins:         "https://create.arduino.cc, http://create.arduino.cc, https://create-dev.arduino.cc, http://create-dev.arduino.cc, http://webide.arduino.cc:8080, http://create-staging.arduino.cc, https://create-staging.arduino.cc, http://localhost:8989, https://localhost:8990",
			Methods:         "GET, PUT, POST, DELETE",
			RequestHeaders:  "Origin, Authorization, Content-Type",
			ExposedHeaders:  "",
			MaxAge:          50 * time.Second,
			Credentials:     true,
			ValidateHeaders: false,
		}))

		r.GET("/", homeHandler)
		r.POST("/upload", uploadHandler)
		r.GET("/socket.io/", socketHandler)
		r.POST("/socket.io/", socketHandler)
		r.Handle("WS", "/socket.io/", socketHandler)
		r.Handle("WSS", "/socket.io/", socketHandler)
		go func() {
			if err := r.RunTLS(*addrSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil {
				fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
				log.Fatal("Error ListenAndServe:", err)
			}
		}()

		if err := r.Run(*addr); err != nil {
			fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()

}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
</form>

`
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/dchest/uniuri"
	"github.com/ewhal/pygments"
	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
)

const (
	ADDRESS  = "http://localhost:9900"
	LENGTH   = 6
	TEXT     = "$ <command> | curl -F 'p=<-' " + ADDRESS + "\n"
	PORT     = ":9900"
	USERNAME = ""
	PASS     = ""
	NAME     = ""
	DATABASE = USERNAME + ":" + PASS + "@/" + NAME + "?charset=utf8"
)

type Response struct {
	ID     string `json:"id"`
	HASH   string `json:"hash"`
	URL    string `json:"url"`
	SIZE   int    `json:"size"`
	DELKEY string `json:"delkey"`
}

func check(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

func generateName() string {
	s := uniuri.NewLen(LENGTH)
	db, err := sql.Open("mysql", DATABASE)
	check(err)

	query, err := db.Query("select id from pastebin")
	for query.Next() {
		var id string
		err := query.Scan(&id)
		if err != nil {

		}
		if id == s {
			generateName()
		}
	}
	db.Close()

	return s

}
func hash(paste []byte) string {
	hasher := sha1.New()
	hasher.Write(paste)
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

func save(raw []byte) []string {
	p := raw[86 : len(raw)-46]

	db, err := sql.Open("mysql", DATABASE)
	check(err)

	sha := hash(p)
	query, err := db.Query("select id, hash, data, delkey from pastebin")
	for query.Next() {
		var id, hash, paste, delkey string
		err := query.Scan(&id, &hash, &paste, &delkey)
		check(err)
		if hash == sha {
			url := ADDRESS + "/p/" + id
			return []string{id, hash, url, paste, delkey}
		}
	}
	id := generateName()
	url := ADDRESS + "/p/" + id
	delKey := uniuri.NewLen(40)
	paste := html.EscapeString(string(p))

	stmt, err := db.Prepare("INSERT INTO pastebin(id, hash, data, delkey) values(?,?,?,?)")
	check(err)
	_, err = stmt.Exec(id, sha, paste, delKey)
	check(err)
	db.Close()
	return []string{id, sha, url, paste, delKey}

}

func delHandler(w http.ResponseWriter, r *http.Request) {
	/*	vars := mux.Vars(r)
		paste := vars["pasteId"]
		delkey := vars["delKey"] */
}
func saveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		buf, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, err.Error(), 500)
		}

		values := save(buf)
		b := &Response{
			ID:     values[0],
			HASH:   values[1],
			URL:    values[2],
			SIZE:   len(values[3]),
			DELKEY: values[4],
		}

		switch output {
		case "json":

			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)

			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		case "xml":
			x, err := xml.MarshalIndent(b, "", "  ")
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

			w.Header().Set("Content-Type", "application/xml")
			w.Write(x)

		default:
			io.WriteString(w, b.URL+"\n")
			io.WriteString(w, "delete key: "+b.DELKEY+"\n")
		}
	}

}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, TEXT)
}
func langHandler(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]
	s := getPaste(paste)
	highlight := pygments.Highlight(html.UnescapeString(s), lang, "html", "full, style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,", "utf-8")
	io.WriteString(w, highlight)

}

func getPaste(paste string) string {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	var s string
	err = db.QueryRow("select data from pastebin where id=?", param1).Scan(&s)
	db.Close()
	check(err)

	if err == sql.ErrNoRows {
		return "Error invalid paste"
	} else {
		return html.UnescapeString(s)
	}

}
func pasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s := getPaste(paste)
	io.WriteString(w, s)

}

func main() {
	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/", rootHandler)
	router.HandleFunc("/p/{pasteId}", pasteHandler)
	router.HandleFunc("/p/{pasteId}/{lang}", langHandler)
	router.HandleFunc("/save", saveHandler)
	router.HandleFunc("/save/{output}", saveHandler)
	router.HandleFunc("/del/{pasteId}/{delKey}", delHandler)
	err := http.ListenAndServe(PORT, router)
	if err != nil {
		log.Fatal(err)
	}

}
<commit_msg>Add delete paste handling<commit_after>package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/dchest/uniuri"
	"github.com/ewhal/pygments"
	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
)

const (
	ADDRESS  = "http://localhost:9900"
	LENGTH   = 6
	TEXT     = "$ <command> | curl -F 'p=<-' " + ADDRESS + "\n"
	PORT     = ":9900"
	USERNAME = ""
	PASS     = ""
	NAME     = ""
	DATABASE = USERNAME + ":" + PASS + "@/" + NAME + "?charset=utf8"
)

type Response struct {
	ID     string `json:"id"`
	HASH   string `json:"hash"`
	URL    string `json:"url"`
	SIZE   int    `json:"size"`
	DELKEY string `json:"delkey"`
}

func check(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

func generateName() string {
	s := uniuri.NewLen(LENGTH)
	db, err := sql.Open("mysql", DATABASE)
	check(err)

	query, err := db.Query("select id from pastebin")
	for query.Next() {
		var id string
		err := query.Scan(&id)
		if err != nil {

		}
		if id == s {
			generateName()
		}
	}
	db.Close()

	return s

}
func hash(paste []byte) string {
	hasher := sha1.New()
	hasher.Write(paste)
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

func save(raw []byte) []string {
	p := raw[86 : len(raw)-46]

	db, err := sql.Open("mysql", DATABASE)
	check(err)

	sha := hash(p)
	query, err := db.Query("select id, hash, data, delkey from pastebin")
	for query.Next() {
		var id, hash, paste, delkey string
		err := query.Scan(&id, &hash, &paste, &delkey)
		check(err)
		if hash == sha {
			url := ADDRESS + "/p/" + id
			return []string{id, hash, url, paste, delkey}
		}
	}
	id := generateName()
	url := ADDRESS + "/p/" + id
	delKey := uniuri.NewLen(40)
	paste := html.EscapeString(string(p))

	stmt, err := db.Prepare("INSERT INTO pastebin(id, hash, data, delkey) values(?,?,?,?)")
	check(err)
	_, err = stmt.Exec(id, sha, paste, delKey)
	check(err)
	db.Close()
	return []string{id, sha, url, paste, delKey}

}

func delHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	delkey := vars["delKey"]

	db, err := sql.Open("mysql", DATABASE)
	check(err)

	stmt, err := db.Prepare("delete from pastebin where delkey=? id=?")
	check(err)

	res, err := stmt.Exec(html.EscapeString(delkey), html.EscapeString(paste))
	check(err)

	affect, err := res.RowsAffected()
	check(err)

	io.WriteString(w, string(affect))

	db.Close()

}
func saveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		buf, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, err.Error(), 500)
		}

		values := save(buf)
		b := &Response{
			ID:     values[0],
			HASH:   values[1],
			URL:    values[2],
			SIZE:   len(values[3]),
			DELKEY: values[4],
		}

		switch output {
		case "json":

			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)

			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		case "xml":
			x, err := xml.MarshalIndent(b, "", "  ")
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

			w.Header().Set("Content-Type", "application/xml")
			w.Write(x)

		default:
			io.WriteString(w, b.URL+"\n")
			io.WriteString(w, "delete key: "+b.DELKEY+"\n")
		}
	}

}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, TEXT)
}
func langHandler(w http.ResponseWriter, r *http.Request) {

	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]
	s := getPaste(paste)
	highlight := pygments.Highlight(html.UnescapeString(s), html.EscapeString(lang), "html", "full, style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,", "utf-8")
	io.WriteString(w, highlight)

}

func getPaste(paste string) string {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	var s string
	err = db.QueryRow("select data from pastebin where id=?", param1).Scan(&s)
	db.Close()
	check(err)

	if err == sql.ErrNoRows {
		return "Error invalid paste"
	} else {
		return html.UnescapeString(s)
	}

}
func pasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s := getPaste(paste)
	io.WriteString(w, s)

}

func main() {
	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/", rootHandler)
	router.HandleFunc("/p/{pasteId}", pasteHandler)
	router.HandleFunc("/p/{pasteId}/{lang}", langHandler)
	router.HandleFunc("/save", saveHandler)
	router.HandleFunc("/save/{output}", saveHandler)
	router.HandleFunc("/del/{pasteId}/{delKey}", delHandler)
	err := http.ListenAndServe(PORT, router)
	if err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
	"flag"
	"net/http"
	"html"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/vohumana/golossary/dictionary"
	"github.com/vohumana/golossary/tokenizer"
)

func getJSONDefinitions(input string) (string, error) {
	api := dictionary.NewPearsonDictionaryDefault()
	tok := tokenizer.NewEnglish(input)
	words := tok.GetTokens()
	uniqueWords := make(map[string][]string)

	for _, word := range words {
		uniqueWords[strings.ToLower(word)] = nil
	}

	for word := range uniqueWords {
		def, err := api.DefineWord(word)
		if err != nil {
			fmt.Println(err)
		} else {
			uniqueWords[word] = def
		}
	}

	jsonOut,err := json.Marshal(uniqueWords)

	return string(jsonOut), err
}

func main() {
	var (
		httpAddr = flag.String("http", ":80", "HTTP service address.")
	)
	flag.Parse()

	// Use a buffered error channel so that handlers can
	// keep processing after throwing errors.
	errChan := make(chan error, 10)
	go func() {
		http.HandleFunc("/api/define", func (w http.ResponseWriter, r *http.Request) {
			var output string
			buf, err := ioutil.ReadAll(r.Body)

			if err == nil {
				output, err = getJSONDefinitions(string(buf))
			}

			if err != nil {
				fmt.Fprintf(w, "Hello, %q", html.EscapeString(err.Error()))
			} else {
				fmt.Fprintf(w, "%s", output)
			}
		})

		log.Println("Starting server...")
		log.Printf("HTTP service listening on %s", *httpAddr)

		errChan <- http.ListenAndServe(*httpAddr, nil)
	}()

	signalChan := make(chan os.Signal)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	for {
		select {
		case err := <-errChan:
			// Log any errors from our server
			log.Fatal(err)
		case s := <-signalChan:
			// ctrl+c is a clean exit
			log.Println(fmt.Sprintf("Captured %v. Exiting...", s))
			os.Exit(0)
		}
}

	// api := dictionary.NewPearsonDictionaryDefault()

	// fileName := flag.String("f", "/usr/bin/test.txt", "File to parse")
	// flag.Parse()

	// buf, err := ioutil.ReadFile(*fileName)
	// if err != nil {
	// 	panic(err)
	// }

	// tok := tokenizer.NewEnglish(string(buf))

	// words := tok.GetTokens()

	// uniqueWords := make(map[string][]string)

	// for _, word := range words {
	// 	uniqueWords[strings.ToLower(word)] = nil
	// }

	// for word := range uniqueWords {
	// 	fmt.Printf("Looking up definition for %s...\n", word)
	// 	def, err := api.DefineWord(word)
	// 	if err != nil {
	// 		fmt.Println(err)
	// 	} else {
	// 		uniqueWords[word] = def
	// 	}
	// }

	// fmt.Println("")

	// wordsWithNoDefinition := make([]string, 1)

	// for word, definitions := range uniqueWords {
	// 	if len(definitions) != 0 {
	// 		fmt.Printf("%s\n", word)
	// 		for _, def := range definitions {
	// 			fmt.Printf("---> %s\n", def)
	// 		}
	// 	} else {
	// 		wordsWithNoDefinition = append(wordsWithNoDefinition, word)
	// 	}
	// }

	// if len(wordsWithNoDefinition) != 0 {
	// 	fmt.Println("\nCould not find definitions for these words:")

	// 	for _, word := range wordsWithNoDefinition {
	// 		fmt.Println(word)
	// 	}
	// }
}<commit_msg>Cleaning up code<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
	"flag"
	"net/http"
	"html"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/vohumana/golossary/dictionary"
	"github.com/vohumana/golossary/tokenizer"
)

func getJSONDefinitions(input string) (string, error) {
	api := dictionary.NewPearsonDictionaryDefault()
	tok := tokenizer.NewEnglish(input)
	words := tok.GetTokens()
	uniqueWords := make(map[string][]string)

	for _, word := range words {
		uniqueWords[strings.ToLower(word)] = nil
	}

	for word := range uniqueWords {
		def, err := api.DefineWord(word)
		if err != nil {
			fmt.Println(err)
		} else {
			uniqueWords[word] = def
		}
	}

	jsonOut,err := json.Marshal(uniqueWords)

	return string(jsonOut), err
}

func main() {
	var (
		httpAddr = flag.String("http", ":80", "HTTP service address.")
	)
	flag.Parse()

	// Use a buffered error channel so that handlers can
	// keep processing after throwing errors.
	errChan := make(chan error, 10)
	go func() {
		http.HandleFunc("/api/define", func (w http.ResponseWriter, r *http.Request) {
			var output string
			buf, err := ioutil.ReadAll(r.Body)

			if err == nil {
				output, err = getJSONDefinitions(string(buf))
			}

			if err != nil {
				fmt.Fprintf(w, "%q", html.EscapeString(err.Error()))
			} else {
				fmt.Fprintf(w, "%s", output)
			}
		})

		log.Println("Starting server...")
		log.Printf("HTTP service listening on %s", *httpAddr)

		errChan <- http.ListenAndServe(*httpAddr, nil)
	}()

	signalChan := make(chan os.Signal)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	for {
		select {
		case err := <-errChan:
			// Log any errors from our server
			log.Fatal(err)
		case s := <-signalChan:
			// ctrl+c is a clean exit
			log.Println(fmt.Sprintf("Captured %v. Exiting...", s))
			os.Exit(0)
		}
	}
}<|endoftext|>