<commit_before>package main

import (
	"bytes"
	"fmt"
	ui "github.com/gizak/termui"
	"github.com/op/go-logging"
	"os"
	"strings"
	//jira "github.com/mikepea/go-jira"
	"jira"
)

const (
	ticketQuery = 1
	ticketList  = 2
	ticketShow  = 3
)

var exitNow = false

var currentPage = ticketQuery
var previousPage = ticketQuery

var currentQuery = ""
var previousQuery = ""

var ticketSelected = 0
var querySelected = 0

var activeQueryList *ui.List
var activeTicketList *ui.List

func prevTicket(n int) {
	ticketSelected = ticketSelected - n
}

func nextTicket(n int) {
	ticketSelected = ticketSelected + n
}

func prevQuery(n int) {
	querySelected = querySelected - n
}

func nextQuery(n int) {
	querySelected = querySelected + n
}

type Query struct {
	Name string
	JQL  string
}

var origQueries = []Query{
	Query{"My Tickets", "project = OPS AND assignee = currentUser() AND resolution = Unresolved"},
	Query{"My Watched Tickets", "watcher = currentUser() AND resolution = Unresolved"},
	Query{"unlabelled", "project = OPS AND labels IS EMPTY AND resolution = Unresolved"},
	Query{"Ops Queue", "project = OPS AND resolution = Unresolved"},
}

var displayQueries = []string{
	"My Tickets",
	"My Watched Tickets",
	"unlabelled",
	"OPS queue",
}

var currentTicketListCache []string
var displayTickets []string

func displayQueryResults(query string) []string {
	results := JiraQueryAsStrings(query)
	return results
}

func markActiveQuery() {
	for i, v := range origQueries {
		selected := ""
		if i == querySelected {
			selected = "fg-white,bg-blue"
		}
		displayQueries[i] = fmt.Sprintf("[%s](%s)", v.Name, selected)
	}
}

func markActiveTicket() {
	for i, v := range currentTicketListCache {
		selected := ""
		if i == ticketSelected {
			selected = "fg-white,bg-blue"
		}
		displayTickets[i] = fmt.Sprintf("[%s](%s)", v, selected)
	}
}

func handleTicketQueryPage() {
	ls := ui.NewList()
	ls.Items = displayQueries
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "List"
	ls.Height = 10
	ls.Width = 80
	ls.Y = 0
	activeQueryList = ls
	markActiveQuery()
	ui.Render(ls)
}

func changePage() {
	switch currentPage {
	case ticketQuery:
		handleTicketQueryPage()
	case ticketList:
		handleTicketListPage()
	case ticketShow:
	}
}

func handleTicketListPage() {
	ticketSelected = 0
	currentTicketListCache = displayQueryResults(origQueries[querySelected].JQL)
	displayTickets = make([]string, len(currentTicketListCache))
	ls := ui.NewList()
	ls.Items = displayTickets
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "List"
	ls.Height = 30
	ls.Width = 132
	ls.Y = 0
	activeTicketList = ls
	markActiveTicket()
	ui.Render(ls)
}

func getJiraOpts() map[string]interface{} {

	user := os.Getenv("USER")
	home := os.Getenv("HOME")
	defaultQueryFields := "summary,created,updated,priority,status,reporter,assignee"
	defaultSort := "priority asc, created"
	defaultMaxResults := 500

	defaults := map[string]interface{}{
		"user":        user,
		"endpoint":    os.Getenv("JIRA_ENDPOINT"),
		"queryfields": defaultQueryFields,
		"directory":   fmt.Sprintf("%s/.jira.d/templates", home),
		"sort":        defaultSort,
		"max_results": defaultMaxResults,
		"method":      "GET",
		"quiet":       true,
	}
	//opts := make(map[string]interface{})
	return defaults
}

func runJiraQuery(query string) (interface{}, error) {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	return c.FindIssues()
}

func JiraQueryAsStrings(query string) []string {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	data, _ := c.FindIssues()
	buf := new(bytes.Buffer)
	jira.RunTemplate(c.GetTemplate("list"), data, buf)
	return strings.Split(buf.String(), "\n")
}

func updateQueryPage(ls *ui.List) {
	markActiveQuery()
	ls.Items = displayQueries
	ui.Render(ls)
}

func updateTicketListPage(ls *ui.List) {
	markActiveTicket()
	ui.Render(ls)
}

func registerKeyboardHandlers() {
	ui.Handle("/sys/kbd/q", func(ui.Event) {
		ui.StopLoop()
		exitNow = true
	})
	ui.Handle("/sys/kbd/j", func(ui.Event) {
		handleDownKey()
	})
	ui.Handle("/sys/kbd/k", func(ui.Event) {
		handleUpKey()
	})
	ui.Handle("/sys/kbd/l", func(ui.Event) {
		handleSelectKey()
	})
}

func handleSelectKey() {
	switch currentPage {
	case ticketQuery:
		currentPage = ticketList
		previousPage = ticketQuery
	case ticketList:
		currentPage = ticketQuery
		previousPage = ticketList
	}
	changePage()
}

func handleUpKey() {
	switch currentPage {
	case ticketQuery:
		prevQuery(1)
		updateQueryPage(activeQueryList)
	case ticketList:
		prevTicket(1)
		updateTicketListPage(activeTicketList)
	}
}

func handleDownKey() {
	switch currentPage {
	case ticketQuery:
		nextQuery(1)
		updateQueryPage(activeQueryList)
	case ticketList:
		nextTicket(1)
		updateTicketListPage(activeTicketList)
	}
}

var (
	log    = logging.MustGetLogger("jira")
	format = "%{color}%{time:2006-01-02T15:04:05.000Z07:00} %{level:-5s} [%{shortfile}]%{color:reset} %{message}"
)

func main() {

	opts := getJiraOpts()

	logging.SetLevel(logging.NOTICE, "")

	c := jira.New(opts)

	// TODO: make this as quick as can be
	if _, err := runJiraQuery("assignee = CurrentUser() AND resolution = Unresolved"); err != nil {
		c.CmdLogin()
	}

	err := ui.Init()
	if err != nil {
		panic(err)
	}
	defer ui.Close()

	registerKeyboardHandlers()

	for exitNow != true {

		handleTicketQueryPage()
		ui.Loop()

	}

}
<commit_msg><enter> for selection :)<commit_after>package main

import (
	"bytes"
	"fmt"
	ui "github.com/gizak/termui"
	"github.com/op/go-logging"
	"os"
	"strings"
	//jira "github.com/mikepea/go-jira"
	"jira"
)

const (
	ticketQuery = 1
	ticketList  = 2
	ticketShow  = 3
)

var exitNow = false

var currentPage = ticketQuery
var previousPage = ticketQuery

var currentQuery = ""
var previousQuery = ""

var ticketSelected = 0
var querySelected = 0

var activeQueryList *ui.List
var activeTicketList *ui.List

func prevTicket(n int) {
	ticketSelected = ticketSelected - n
}

func nextTicket(n int) {
	ticketSelected = ticketSelected + n
}

func prevQuery(n int) {
	querySelected = querySelected - n
}

func nextQuery(n int) {
	querySelected = querySelected + n
}

type Query struct {
	Name string
	JQL  string
}

var origQueries = []Query{
	Query{"My Tickets", "project = OPS AND assignee = currentUser() AND resolution = Unresolved"},
	Query{"My Watched Tickets", "watcher = currentUser() AND resolution = Unresolved"},
	Query{"unlabelled", "project = OPS AND labels IS EMPTY AND resolution = Unresolved"},
	Query{"Ops Queue", "project = OPS AND resolution = Unresolved"},
}

var displayQueries = []string{
	"My Tickets",
	"My Watched Tickets",
	"unlabelled",
	"OPS queue",
}

var currentTicketListCache []string
var displayTickets []string

func displayQueryResults(query string) []string {
	results := JiraQueryAsStrings(query)
	return results
}

func markActiveQuery() {
	for i, v := range origQueries {
		selected := ""
		if i == querySelected {
			selected = "fg-white,bg-blue"
		}
		displayQueries[i] = fmt.Sprintf("[%s](%s)", v.Name, selected)
	}
}

func markActiveTicket() {
	for i, v := range currentTicketListCache {
		selected := ""
		if i == ticketSelected {
			selected = "fg-white,bg-blue"
		}
		displayTickets[i] = fmt.Sprintf("[%s](%s)", v, selected)
	}
}

func handleTicketQueryPage() {
	ls := ui.NewList()
	ls.Items = displayQueries
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "List"
	ls.Height = 10
	ls.Width = 80
	ls.Y = 0
	activeQueryList = ls
	markActiveQuery()
	ui.Render(ls)
}

func changePage() {
	switch currentPage {
	case ticketQuery:
		handleTicketQueryPage()
	case ticketList:
		handleTicketListPage()
	case ticketShow:
	}
}

func handleTicketListPage() {
	ticketSelected = 0
	currentTicketListCache = displayQueryResults(origQueries[querySelected].JQL)
	displayTickets = make([]string, len(currentTicketListCache))
	ls := ui.NewList()
	ls.Items = displayTickets
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = "List"
	ls.Height = 30
	ls.Width = 132
	ls.Y = 0
	activeTicketList = ls
	markActiveTicket()
	ui.Render(ls)
}

func getJiraOpts() map[string]interface{} {

	user := os.Getenv("USER")
	home := os.Getenv("HOME")
	defaultQueryFields := "summary,created,updated,priority,status,reporter,assignee"
	defaultSort := "priority asc, created"
	defaultMaxResults := 500

	defaults := map[string]interface{}{
		"user":        user,
		"endpoint":    os.Getenv("JIRA_ENDPOINT"),
		"queryfields": defaultQueryFields,
		"directory":   fmt.Sprintf("%s/.jira.d/templates", home),
		"sort":        defaultSort,
		"max_results": defaultMaxResults,
		"method":      "GET",
		"quiet":       true,
	}
	//opts := make(map[string]interface{})
	return defaults
}

func runJiraQuery(query string) (interface{}, error) {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	return c.FindIssues()
}

func JiraQueryAsStrings(query string) []string {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	data, _ := c.FindIssues()
	buf := new(bytes.Buffer)
	jira.RunTemplate(c.GetTemplate("list"), data, buf)
	return strings.Split(buf.String(), "\n")
}

func updateQueryPage(ls *ui.List) {
	markActiveQuery()
	ls.Items = displayQueries
	ui.Render(ls)
}

func updateTicketListPage(ls *ui.List) {
	markActiveTicket()
	ui.Render(ls)
}

func registerKeyboardHandlers() {
	ui.Handle("/sys/kbd/q", func(ui.Event) {
		ui.StopLoop()
		exitNow = true
	})
	ui.Handle("/sys/kbd/j", func(ui.Event) {
		handleDownKey()
	})
	ui.Handle("/sys/kbd/k", func(ui.Event) {
		handleUpKey()
	})
	ui.Handle("/sys/kbd/<enter>", func(ui.Event) {
		handleSelectKey()
	})
}

func handleSelectKey() {
	switch currentPage {
	case ticketQuery:
		currentPage = ticketList
		previousPage = ticketQuery
	case ticketList:
		currentPage = ticketQuery
		previousPage = ticketList
	}
	changePage()
}

func handleUpKey() {
	switch currentPage {
	case ticketQuery:
		prevQuery(1)
		updateQueryPage(activeQueryList)
	case ticketList:
		prevTicket(1)
		updateTicketListPage(activeTicketList)
	}
}

func handleDownKey() {
	switch currentPage {
	case ticketQuery:
		nextQuery(1)
		updateQueryPage(activeQueryList)
	case ticketList:
		nextTicket(1)
		updateTicketListPage(activeTicketList)
	}
}

var (
	log    = logging.MustGetLogger("jira")
	format = "%{color}%{time:2006-01-02T15:04:05.000Z07:00} %{level:-5s} [%{shortfile}]%{color:reset} %{message}"
)

func main() {

	opts := getJiraOpts()

	logging.SetLevel(logging.NOTICE, "")

	c := jira.New(opts)

	// TODO: make this as quick as can be
	if _, err := runJiraQuery("assignee = CurrentUser() AND resolution = Unresolved"); err != nil {
		c.CmdLogin()
	}

	err := ui.Init()
	if err != nil {
		panic(err)
	}
	defer ui.Close()

	registerKeyboardHandlers()

	for exitNow != true {

		handleTicketQueryPage()
		ui.Loop()

	}

}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/labstack/echo"
	"github.com/node4j/node-repo-proxy/route"
	"github.com/node4j/node-repo-proxy/util"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "8000"
	}

	e := echo.New()
	util.SetLogger(e.Logger)

	route.Init(e)
	util.Log.Fatal(e.Start(":" + port))
}
<commit_msg>Changed default port<commit_after>package main

import (
	"os"

	"github.com/labstack/echo"
	"github.com/node4j/node-repo-proxy/route"
	"github.com/node4j/node-repo-proxy/util"
)

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

	e := echo.New()
	util.SetLogger(e.Logger)

	route.Init(e)
	util.Log.Fatal(e.Start(":" + port))
}
<|endoftext|>


<commit_before>package main

import (
  "bufio"
  "encoding/json"
  "github.com/gin-gonic/contrib/static"
  "github.com/gin-gonic/gin"
  "io/ioutil"
  "math/rand"
  "os"
  "strconv"
  "text/template"
)

// Set numWords constant
const numWords int = 5000

func check(e error) {
  if e != nil {
    panic(e)
  }
}

func randChoice(arr [numWords]string) (string) {
  idx := rand.Intn(len(arr))
  return arr[idx]
}

func extendJSON(target map[string]interface{}, extension map[string]interface{}) map[string]interface{} {
  var resultSlice map[string]interface{} = make(map[string]interface{}, len(target) + len(extension))
  for k, v := range target {
    resultSlice[k] = v
  }
  for k, v := range extension {
    resultSlice[k] = v
  }
  return resultSlice
}

func main() {
  // Create gin router
  r := gin.Default()

  // Setup router
  r.Use(static.Serve("/", static.LocalFile("public", false)))

  // Read data files
  var e error
  var data []byte
  var delimiters, prefixes, suffixes map[string]interface{}
  data, e = ioutil.ReadFile("public/data/delimiters.json")
  check(e)
  e = json.Unmarshal(data, &delimiters)
  check(e)
  data, e = ioutil.ReadFile("public/data/prefixes.json")
  check(e)
  e = json.Unmarshal(data, &prefixes)
  check(e)
  prefixes = extendJSON(prefixes, delimiters)
  data, e = ioutil.ReadFile("public/data/suffixes.json")
  check(e)
  e = json.Unmarshal(data, &suffixes)
  suffixes = extendJSON(suffixes, delimiters)

  // Create word array
  var words [numWords]string

  // Read from 5000-common-words.txt
  f, err := os.Open("5000-common-words.txt")
  check(err)
  scanner := bufio.NewScanner(f)
  scanner.Split(bufio.ScanLines)

  // Fetch words
  for i := 0; i < numWords; i++ {
    scanner.Scan()
    words[i] = scanner.Text()
  }

  /* Begin routes */

  // Index
  r.GET("/", func(c *gin.Context) {
    tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
      "templates/partials/index.html", "templates/partials/footer.html")
    if err != nil {
      c.String(500, "Internal Server Error: Error parsing templates")
      return
    }

    contextObj := gin.H{"title": "EZ Password Generator"}

    err = tmpl.Execute(c.Writer, contextObj)
    if err != nil {
      c.String(500, "Internal Server Error: Error executing compiled template")
      return
    }
  })

  // Random words
  r.GET("/randwords", func(c *gin.Context) {
    num, err := strconv.Atoi(c.DefaultQuery("num", "4"))

    if err != nil {
      c.String(400, "Bad Request: Num paramenter was not an integer.")
      return
    }
    if num <= 0 {
      c.String(400, "Bad Request: Num parameter must be positive.")
      return
    }

    // Dynamic array allocation
    var myWords []string
    myWords = make([]string, num)

    for i, _ := range myWords {
      myWords[i] = randChoice(words)
    }

    c.JSON(200, gin.H{"words": myWords})
  })

  r.GET("/delimiters", func(c *gin.Context) {
    c.JSON(200, gin.H(delimiters))
  })

  r.GET("/prefixes", func(c *gin.Context) {
    c.JSON(200, gin.H(prefixes))
  })

  r.GET("/suffixes", func(c *gin.Context) {
    c.JSON(200, gin.H(suffixes))
  })

  r.GET("/characters", func(c *gin.Context) {
    c.JSON(200, gin.H{
      "delimiters": delimiters,
      "prefixes": prefixes,
      "suffixes": suffixes,
    })
  })

  r.GET("/about", func(c *gin.Context) {
    tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
      "templates/partials/about.html", "templates/partials/footer.html")
    if err != nil {
      c.String(500, "Internal Server Error: Error parsing templates")
      return
    }

    contextObj := gin.H{"title": "EZ Password Generator"}

    err = tmpl.Execute(c.Writer, contextObj)
    if err != nil {
      c.String(500, "Internal Server Error: Error executing compiled template")
      return
    }
  })

  r.GET("/terms", func(c *gin.Context) {
    tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
      "templates/partials/terms.html", "templates/partials/footer.html")
    if err != nil {
      c.String(500, "Internal Server Error: Error parsing templates")
      return
    }

    contextObj := gin.H{"title": "EZ Password Generator"}

    err = tmpl.Execute(c.Writer, contextObj)
    if err != nil {
      c.String(500, "Internal Server Error: Error executing compiled template")
      return
    }
  })

  r.GET("/github", func(c *gin.Context) {
    c.Redirect(301, "https://github.com/andrewyang96/GoPasswordGenerator")
  })

  /* End routes */

  // Run server
  port := os.Getenv("PORT")
  if port == "" {
    port = "8000"
  }
  r.Run(":" + port)
}
<commit_msg>Run go fmt on main.go<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"github.com/gin-gonic/contrib/static"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"math/rand"
	"os"
	"strconv"
	"text/template"
)

// Set numWords constant
const numWords int = 5000

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func randChoice(arr [numWords]string) string {
	idx := rand.Intn(len(arr))
	return arr[idx]
}

func extendJSON(target map[string]interface{}, extension map[string]interface{}) map[string]interface{} {
	var resultSlice map[string]interface{} = make(map[string]interface{}, len(target)+len(extension))
	for k, v := range target {
		resultSlice[k] = v
	}
	for k, v := range extension {
		resultSlice[k] = v
	}
	return resultSlice
}

func main() {
	// Create gin router
	r := gin.Default()

	// Setup router
	r.Use(static.Serve("/", static.LocalFile("public", false)))

	// Read data files
	var e error
	var data []byte
	var delimiters, prefixes, suffixes map[string]interface{}
	data, e = ioutil.ReadFile("public/data/delimiters.json")
	check(e)
	e = json.Unmarshal(data, &delimiters)
	check(e)
	data, e = ioutil.ReadFile("public/data/prefixes.json")
	check(e)
	e = json.Unmarshal(data, &prefixes)
	check(e)
	prefixes = extendJSON(prefixes, delimiters)
	data, e = ioutil.ReadFile("public/data/suffixes.json")
	check(e)
	e = json.Unmarshal(data, &suffixes)
	suffixes = extendJSON(suffixes, delimiters)

	// Create word array
	var words [numWords]string

	// Read from 5000-common-words.txt
	f, err := os.Open("5000-common-words.txt")
	check(err)
	scanner := bufio.NewScanner(f)
	scanner.Split(bufio.ScanLines)

	// Fetch words
	for i := 0; i < numWords; i++ {
		scanner.Scan()
		words[i] = scanner.Text()
	}

	/* Begin routes */

	// Index
	r.GET("/", func(c *gin.Context) {
		tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
			"templates/partials/index.html", "templates/partials/footer.html")
		if err != nil {
			c.String(500, "Internal Server Error: Error parsing templates")
			return
		}

		contextObj := gin.H{"title": "EZ Password Generator"}

		err = tmpl.Execute(c.Writer, contextObj)
		if err != nil {
			c.String(500, "Internal Server Error: Error executing compiled template")
			return
		}
	})

	// Random words
	r.GET("/randwords", func(c *gin.Context) {
		num, err := strconv.Atoi(c.DefaultQuery("num", "4"))

		if err != nil {
			c.String(400, "Bad Request: Num paramenter was not an integer.")
			return
		}
		if num <= 0 {
			c.String(400, "Bad Request: Num parameter must be positive.")
			return
		}

		// Dynamic array allocation
		var myWords []string
		myWords = make([]string, num)

		for i, _ := range myWords {
			myWords[i] = randChoice(words)
		}

		c.JSON(200, gin.H{"words": myWords})
	})

	r.GET("/delimiters", func(c *gin.Context) {
		c.JSON(200, gin.H(delimiters))
	})

	r.GET("/prefixes", func(c *gin.Context) {
		c.JSON(200, gin.H(prefixes))
	})

	r.GET("/suffixes", func(c *gin.Context) {
		c.JSON(200, gin.H(suffixes))
	})

	r.GET("/characters", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"delimiters": delimiters,
			"prefixes":   prefixes,
			"suffixes":   suffixes,
		})
	})

	r.GET("/about", func(c *gin.Context) {
		tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
			"templates/partials/about.html", "templates/partials/footer.html")
		if err != nil {
			c.String(500, "Internal Server Error: Error parsing templates")
			return
		}

		contextObj := gin.H{"title": "EZ Password Generator"}

		err = tmpl.Execute(c.Writer, contextObj)
		if err != nil {
			c.String(500, "Internal Server Error: Error executing compiled template")
			return
		}
	})

	r.GET("/terms", func(c *gin.Context) {
		tmpl, err := template.ParseFiles("templates/layouts/index.html", "templates/partials/head.html",
			"templates/partials/terms.html", "templates/partials/footer.html")
		if err != nil {
			c.String(500, "Internal Server Error: Error parsing templates")
			return
		}

		contextObj := gin.H{"title": "EZ Password Generator"}

		err = tmpl.Execute(c.Writer, contextObj)
		if err != nil {
			c.String(500, "Internal Server Error: Error executing compiled template")
			return
		}
	})

	r.GET("/github", func(c *gin.Context) {
		c.Redirect(301, "https://github.com/andrewyang96/GoPasswordGenerator")
	})

	/* End routes */

	// Run server
	port := os.Getenv("PORT")
	if port == "" {
		port = "8000"
	}
	r.Run(":" + port)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"flag"
	"io"
	"log"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strconv"
	"strings"
)

const MAXFUZZERS = 256
const AFLNAME = "afl-fuzz"

var (
	flagNoMaster = flag.Bool("no-master", false, "Launch all instances with -S")
	flagNum      = flag.Int("n", 1, "Number of instances to launch")
	flagName     = flag.String("name", "", "Base name for instances. Fuzzers will work in <output>/<BASE>-[M|S]<N>")
	flagTimeout  = flag.String("t", "", "afl-fuzz -t option (timeout)") // afl -t option supports a + suffix
	flagMem      = flag.Int("m", -1, "afl-fuzz -m option (memory limit)")
	flagInput    = flag.String("i", "", "afl-fuzz -i option (input location)")
	flagExtras   = flag.String("x", "", "afl-fuzz -x option (extras location)")
	flagOutput   = flag.String("o", "", "afl-fuzz -o option (output location)")
	flagFile     = flag.String("f", "", "Filename template (substituted and passed via -f)")
	flagXXX      = flag.Bool("XXX", false, "[HACK] substitute XXX in the target args with an 8 char random string [HACK]")

	subRegex = regexp.MustCompile("XXX")
)

func randomName(n int) (result string) {
	buf := make([]byte, n)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		panic(err)
	}
	for _, b := range buf {
		result += string(b%26 + 0x61)
	}
	return
}

func spawn(fuzzerName string, args []string) {

	// if the user wants to use a special location for the testfiles ( like a
	// ramdisk ) then they can provide any filename /path/to/whatever.xxx and
	// we'll sub out 'whatever' for the name of this fuzzer and keep the base
	// and the extension.
	if len(*flagFile) > 0 {
		base, _ := path.Split(*flagFile)
		ext := path.Ext(*flagFile)
		args = append(args, "-f", path.Join(base, fuzzerName+ext))
	}

	// Create a logfile for afl's stdout. Truncates any existing logfile.
	fuzzerDir := path.Join(*flagOutput, fuzzerName)
	err := os.MkdirAll(fuzzerDir, 0777)
	if err != nil {
		log.Fatalf(err.Error())
	}
	fd, err := os.Create(path.Join(fuzzerDir, "afl-launch.log"))
	if err != nil {
		log.Fatalf(err.Error())
	}
	defer fd.Close()

	args = append(args, "--")
	progArgs := flag.Args()[:]
	if *flagXXX {
		for i, elem := range progArgs {
			if subRegex.MatchString(elem) {
				progArgs[i] = subRegex.ReplaceAllString(elem, randomName(8))
			}
		}
	}
	args = append(args, progArgs...)

	cmd := exec.Command(AFLNAME, args...)
	cmd.Stdout = fd
	err = cmd.Start()
	if err != nil {
		// If this fails to start it will be OS issues like no swap or rlimit
		// or something, so it's not something we can handle gracefully. It's
		// NOT the same as the afl-fuzz process exiting because the args are
		// incorrect.
		log.Fatalf(err.Error())
	}
	cmd.Process.Release()
	log.Printf("%s %s\n", AFLNAME, strings.Join(args, " "))
}

func main() {

	flag.Parse()
	if len(flag.Args()) < 2 {
		log.Fatalf("no command to fuzz, eg: targetname @@")
	}

	// can we find afl?
	_, err := exec.LookPath(AFLNAME)
	if err != nil {
		log.Fatalf("couldn't find %s in $PATH", AFLNAME)
	}
	// sanity for n
	if *flagNum > MAXFUZZERS {
		log.Fatalf("too many fuzzers: %d", *flagNum)
	}
	// sanity for name
	if len(*flagName) > 32 {
		log.Fatalf("base name too long (%d), must be <= 32", len(*flagName))
	}

	// collect the proxy args for afl-fuzz
	baseArgs := []string{}
	for _, v := range []string{"t", "m", "i", "x", "o"} {
		f := flag.Lookup(v)
		if f != nil && f.Value.String() != f.DefValue {
			baseArgs = append(baseArgs, "-"+v, f.Value.String())
		}
	}

	baseName := *flagName
	if len(baseName) == 0 {
		baseName = randomName(5)
	}

	// first instance is a master unless indicated otherwise
	if *flagNoMaster {
		name := baseName + "-" + "S" + "0"
		spawn(name, append(baseArgs, "-S", name))
	} else {
		name := baseName + "-" + "M" + "0"
		spawn(name, append(baseArgs, "-M", name))
	}

	// launch the rest
	for i := 1; i < *flagNum; i++ {
		name := baseName + "-" + "S" + strconv.Itoa(i)
		spawn(name, append(baseArgs, "-S", name))
	}
}
<commit_msg>bug in XXX option<commit_after>package main

import (
	"crypto/rand"
	"flag"
	"io"
	"log"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strconv"
	"strings"
)

const MAXFUZZERS = 256
const AFLNAME = "afl-fuzz"

var (
	flagNoMaster = flag.Bool("no-master", false, "Launch all instances with -S")
	flagNum      = flag.Int("n", 1, "Number of instances to launch")
	flagName     = flag.String("name", "", "Base name for instances. Fuzzers will work in <output>/<BASE>-[M|S]<N>")
	flagTimeout  = flag.String("t", "", "afl-fuzz -t option (timeout)") // afl -t option supports a + suffix
	flagMem      = flag.Int("m", -1, "afl-fuzz -m option (memory limit)")
	flagInput    = flag.String("i", "", "afl-fuzz -i option (input location)")
	flagExtras   = flag.String("x", "", "afl-fuzz -x option (extras location)")
	flagOutput   = flag.String("o", "", "afl-fuzz -o option (output location)")
	flagFile     = flag.String("f", "", "Filename template (substituted and passed via -f)")
	flagXXX      = flag.Bool("XXX", false, "[HACK] substitute XXX in the target args with an 8 char random string [HACK]")

	subRegex = regexp.MustCompile("XXX")
)

func randomName(n int) (result string) {
	buf := make([]byte, n)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		panic(err)
	}
	for _, b := range buf {
		result += string(b%26 + 0x61)
	}
	return
}

func spawn(fuzzerName string, args []string) {

	// if the user wants to use a special location for the testfiles ( like a
	// ramdisk ) then they can provide any filename /path/to/whatever.xxx and
	// we'll sub out 'whatever' for the name of this fuzzer and keep the base
	// and the extension.
	if len(*flagFile) > 0 {
		base, _ := path.Split(*flagFile)
		ext := path.Ext(*flagFile)
		args = append(args, "-f", path.Join(base, fuzzerName+ext))
	}

	// Create a logfile for afl's stdout. Truncates any existing logfile.
	fuzzerDir := path.Join(*flagOutput, fuzzerName)
	err := os.MkdirAll(fuzzerDir, 0777)
	if err != nil {
		log.Fatalf(err.Error())
	}
	fd, err := os.Create(path.Join(fuzzerDir, "afl-launch.log"))
	if err != nil {
		log.Fatalf(err.Error())
	}
	defer fd.Close()

	args = append(args, "--")
	progArgs := []string{}
	copy(progArgs, flag.Args()[:])
	if *flagXXX {
		for i, elem := range progArgs {
			if subRegex.MatchString(elem) {
				progArgs[i] = subRegex.ReplaceAllString(elem, randomName(8))
			}
		}
	}
	args = append(args, progArgs...)

	cmd := exec.Command(AFLNAME, args...)
	cmd.Stdout = fd
	err = cmd.Start()
	if err != nil {
		// If this fails to start it will be OS issues like no swap or rlimit
		// or something, so it's not something we can handle gracefully. It's
		// NOT the same as the afl-fuzz process exiting because the args are
		// incorrect.
		log.Fatalf(err.Error())
	}
	cmd.Process.Release()
	log.Printf("%s %s\n", AFLNAME, strings.Join(args, " "))
}

func main() {

	flag.Parse()
	if len(flag.Args()) < 2 {
		log.Fatalf("no command to fuzz, eg: targetname @@")
	}

	// can we find afl?
	_, err := exec.LookPath(AFLNAME)
	if err != nil {
		log.Fatalf("couldn't find %s in $PATH", AFLNAME)
	}
	// sanity for n
	if *flagNum > MAXFUZZERS {
		log.Fatalf("too many fuzzers: %d", *flagNum)
	}
	// sanity for name
	if len(*flagName) > 32 {
		log.Fatalf("base name too long (%d), must be <= 32", len(*flagName))
	}

	// collect the proxy args for afl-fuzz
	baseArgs := []string{}
	for _, v := range []string{"t", "m", "i", "x", "o"} {
		f := flag.Lookup(v)
		if f != nil && f.Value.String() != f.DefValue {
			baseArgs = append(baseArgs, "-"+v, f.Value.String())
		}
	}

	baseName := *flagName
	if len(baseName) == 0 {
		baseName = randomName(5)
	}

	// first instance is a master unless indicated otherwise
	if *flagNoMaster {
		name := baseName + "-" + "S" + "0"
		spawn(name, append(baseArgs, "-S", name))
	} else {
		name := baseName + "-" + "M" + "0"
		spawn(name, append(baseArgs, "-M", name))
	}

	// launch the rest
	for i := 1; i < *flagNum; i++ {
		name := baseName + "-" + "S" + strconv.Itoa(i)
		spawn(name, append(baseArgs, "-S", name))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"os"
	"strings"
)

func main() {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, ".", isSrcFile, 0)
	if err != nil {
		fatal(err)
	}

	// TODO: ensure multiple files output into single file
	for name, p := range pkgs {
		for _, f := range p.Files {
			// ast.Print(fset, f)
			f.Decls = generateSpies(f.Decls)
			f.Name = ast.NewIdent(name + "_test")

			// TODO: Write to file instead of standard out
			printer.Fprint(os.Stdout, fset, f)
		}
	}
}

func isSrcFile(info os.FileInfo) bool {
	return !strings.HasSuffix(info.Name(), "_test.go")
}

// generateSpies transforms all the interfaces in the list of declarations
// into spies in the form of structs with implemented functions
func generateSpies(ds []ast.Decl) []ast.Decl {
	var decls []ast.Decl
	for _, d := range ds {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}

		for _, spec := range genDecl.Specs {
			typeSpec, ok := spec.(*ast.TypeSpec)
			if !ok {
				continue
			}

			interfaceType, ok := typeSpec.Type.(*ast.InterfaceType)
			if !ok {
				continue
			}

			mutatateToStruct(typeSpec, interfaceType)
			funcDecls := createSpyFuncs(typeSpec, interfaceType)

			decls = append(decls, genDecl)
			for _, fd := range funcDecls {
				decls = append(decls, fd)
			}
		}
	}
	return decls
}

// mutatateToStruct mutates the underlying interface type into a struct type
// and adds implentations of the interface's methods
func mutatateToStruct(t *ast.TypeSpec, i *ast.InterfaceType) {
	t.Name = ast.NewIdent("Fake" + t.Name.Name)

	var list []*ast.Field
	for _, field := range i.Methods.List {
		funcType, ok := field.Type.(*ast.FuncType)
		if !ok {
			continue // TODO: when would this happen?
		}

		methodName := field.Names[0].Name
		wasCalled := &ast.Field{
			Names: []*ast.Ident{ast.NewIdent(methodName + "_Called")},
			Type:  ast.NewIdent("bool"),
		}
		list = append(list, wasCalled)

		// add Input struct with params
		if len(funcType.Params.List) > 0 {
			input := buildInputStruct("Arg", methodName+"_Input", funcType.Params.List)
			list = append(list, input)
		}

		// add Output struct with return values
		if len(funcType.Results.List) > 0 {
			// for idx, result := range funcType.Results.List {
			// }
		}
	}

	t.Type = &ast.StructType{
		Fields:     &ast.FieldList{List: list},
		Incomplete: i.Incomplete,
	}
}

// buildInputStruct writes a struct type whose fields
// reflect the various input arguments defined in the interface
func buildInputStruct(prefix, fieldname string, list []*ast.Field) *ast.Field {
	var fields []*ast.Field
	var argOffset int
	var argName string

	for idx, param := range list {
		argName = fmt.Sprintf("%s%d", prefix, idx+argOffset)
		// if we have multiple args of same type,
		// add fields for each
		if len(param.Names) > 1 {
			for range param.Names {
				argName = fmt.Sprintf("%s%d", prefix, idx+argOffset)
				fields = append(fields, &ast.Field{
					Names: []*ast.Ident{ast.NewIdent(argName)},
					Type:  param.Type,
				})
				argOffset += 1
			}
		} else {
			fields = append(fields, &ast.Field{
				Names: []*ast.Ident{ast.NewIdent(argName)},
				Type:  param.Type,
			})
		}
	}
	return &ast.Field{
		Names: []*ast.Ident{ast.NewIdent(fieldname)},
		Type: &ast.StructType{
			Fields: &ast.FieldList{List: fields},
		},
	}
}

// createSpyFuncs creates spy functions which implement the methods of
// the interface type
func createSpyFuncs(t *ast.TypeSpec, i *ast.InterfaceType) []*ast.FuncDecl {
	var funcDecls []*ast.FuncDecl
	for _, list := range i.Methods.List {
		recv := &ast.FieldList{
			List: []*ast.Field{
				&ast.Field{
					Names: []*ast.Ident{ast.NewIdent("f")},
					Type:  &ast.StarExpr{X: t.Name},
				},
			},
		}

		funcType, ok := list.Type.(*ast.FuncType)
		if !ok {
			// TODO: When will this happen?
			continue
		}

		blockStmt := &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.ReturnStmt{
					Results: []ast.Expr{
						// TODO: stop hard coding these values
						&ast.BasicLit{Kind: token.INT, Value: "0"},
						ast.NewIdent("nil"),
					},
				},
			},
		}

		funcDecls = append(funcDecls, &ast.FuncDecl{
			Recv: recv,
			Name: list.Names[0],
			Type: funcType,
			Body: blockStmt,
		})
	}
	return funcDecls
}

func fatal(err error) {
	fmt.Printf("Error %v\n", err)
	os.Exit(1)
}
<commit_msg>Add fields to cover return values<commit_after>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"os"
	"strings"
)

func main() {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, ".", isSrcFile, 0)
	if err != nil {
		fatal(err)
	}

	// TODO: ensure multiple files output into single file
	for name, p := range pkgs {
		for _, f := range p.Files {
			// ast.Print(fset, f)
			f.Decls = generateSpies(f.Decls)
			f.Name = ast.NewIdent(name + "_test")

			// TODO: Write to file instead of standard out
			printer.Fprint(os.Stdout, fset, f)
		}
	}
}

func isSrcFile(info os.FileInfo) bool {
	return !strings.HasSuffix(info.Name(), "_test.go")
}

// generateSpies transforms all the interfaces in the list of declarations
// into spies in the form of structs with implemented functions
func generateSpies(ds []ast.Decl) []ast.Decl {
	var decls []ast.Decl
	for _, d := range ds {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}

		for _, spec := range genDecl.Specs {
			typeSpec, ok := spec.(*ast.TypeSpec)
			if !ok {
				continue
			}

			interfaceType, ok := typeSpec.Type.(*ast.InterfaceType)
			if !ok {
				continue
			}

			mutatateToStruct(typeSpec, interfaceType)
			funcDecls := createSpyFuncs(typeSpec, interfaceType)

			decls = append(decls, genDecl)
			for _, fd := range funcDecls {
				decls = append(decls, fd)
			}
		}
	}
	return decls
}

// mutatateToStruct mutates the underlying interface type into a struct type
// and adds implentations of the interface's methods
func mutatateToStruct(t *ast.TypeSpec, i *ast.InterfaceType) {
	t.Name = ast.NewIdent("Fake" + t.Name.Name)

	var list []*ast.Field
	for _, field := range i.Methods.List {
		funcType, ok := field.Type.(*ast.FuncType)
		if !ok {
			continue // TODO: when would this happen?
		}

		methodName := field.Names[0].Name
		wasCalled := &ast.Field{
			Names: []*ast.Ident{ast.NewIdent(methodName + "_Called")},
			Type:  ast.NewIdent("bool"),
		}
		list = append(list, wasCalled)

		// add Input struct with params
		if len(funcType.Params.List) > 0 {
			inputStruct := buildStruct("Arg", methodName+"_Input", funcType.Params.List)
			list = append(list, inputStruct)
		}

		// add Output struct with return values
		if len(funcType.Results.List) > 0 {
			outputStruct := buildStruct("Ret", methodName+"_Output", funcType.Results.List)
			list = append(list, outputStruct)
		}
	}

	t.Type = &ast.StructType{
		Fields:     &ast.FieldList{List: list},
		Incomplete: i.Incomplete,
	}
}

// buildInputStruct writes a struct type whose fields
// reflect the various input arguments defined in the interface
func buildStruct(prefix, fieldname string, list []*ast.Field) *ast.Field {
	var fields []*ast.Field
	var argOffset int
	var argName string

	for idx, param := range list {
		argName = fmt.Sprintf("%s%d", prefix, idx+argOffset)
		// if we have multiple args of same type,
		// add fields for each
		if len(param.Names) > 1 {
			for range param.Names {
				argName = fmt.Sprintf("%s%d", prefix, idx+argOffset)
				fields = append(fields, &ast.Field{
					Names: []*ast.Ident{ast.NewIdent(argName)},
					Type:  param.Type,
				})
				argOffset += 1
			}
		} else {
			fields = append(fields, &ast.Field{
				Names: []*ast.Ident{ast.NewIdent(argName)},
				Type:  param.Type,
			})
		}
	}
	return &ast.Field{
		Names: []*ast.Ident{ast.NewIdent(fieldname)},
		Type: &ast.StructType{
			Fields: &ast.FieldList{List: fields},
		},
	}
}

// createSpyFuncs creates spy functions which implement the methods of
// the interface type
func createSpyFuncs(t *ast.TypeSpec, i *ast.InterfaceType) []*ast.FuncDecl {
	var funcDecls []*ast.FuncDecl
	for _, list := range i.Methods.List {
		recv := &ast.FieldList{
			List: []*ast.Field{
				&ast.Field{
					Names: []*ast.Ident{ast.NewIdent("f")},
					Type:  &ast.StarExpr{X: t.Name},
				},
			},
		}

		funcType, ok := list.Type.(*ast.FuncType)
		if !ok {
			// TODO: When will this happen?
			continue
		}

		blockStmt := &ast.BlockStmt{
			List: []ast.Stmt{
				&ast.ReturnStmt{
					Results: []ast.Expr{
						// TODO: stop hard coding these values
						&ast.BasicLit{Kind: token.INT, Value: "0"},
						ast.NewIdent("nil"),
					},
				},
			},
		}

		funcDecls = append(funcDecls, &ast.FuncDecl{
			Recv: recv,
			Name: list.Names[0],
			Type: funcType,
			Body: blockStmt,
		})
	}
	return funcDecls
}

func fatal(err error) {
	fmt.Printf("Error %v\n", err)
	os.Exit(1)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main // import "mvdan.cc/interfacer"

import (
	"flag"
	"fmt"
	"os"

	"mvdan.cc/interfacer/check"
)

var _ = flag.Bool("v", false, "print the names of packages as they are checked")

func main() {
	flag.Parse()
	lines, err := check.CheckArgs(flag.Args())
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	for _, line := range lines {
		fmt.Println(line)
	}
}
<commit_msg>add -tags flag to set the loader's build tags<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main // import "mvdan.cc/interfacer"

import (
	"flag"
	"fmt"
	"go/build"
	"os"

	"golang.org/x/tools/go/buildutil"

	"mvdan.cc/interfacer/check"
)

func init() {
	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags",
		buildutil.TagsFlagDoc)
}

func main() {
	flag.Parse()
	lines, err := check.CheckArgs(flag.Args())
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	for _, line := range lines {
		fmt.Println(line)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"strings"
)

func listFiles(path string, includeMeta bool,
	depth int) (map[string]interface{}, error) {

	viewRes := struct {
		Rows []struct {
			Key   []string
			Value map[string]interface{}
		}
	}{}

	// use the requested path to build our view query parameters
	startKey := []string{}
	if path != "" {
		startKey = strings.Split(path, "/")
	}
	endKey := make([]string, len(startKey)+1, len(startKey)+1)
	copy(endKey, startKey)
	endKey[len(startKey)] = "ZZZZZZ" // FIXME use {} instead
	groupLevel := len(startKey) + depth

	// query the view
	err := couchbase.ViewCustom("cbfs", "file_browse",
		map[string]interface{}{
			"group_level": groupLevel,
			"start_key":   startKey,
			"end_key":     endKey,
		}, &viewRes)
	if err != nil {
		return nil, err
	}

	// use the view result to build a list of keys
	keys := make([]string, len(viewRes.Rows), len(viewRes.Rows))
	for i, r := range viewRes.Rows {
		keys[i] = strings.Join(r.Key, "/")
	}

	// do a multi-get on the all the keys returned
	bulkResult := couchbase.GetBulk(keys)

	// divide items up into files and directories
	files := map[string]interface{}{}
	dirs := map[string]interface{}{}
	for _, r := range viewRes.Rows {
		key := strings.Join(r.Key, "/")
		name := strings.Join(r.Key[len(r.Key)-depth:], "/")
		res, ok := bulkResult[key]
		if ok == true {
			// this means we have a file
			rv := map[string]interface{}{}
			err := json.Unmarshal(res.Body, &rv)
			if err != nil {
				log.Printf("Error deserializing json, ignoring: %v", err)
			} else {
				if includeMeta {
					files[name] = rv
				} else {
					files[name] = map[string]interface{}{}
				}
			}
		} else {
			// no record in the multi-get metans this is a directory
			dirs[name] = map[string]interface{}{
				"children": r.Value["count"],
				"size":     int64(r.Value["sum"].(float64)),
				"smallest": int64(r.Value["min"].(float64)),
				"largest":  int64(r.Value["max"].(float64)),
			}
		}
	}

	// assemble the final return value
	rv := map[string]interface{}{"path": "/" + path, "dirs": dirs, "files": files}

	return rv, nil
}
<commit_msg>Don't panic if some paths are shorter than our sought depth.<commit_after>package main

import (
	"encoding/json"
	"log"
	"strings"
)

func listFiles(path string, includeMeta bool,
	depth int) (map[string]interface{}, error) {

	viewRes := struct {
		Rows []struct {
			Key   []string
			Value map[string]interface{}
		}
	}{}

	// use the requested path to build our view query parameters
	startKey := []string{}
	if path != "" {
		startKey = strings.Split(path, "/")
	}
	endKey := make([]string, len(startKey)+1, len(startKey)+1)
	copy(endKey, startKey)
	endKey[len(startKey)] = "ZZZZZZ" // FIXME use {} instead
	groupLevel := len(startKey) + depth

	// query the view
	err := couchbase.ViewCustom("cbfs", "file_browse",
		map[string]interface{}{
			"group_level": groupLevel,
			"start_key":   startKey,
			"end_key":     endKey,
		}, &viewRes)
	if err != nil {
		return nil, err
	}

	// use the view result to build a list of keys
	keys := make([]string, len(viewRes.Rows), len(viewRes.Rows))
	for i, r := range viewRes.Rows {
		keys[i] = strings.Join(r.Key, "/")
	}

	// do a multi-get on the all the keys returned
	bulkResult := couchbase.GetBulk(keys)

	// divide items up into files and directories
	files := map[string]interface{}{}
	dirs := map[string]interface{}{}
	for _, r := range viewRes.Rows {
		key := strings.Join(r.Key, "/")
		subkey := r.Key
		if len(r.Key) > depth {
			subkey = r.Key[len(r.Key)-depth:]
		}
		name := strings.Join(subkey, "/")
		res, ok := bulkResult[key]
		if ok == true {
			// this means we have a file
			rv := map[string]interface{}{}
			err := json.Unmarshal(res.Body, &rv)
			if err != nil {
				log.Printf("Error deserializing json, ignoring: %v", err)
			} else {
				if includeMeta {
					files[name] = rv
				} else {
					files[name] = map[string]interface{}{}
				}
			}
		} else {
			// no record in the multi-get metans this is a directory
			dirs[name] = map[string]interface{}{
				"children": r.Value["count"],
				"size":     int64(r.Value["sum"].(float64)),
				"smallest": int64(r.Value["min"].(float64)),
				"largest":  int64(r.Value["max"].(float64)),
			}
		}
	}

	// assemble the final return value
	rv := map[string]interface{}{"path": "/" + path, "dirs": dirs, "files": files}

	return rv, nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"fmt"
	"log"
	"math/big"
	"net"
	"os"
	"path/filepath"
	"time"
)

var (
	clientN   int
	directory string
	org       string
	duration  time.Duration
	rsaBits   int
	ec        string
)

// Usage: quicktls host1 host2 host3
// Output: ca.pem host1.cert host1.key host2.cert host2.key host3.cert host3.key
// NOTE: CA key is NEVER saved to disk, this ensures safety of the ca
func main() {
	flag.IntVar(&clientN, "clients", 0, "Number of client certificates to generate")
	flag.StringVar(&directory, "o", "", "Output directory")
	flag.StringVar(&org, "org", "QuickTLS", "Organization in the certificate")
	flag.DurationVar(&duration, "exp", 1080*24*time.Hour, "Time until Certificate expiration")
	flag.IntVar(&rsaBits, "rsa", 2048, "Number of RSA bits")
	flag.StringVar(&ec, "ec", "", "Which elliptic curve key to use 224, 384, 521 (default to use RSA)")
	flag.Parse()

	hosts := flag.Args()

	caFile := filepath.Join(directory, "ca.pem")
	ca, caKey, err := generateCA(caFile)
	if err != nil {
		log.Fatal(err)
	}

	for _, host := range hosts {
		hostCert := filepath.Join(directory, fmt.Sprintf("%s.cert", host))
		hostKey := filepath.Join(directory, fmt.Sprintf("%s.key", host))
		if err := generateCert([]string{host}, hostCert, hostKey, ca, caKey); err != nil {
			log.Fatal(err)
		}
	}
	for i := 0; i < clientN; i++ {
		clientCert := filepath.Join(directory, fmt.Sprintf("client-%d.cert", i))
		clientKey := filepath.Join(directory, fmt.Sprintf("client-%d.key", i))
		if err := generateClient(clientCert, clientKey, ca, caKey); err != nil {
			log.Fatal(err)
		}
	}
}

// newCertificate creates a new template
func newCertificate() *x509.Certificate {
	notBefore := time.Now()
	notAfter := notBefore.Add(duration)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		log.Fatalf("failed to generate serial number: %s", err)
	}

	return &x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{org},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		BasicConstraintsValid: true,
	}
}

// newPrivateKey creates a new private key depending
// on the input flags
func newPrivateKey() (crypto.PrivateKey, error) {
	if ec != "" {
		var curve elliptic.Curve
		switch ec {
		case "224":
			curve = elliptic.P224()
		case "384":
			curve = elliptic.P384()
		case "521":
			curve = elliptic.P521()
		default:
			return nil, fmt.Errorf("Unknown elliptic curve: %q", ec)
		}
		return ecdsa.GenerateKey(curve, rand.Reader)
	}
	return rsa.GenerateKey(rand.Reader, rsaBits)
}

// generateCA creates a new CA certificate, saves the certificate
// and returns the x509 certificate and crypto private key. This
// private key should never be saved to disk, but rather used to
// immediately generate further certificates.
func generateCA(caFile string) (*x509.Certificate, crypto.PrivateKey, error) {
	template := newCertificate()
	template.IsCA = true
	template.KeyUsage |= x509.KeyUsageCertSign
	template.Subject.CommonName = org

	priv, err := newPrivateKey()
	if err != nil {
		return nil, nil, err
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, template, template, priv.(crypto.Signer).Public(), priv)
	if err != nil {
		return nil, nil, err
	}

	ca, err := x509.ParseCertificate(derBytes)
	if err != nil {
		return nil, nil, err
	}

	certOut, err := os.Create(caFile)
	if err != nil {
		return nil, nil, err
	}
	defer certOut.Close()
	if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
		return nil, nil, err
	}

	return ca, priv, nil
}

// generateCert generates a new certificate for the given hosts using the
// provided certificate authority. The cert and key files are stored in the
// the provided files.
func generateCert(hosts []string, certFile, keyFile string, ca *x509.Certificate, caKey crypto.PrivateKey) error {
	template := newCertificate()
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
			if template.Subject.CommonName == "" {
				template.Subject.CommonName = h
			}
		}
	}

	priv, err := newPrivateKey()
	if err != nil {
		return err
	}

	return generateFromTemplate(certFile, keyFile, template, ca, priv, caKey)
}

// generateClient gnerates a new client certificate. The cert and key files are
// stored in the provided files.
func generateClient(certFile, keyFile string, ca *x509.Certificate, caKey crypto.PrivateKey) error {
	template := newCertificate()
	template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}

	priv, err := newPrivateKey()
	if err != nil {
		return err
	}

	return generateFromTemplate(certFile, keyFile, template, ca, priv, caKey)
}

// generateFromTemplate generates a certificate from the given template and signed by
// the given parent, storing the results in a certificate and key file.
func generateFromTemplate(certFile, keyFile string, template, parent *x509.Certificate, key crypto.PrivateKey, parentKey crypto.PrivateKey) error {
	derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, key.(crypto.Signer).Public(), parentKey)
	if err != nil {
		return err
	}

	certOut, err := os.Create(certFile)
	if err != nil {
		return err
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()

	keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer keyOut.Close()

	switch v := key.(type) {
	case *rsa.PrivateKey:
		keyBytes := x509.MarshalPKCS1PrivateKey(v)
		pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyBytes})
	case *ecdsa.PrivateKey:
		keyBytes, err := x509.MarshalECPrivateKey(v)
		if err != nil {
			return err
		}
		pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes})
	default:
		return fmt.Errorf("Unsupport private key type: %#v", key)
	}

	return nil
}
<commit_msg>Add option to save CA key<commit_after>package main

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"fmt"
	"log"
	"math/big"
	"net"
	"os"
	"path/filepath"
	"time"
)

var (
	clientN   int
	directory string
	org       string
	duration  time.Duration
	rsaBits   int
	ec        string
	keepCAKey bool
)

// Usage: quicktls host1 host2 host3
// Output: ca.pem host1.cert host1.key host2.cert host2.key host3.cert host3.key
// NOTE: CA key by default is not saved to disk, this ensures integrity of the ca
func main() {
	flag.IntVar(&clientN, "clients", 0, "Number of client certificates to generate")
	flag.StringVar(&directory, "o", "", "Output directory")
	flag.StringVar(&org, "org", "QuickTLS", "Organization in the certificate")
	flag.DurationVar(&duration, "exp", 1080*24*time.Hour, "Time until Certificate expiration")
	flag.IntVar(&rsaBits, "rsa", 2048, "Number of RSA bits")
	flag.StringVar(&ec, "ec", "", "Which elliptic curve key to use 224, 384, 521 (default to use RSA)")
	flag.BoolVar(&keepCAKey, "keep-ca-key", false, "Keep CA key to generate further certificates")
	flag.Parse()

	hosts := flag.Args()

	caFile := filepath.Join(directory, "ca.pem")
	ca, caKey, err := generateCA(caFile)
	if err != nil {
		log.Fatal(err)
	}

	if keepCAKey {
		caKeyFile := filepath.Join(directory, "ca.key")
		if err := savePrivateKey(caKey, caKeyFile); err != nil {
			log.Fatal(err)
		}
	}

	for _, host := range hosts {
		hostCert := filepath.Join(directory, fmt.Sprintf("%s.cert", host))
		hostKey := filepath.Join(directory, fmt.Sprintf("%s.key", host))
		if err := generateCert([]string{host}, hostCert, hostKey, ca, caKey); err != nil {
			log.Fatal(err)
		}
	}
	for i := 0; i < clientN; i++ {
		clientCert := filepath.Join(directory, fmt.Sprintf("client-%d.cert", i))
		clientKey := filepath.Join(directory, fmt.Sprintf("client-%d.key", i))
		if err := generateClient(clientCert, clientKey, ca, caKey); err != nil {
			log.Fatal(err)
		}
	}
}

// newCertificate creates a new template
func newCertificate() *x509.Certificate {
	notBefore := time.Now()
	notAfter := notBefore.Add(duration)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		log.Fatalf("failed to generate serial number: %s", err)
	}

	return &x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{org},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		BasicConstraintsValid: true,
	}
}

// newPrivateKey creates a new private key depending
// on the input flags
func newPrivateKey() (crypto.PrivateKey, error) {
	if ec != "" {
		var curve elliptic.Curve
		switch ec {
		case "224":
			curve = elliptic.P224()
		case "384":
			curve = elliptic.P384()
		case "521":
			curve = elliptic.P521()
		default:
			return nil, fmt.Errorf("Unknown elliptic curve: %q", ec)
		}
		return ecdsa.GenerateKey(curve, rand.Reader)
	}
	return rsa.GenerateKey(rand.Reader, rsaBits)
}

// generateCA creates a new CA certificate, saves the certificate
// and returns the x509 certificate and crypto private key. This
// private key should never be saved to disk, but rather used to
// immediately generate further certificates.
func generateCA(caFile string) (*x509.Certificate, crypto.PrivateKey, error) {
	template := newCertificate()
	template.IsCA = true
	template.KeyUsage |= x509.KeyUsageCertSign
	template.Subject.CommonName = org

	priv, err := newPrivateKey()
	if err != nil {
		return nil, nil, err
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, template, template, priv.(crypto.Signer).Public(), priv)
	if err != nil {
		return nil, nil, err
	}

	ca, err := x509.ParseCertificate(derBytes)
	if err != nil {
		return nil, nil, err
	}

	certOut, err := os.Create(caFile)
	if err != nil {
		return nil, nil, err
	}
	defer certOut.Close()
	if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
		return nil, nil, err
	}

	return ca, priv, nil
}

// generateCert generates a new certificate for the given hosts using the
// provided certificate authority. The cert and key files are stored in the
// the provided files.
func generateCert(hosts []string, certFile, keyFile string, ca *x509.Certificate, caKey crypto.PrivateKey) error {
	template := newCertificate()
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
			if template.Subject.CommonName == "" {
				template.Subject.CommonName = h
			}
		}
	}

	priv, err := newPrivateKey()
	if err != nil {
		return err
	}

	return generateFromTemplate(certFile, keyFile, template, ca, priv, caKey)
}

// generateClient gnerates a new client certificate. The cert and key files are
// stored in the provided files.
func generateClient(certFile, keyFile string, ca *x509.Certificate, caKey crypto.PrivateKey) error {
	template := newCertificate()
	template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}

	priv, err := newPrivateKey()
	if err != nil {
		return err
	}

	return generateFromTemplate(certFile, keyFile, template, ca, priv, caKey)
}

// generateFromTemplate generates a certificate from the given template and signed by
// the given parent, storing the results in a certificate and key file.
func generateFromTemplate(certFile, keyFile string, template, parent *x509.Certificate, key crypto.PrivateKey, parentKey crypto.PrivateKey) error {
	derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, key.(crypto.Signer).Public(), parentKey)
	if err != nil {
		return err
	}

	certOut, err := os.Create(certFile)
	if err != nil {
		return err
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()

	return savePrivateKey(key, keyFile)
}

// savePrivateKey saves the private key to a PEM file
func savePrivateKey(key crypto.PrivateKey, keyFile string) error {
	keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer keyOut.Close()

	switch v := key.(type) {
	case *rsa.PrivateKey:
		keyBytes := x509.MarshalPKCS1PrivateKey(v)
		pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyBytes})
	case *ecdsa.PrivateKey:
		keyBytes, err := x509.MarshalECPrivateKey(v)
		if err != nil {
			return err
		}
		pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes})
	default:
		return fmt.Errorf("Unsupport private key type: %#v", key)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	// "database/sql"
	"encoding/json"
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/nu7hatch/gouuid"
	apns "github.com/sideshow/apns2"
	"github.com/sideshow/apns2/certificate"
)

var db *sqlx.DB
var apnsClient *apns.Client

type User struct {
	Id       string `json:"id" db:"id"`
	Email    string `json:"email" db:"email"`
	Password string `json:"password" db:"password"`
}

type Notification struct {
	Id      string `json:"id" db:"id"`
	Message string `json:"message" db:"message"`
	UserId  string `json:"user_id" db:"user_id"`
}

type Token struct {
	Id     string `json:"id" db:"id"`
	Token  string `json:"token" db:"token"`
	UserId string `json:"user_id" db:"user_id"`
	Status bool   `json:"status" db:"status"`
}

func DBConnection() *sqlx.DB {
	dbURL := os.Getenv("DATABASE_URL")

	if dbURL == "" {
		log.Fatal("$DATABASE_URL environment variable must be set")
	} else {
		fmt.Println("Connected to database: " + dbURL)
	}

	db, err := sqlx.Connect("postgres", dbURL)
	if err != nil {
		log.Fatal(err)
	}

	return db
}

func APNSConnection() *apns.Client {
	// TODO: This should be done through configuration
	cert, err := certificate.FromPemFile("cert.cer", "")
	if err != nil {
		log.Fatal(err)
	}

	return apns.NewClient(cert).Production()
}

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		log.Fatal("$PORT environment variable must be set")
	} else {
		fmt.Println("Running on port: " + port)
	}

	db = DBConnection()
	apnsClient = APNSConnection()
	router := mux.NewRouter().StrictSlash(true)

	router.HandleFunc("/", Index)
	router.HandleFunc("/login", UserLogin).Methods("POST")
	router.HandleFunc("/tokens", CreateToken).Methods("POST")
	router.HandleFunc("/notifications", CreateNotification).Methods("POST")
	router.HandleFunc("/users/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}/notifications", ListUserNotifications).Methods("GET")

	log.Fatal(http.ListenAndServe(":"+port, router))
}

/// UserLogin will register a user with the service so that they can receive notifications
func UserLogin(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var user User

	err := decoder.Decode(&user)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	user.Id = id.String()
	query := "INSERT INTO \"user\" (id, email, password) VALUES (:id, :email, :password)"
	_, err = db.NamedExec(query, &user)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(user)

	w.Write(jsonString)
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "OK")
}

func ListUserNotifications(w http.ResponseWriter, r *http.Request) {
	// Get all notifications for user
	vars := mux.Vars(r)
	id, _ := vars["id"]
	query := `SELECT id, message, user_id FROM notification WHERE user_id = $1`

	fmt.Printf("User ID %v", id)

	var notifications []*Notification

	db.Select(&notifications, query, id)
	fmt.Printf("Notifications: %v", notifications)
	w.Header().Set("Content-Type", "application/json")

	jsonString, _ := json.Marshal(notifications)

	w.Write(jsonString)
}

func CreateNotification(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var notification Notification

	err := decoder.Decode(&notification)
	if err != nil {
		log.Fatal(err)
	}

	// TODO: Get user's token
	token := getActiveTokenForUserId(notification.UserId)

	// Send notification to APNS server
	apnsNotification := &apns.Notification{}
	apnsNotification.DeviceToken = token.Token
	apnsNotification.Topic = "com.sideshow.Apns2"
	apnsNotification.Payload = []byte(`{"aps":{"alert":"Hello!"}}`) // See Payload section below

	res, err := apnsClient.Push(apnsNotification)

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

	log.Println("APNs ID:", res.ApnsID)

	u, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	notification.Id = u.String()
	query := "INSERT INTO notification (id, message, user_id) VALUES (:id, :message, :user_id)"
	_, err = db.NamedExec(query, &notification)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(notification)

	// TODO: Make call to Apple Servers to broadcast notification to user's device

	w.Write(jsonString)

}

func CreateToken(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var token Token

	err := decoder.Decode(&token)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	token.Id = id.String()
	query := "INSERT INTO token (id, token, user_id, status) VALUES (:id, :token, :user_id, :status)"
	_, err = db.NamedExec(query, &token)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(token)

	w.Write(jsonString)
}

func getUserById(userId string) *User {
	var user User
	query := "SELECT * FROM \"user\" WHERE id = $1"

	err := db.Get(&user, query, userId)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("User with id: %v", user)

	return &user
}

func getActiveTokenForUserId(userId string) *Token {
	var token Token
	query := "SELECT * FROM token WHERE user_id = $1 AND status = TRUE"

	err := db.Get(&token, query, userId)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Token for user", token)

	return &token
}
<commit_msg>use .p12 instead of PEM<commit_after>package main

import (
	// "database/sql"
	"encoding/json"
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/nu7hatch/gouuid"
	apns "github.com/sideshow/apns2"
	"github.com/sideshow/apns2/certificate"
)

var db *sqlx.DB
var apnsClient *apns.Client

type User struct {
	Id       string `json:"id" db:"id"`
	Email    string `json:"email" db:"email"`
	Password string `json:"password" db:"password"`
}

type Notification struct {
	Id      string `json:"id" db:"id"`
	Message string `json:"message" db:"message"`
	UserId  string `json:"user_id" db:"user_id"`
}

type Token struct {
	Id     string `json:"id" db:"id"`
	Token  string `json:"token" db:"token"`
	UserId string `json:"user_id" db:"user_id"`
	Status bool   `json:"status" db:"status"`
}

const banner = `
(_______|_______|_)     (_______|_____ (_______) _____)
 _   ___ _     _ _       _____   _____) )  _  ( (____
| | (_  | |   | | |     |  ___) |  __  /  | |  \____ \
| |___) | |___| | |_____| |_____| |  \ \  | |  _____) )
 \_____/ \_____/|_______)_______)_|   |_| |_| (______/
`

func DBConnection() *sqlx.DB {
	dbURL := os.Getenv("DATABASE_URL")

	if dbURL == "" {
		log.Fatal("$DATABASE_URL environment variable must be set")
	} else {
		fmt.Println("Connected to database: " + dbURL)
	}

	db, err := sqlx.Connect("postgres", dbURL)
	if err != nil {
		log.Fatal(err)
	}

	return db
}

func APNSConnection() *apns.Client {
	// TODO: This should be done through configuration
	cert, err := certificate.FromP12File("devPush.p12", "aaaaaaaaAA$%")
	if err != nil {
		log.Fatal(err)
	}

	return apns.NewClient(cert).Production()
}

func main() {
	port := os.Getenv("PORT")

	if port == "" {
		log.Fatal("$PORT environment variable must be set")
	} else {
		fmt.Println("Running on port: " + port)
	}

	db = DBConnection()
	apnsClient = APNSConnection()
	router := mux.NewRouter().StrictSlash(true)

	router.HandleFunc("/", Index)
	router.HandleFunc("/login", UserLogin).Methods("POST")
	router.HandleFunc("/tokens", CreateToken).Methods("POST")
	router.HandleFunc("/notifications", CreateNotification).Methods("POST")
	router.HandleFunc("/users/{id:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}/notifications", ListUserNotifications).Methods("GET")

	log.Fatal(http.ListenAndServe(":"+port, router))
}

/// UserLogin will register a user with the service so that they can receive notifications
func UserLogin(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var user User

	err := decoder.Decode(&user)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	user.Id = id.String()
	query := "INSERT INTO \"user\" (id, email, password) VALUES (:id, :email, :password)"
	_, err = db.NamedExec(query, &user)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(user)

	w.Write(jsonString)
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "OK")
}

func ListUserNotifications(w http.ResponseWriter, r *http.Request) {
	// Get all notifications for user
	vars := mux.Vars(r)
	id, _ := vars["id"]
	query := `SELECT id, message, user_id FROM notification WHERE user_id = $1`

	fmt.Printf("User ID %v", id)

	var notifications []*Notification

	db.Select(&notifications, query, id)
	fmt.Printf("Notifications: %v", notifications)
	w.Header().Set("Content-Type", "application/json")

	jsonString, _ := json.Marshal(notifications)

	w.Write(jsonString)
}

func CreateNotification(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var notification Notification

	err := decoder.Decode(&notification)
	if err != nil {
		log.Fatal(err)
	}

	// TODO: Get user's token
	token := getActiveTokenForUserId(notification.UserId)

	// Send notification to APNS server
	apnsNotification := &apns.Notification{}
	apnsNotification.DeviceToken = token.Token
	apnsNotification.Topic = "com.sideshow.Apns2"
	apnsNotification.Payload = []byte(`{"aps":{"alert":"Hello!"}}`) // See Payload section below

	res, err := apnsClient.Push(apnsNotification)

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

	log.Println("APNs ID:", res.ApnsID)

	u, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	notification.Id = u.String()
	query := "INSERT INTO notification (id, message, user_id) VALUES (:id, :message, :user_id)"
	_, err = db.NamedExec(query, &notification)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(notification)

	// TODO: Make call to Apple Servers to broadcast notification to user's device

	w.Write(jsonString)

}

func CreateToken(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var token Token

	err := decoder.Decode(&token)
	if err != nil {
		log.Fatal(err)
	}

	id, err := uuid.NewV4()
	if err != nil {
		log.Fatal(err)
	}

	token.Id = id.String()
	query := "INSERT INTO token (id, token, user_id, status) VALUES (:id, :token, :user_id, :status)"
	_, err = db.NamedExec(query, &token)
	if err != nil {
		log.Fatal(err)
	}

	jsonString, _ := json.Marshal(token)

	w.Write(jsonString)
}

func getUserById(userId string) *User {
	var user User
	query := "SELECT * FROM \"user\" WHERE id = $1"

	err := db.Get(&user, query, userId)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("User with id: %v", user)

	return &user
}

func getActiveTokenForUserId(userId string) *Token {
	var token Token
	query := "SELECT * FROM token WHERE user_id = $1 AND status = TRUE"

	err := db.Get(&token, query, userId)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Token for user", token)

	return &token
}
<|endoftext|>


<commit_before>package golist

import (
	"errors"
	"fmt"
	"reflect"
	"sync"
)

type List struct {
	data   []interface{}
	locker sync.Mutex
}

var (
	EmptyListError  = "%v operation from empty list"
	OutOfRangeError = "%s index out of range"
)

// Returns a new List
func New(items ...interface{}) List {

	list := List{data: []interface{}{}}

	if len(items) > 0 {
		list.Append(items...)
	}

	return list
}

// Adds an item to the end of the list data
func (l *List) Append(items ...interface{}) {
	l.locker.Lock()
	l.data = append(l.data, items...)
	l.locker.Unlock()

}

// Extend the list by appending all the items in te given list.
func (l *List) Extend(target_list List) {
	l.locker.Lock()
	for _, value := range target_list.data {
		l.data = append(l.data, value)
	}
	l.locker.Unlock()

}

// Returns the length of the list
func (l *List) Len() int {
	return len(l.data)
}

// Insert an item at a given position.
// The first argument is the index of the element before which to insert
func (l *List) Insert(index int, value interface{}) {

	// Resize list to size(list) + 1 to get free space for new element.
	l.locker.Lock()
	size := l.Len()
	l.locker.Unlock()
	l.Append(value)

	if size+1 >= index {

		for i := size - 1; i >= 0; i-- {

			if index == i {
				l.locker.Lock()
				l.data[i+1] = l.data[i]
				l.data[index] = value
				l.locker.Unlock()
				break
			} else {
				l.locker.Lock()
				l.data[i+1] = l.data[i]
				l.locker.Unlock()
			}

		}
	}
}

// Remove the first item from the list whose value is x.
// Returns an error if there is no such item exists.
func (l *List) Remove(value interface{}) error {

	error_text := fmt.Sprintf("'%v' is not in list", value)
	for index, data_value := range l.data {
		if data_value == value {
			l.locker.Lock()
			l.data = append(l.data[:index], l.data[index+1:]...)
			l.locker.Unlock()
			return nil
		}
	}

	return errors.New(error_text)

}

// Remove the index at the given position in the list, and return it.
// If no index is specified, removes and returns the last item in the list.
func (l *List) Pop(index ...interface{}) (interface{}, error) {

	l.locker.Lock()
	list_size := l.Len()
	l.locker.Unlock()

	if list_size == 0 {
		return nil, errors.New(fmt.Sprintf(EmptyListError, "Pop"))
	}

	var value interface{}
	var delete_index int

	if len(index) == 0 {

		l.locker.Lock()
		value = l.data[list_size-1]

		delete_index = list_size - 1
		l.locker.Unlock()

	} else {
		l.locker.Lock()
		_index := reflect.ValueOf(index[0]).Int()

		if int(_index) > list_size-1 {
			return nil, errors.New(fmt.Sprintf(OutOfRangeError, "Pop"))
		}

		value = l.data[_index]

		delete_index = int(_index)
		l.locker.Unlock()

	}

	error := l.Delete(delete_index)

	if error != nil {
		return nil, error
	}

	return value, nil

}

// Delete the item at the given position in the list.
func (l *List) Delete(index int) error {

	list_size := l.Len()

	if list_size == 0 {
		return errors.New(fmt.Sprintf(EmptyListError, "Delete"))
	}

	if index > list_size-1 {
		return errors.New(fmt.Sprintf(OutOfRangeError, "Delete"))
	}

	l.locker.Lock()
	l.data = append(l.data[:index], l.data[index+1:]...)
	l.locker.Unlock()
	return nil

}

// Returns the index in the list of the first item whose value is x. It is an error if there is no such item.
func (l *List) Index(value interface{}) (int, error) {

	list_size := l.Len()

	if list_size == 0 {
		return 0, errors.New(fmt.Sprintf(EmptyListError, "Index"))
	}

	for index, data_value := range l.data {
		if data_value == value {
			return index, nil
		}
	}

	error_text := fmt.Sprintf("'%v' is not in list", value)

	return 0, errors.New(error_text)

}

// Return the number of times x appears in the list.
func (l *List) Count(value interface{}) int {
	total_count := 0

	l.locker.Lock()

	for _, data_value := range l.data {
		if data_value == value {
			total_count++
		}
	}

	l.locker.Unlock()

	return total_count

}

// Reverse the elements of the list, in place.
func (l *List) Reverse() {

	l.locker.Lock()
	list_size := l.Len()
	l.locker.Unlock()

	if list_size > 0 {
		top_index := list_size - 1
		l.locker.Lock()
		for index := 0; index < (top_index/2)+1; index++ {
			l.locker.Lock()
			l.data[index], l.data[top_index-index] = l.data[top_index-index], l.data[index]
			l.locker.Unlock()
		}
		l.locker.Unlock()

	}

}
<commit_msg>remove thread safety effort.<commit_after>package golist

import (
	"errors"
	"fmt"
	"reflect"
)

type List struct {
	data []interface{}
}

var (
	EmptyListError  = "%v operation from empty list"
	OutOfRangeError = "%s index out of range"
)

// Returns a new List
func New(items ...interface{}) List {

	list := List{data: []interface{}{}}

	if len(items) > 0 {
		list.Append(items...)
	}

	return list
}

// Adds an item to the end of the list data
func (l *List) Append(items ...interface{}) {
	l.data = append(l.data, items...)

}

// Extend the list by appending all the items in te given list.
func (l *List) Extend(target_list List) {
	for _, value := range target_list.data {
		l.data = append(l.data, value)
	}

}

// Returns the length of the list
func (l *List) Len() int {
	return len(l.data)
}

// Insert an item at a given position.
// The first argument is the index of the element before which to insert
func (l *List) Insert(index int, value interface{}) {

	// Resize list to size(list) + 1 to get free space for new element.
	size := l.Len()
	l.Append(value)

	if size+1 >= index {

		for i := size - 1; i >= 0; i-- {

			if index == i {
				l.data[i+1] = l.data[i]
				l.data[index] = value
				break
			} else {
				l.data[i+1] = l.data[i]
			}

		}
	}
}

// Remove the first item from the list whose value is x.
// Returns an error if there is no such item exists.
func (l *List) Remove(value interface{}) error {

	error_text := fmt.Sprintf("'%v' is not in list", value)
	for index, data_value := range l.data {
		if data_value == value {
			l.data = append(l.data[:index], l.data[index+1:]...)
			return nil
		}
	}

	return errors.New(error_text)

}

// Remove the index at the given position in the list, and return it.
// If no index is specified, removes and returns the last item in the list.
func (l *List) Pop(index ...interface{}) (interface{}, error) {

	list_size := l.Len()

	if list_size == 0 {
		return nil, errors.New(fmt.Sprintf(EmptyListError, "Pop"))
	}

	var value interface{}
	var delete_index int

	if len(index) == 0 {

		value = l.data[list_size-1]

		delete_index = list_size - 1

	} else {
		_index := reflect.ValueOf(index[0]).Int()

		if int(_index) > list_size-1 {
			return nil, errors.New(fmt.Sprintf(OutOfRangeError, "Pop"))
		}

		value = l.data[_index]

		delete_index = int(_index)

	}

	error := l.Delete(delete_index)

	if error != nil {
		return nil, error
	}

	return value, nil

}

// Delete the item at the given position in the list.
func (l *List) Delete(index int) error {

	list_size := l.Len()

	if list_size == 0 {
		return errors.New(fmt.Sprintf(EmptyListError, "Delete"))
	}

	if index > list_size-1 {
		return errors.New(fmt.Sprintf(OutOfRangeError, "Delete"))
	}

	l.data = append(l.data[:index], l.data[index+1:]...)
	return nil

}

// Returns the index in the list of the first item whose value is x. It is an error if there is no such item.
func (l *List) Index(value interface{}) (int, error) {

	list_size := l.Len()

	if list_size == 0 {
		return 0, errors.New(fmt.Sprintf(EmptyListError, "Index"))
	}

	for index, data_value := range l.data {
		if data_value == value {
			return index, nil
		}
	}

	error_text := fmt.Sprintf("'%v' is not in list", value)

	return 0, errors.New(error_text)

}

// Return the number of times x appears in the list.
func (l *List) Count(value interface{}) int {
	total_count := 0

	for _, data_value := range l.data {
		if data_value == value {
			total_count++
		}
	}

	return total_count

}

// Reverse the elements of the list, in place.
func (l *List) Reverse() {

	list_size := l.Len()

	if list_size > 0 {
		top_index := list_size - 1
		for index := 0; index < (top_index/2)+1; index++ {
			l.data[index], l.data[top_index-index] = l.data[top_index-index], l.data[index]
		}

	}

}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"time"
)

const (
	indexHTML = `<!DOCTYPE html>

		<title>Welcome to my service</title>

Welcome!

A simple app using for examining telemetry options.

Overview

This is a toy application which makes calls to upstream services.

The upstream services might fail, or take a while to respond. This gives us "interesting" data to capture and then report on.

Responses

					{{range .}}

							{{.Key}} : {{.Value}}

					{{end}}

Support links

Source

Built by James Abley

`
)

type backend struct {
	server  *http.Server
	address string
	name    string
}

// KeyValue makes the ENV vars into a first-class data structure
type KeyValue struct {
	Key   string
	Value string
}

// KeyValues is a shorter way of referencing an array
type KeyValues []*KeyValue

var (
	tmpl                = template.Must(template.New("index.html").Parse(indexHTML))
	backendServiceNames = []string{
		"Navigation",
		"Content",
		"Search",
		"Product",
		"Price",
		"Shipping",
		"Identity",
		"Customer",
		"Basket",
		"Order",
	}
)

func main() {
	flag.Parse()

	port := getDefaultConfig("PORT", "8080")

	errorChan := make(chan error, 1)

	backends := newBackends(errorChan)

	serveMux := http.NewServeMux()

	serveMux.HandleFunc("/", mainHandler(backends))
	serveMux.HandleFunc("/_status", statusHandler)

	srv := newServer(serveMux)

	signalChan := make(chan os.Signal, 1)

	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		listener, err := newListener(port)
		if err != nil {
			errorChan <- err
			return
		}
		errorChan <- srv.Serve(listener)
	}()

	for {
		select {
		case err := <-errorChan:
			if err != nil {
				log.Fatal(err)
			}
		case s := <-signalChan:
			log.Println(fmt.Sprintf("Captured %v. Exiting ...", s))
			d := time.Now().Add(1 * time.Second)
			ctx, cancel := context.WithDeadline(context.Background(), d)
			defer cancel()
			srv.Shutdown(ctx)
			for _, b := range backends {
				b.server.Shutdown(ctx)
			}
			os.Exit(0)
		}
	}
}

func newBackends(errorChan chan<- error) []backend {
	backends := make([]backend, 10)

	for i := range backends {
		serveMux := http.NewServeMux()
		serveMux.HandleFunc("/", unreliableHandler(rand.Intn(5)+1))
		server := newServer(serveMux)
		listener, err := newListener("0")

		if err != nil {
			panic(err)
		}

		go func() {
			errorChan <- server.Serve(listener)
		}()

		backends[i] = backend{
			server:  server,
			address: listener.Addr().String(),
			name:    backendName(i),
		}
	}

	return backends
}

func backendName(i int) string {
	nameLen := len(backendServiceNames)
	return fmt.Sprintf("%s_%d", backendServiceNames[i%nameLen], i%nameLen)
}

func newListener(port string) (net.Listener, error) {
	return net.Listen("tcp", "0.0.0.0:"+port)
}

func newServer(serveMux http.Handler) *http.Server {
	return &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  120 * time.Second,
		Handler:      serveMux,
	}
}

func getDefaultConfig(name, fallback string) string {
	if val := os.Getenv(name); val != "" {
		return val
	}
	return fallback
}

func mainHandler(backends []backend) http.HandlerFunc {
	client := &http.Client{}

	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Frontend received request\n")

		results := make(chan KeyValue, len(backends))

		var wg sync.WaitGroup

		for _, b := range backends {
			wg.Add(1)

			go func(b backend, results chan<- KeyValue) {
				defer wg.Done()

				fmt.Printf("Sending request to backend %s\n", b.name)

				res, err := client.Get("http://" + b.address)

				fmt.Printf("Received response from backend %s\n", b.name)

				if err != nil {
					results <- KeyValue{b.name, err.Error()}
				} else {
					defer res.Body.Close()
					results <- KeyValue{b.name, res.Status}
				}
			}(b, results)
		}

		wg.Wait()

		values := make([]KeyValue, len(backends))
		for i := range values {
			values[i] = <-results
		}

		w.Header().Set("Content-Type", "text/html; charset=UTF-8")
		w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")

		if err := tmpl.Execute(w, values); err != nil {
			panic(err)
		}
	}
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")
	w.WriteHeader(http.StatusOK)
	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)
	json.NewEncoder(w).Encode(mem)
}

func unreliableHandler(percentageFailures int) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Backend received request\n")

		if rand.Intn(100) < percentageFailures {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{
  "errors": [
    {
      "status": "400",
      "source": { "pointer": "/data/attributes/first-name" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}`))
		} else {
			w.WriteHeader(http.StatusOK)
			w.Write([]byte(`{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}`))
		}
	}
}

func getKeyValues() KeyValues {
	result := make(KeyValues, 2)
	result[0] = &KeyValue{"PORT", os.Getenv("PORT")}
	result[1] = &KeyValue{"PROVIDER", os.Getenv("PROVIDER")}
	return result
}

func newKeyValue(kv string) *KeyValue {
	s := strings.Split(kv, "=")
	return &KeyValue{Key: s[0], Value: s[1]}
}
<commit_msg>Remove unused code<commit_after>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"sync"
	"syscall"
	"time"
)

const (
	indexHTML = `<!DOCTYPE html>

		<title>Welcome to my service</title>

Welcome!

A simple app using for examining telemetry options.

Overview

This is a toy application which makes calls to upstream services.

The upstream services might fail, or take a while to respond. This gives us "interesting" data to capture and then report on.

Responses

					{{range .}}

							{{.Key}} : {{.Value}}

					{{end}}

Support links

Source

Built by James Abley

`
)

type backend struct {
	server  *http.Server
	address string
	name    string
}

// KeyValue makes the ENV vars into a first-class data structure
type KeyValue struct {
	Key   string
	Value string
}

// KeyValues is a shorter way of referencing an array
type KeyValues []*KeyValue

var (
	tmpl                = template.Must(template.New("index.html").Parse(indexHTML))
	backendServiceNames = []string{
		"Navigation",
		"Content",
		"Search",
		"Product",
		"Price",
		"Shipping",
		"Identity",
		"Customer",
		"Basket",
		"Order",
	}
)

func main() {
	flag.Parse()

	port := getDefaultConfig("PORT", "8080")

	errorChan := make(chan error, 1)

	backends := newBackends(errorChan)

	serveMux := http.NewServeMux()

	serveMux.HandleFunc("/", mainHandler(backends))
	serveMux.HandleFunc("/_status", statusHandler)

	srv := newServer(serveMux)

	signalChan := make(chan os.Signal, 1)

	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		listener, err := newListener(port)
		if err != nil {
			errorChan <- err
			return
		}
		errorChan <- srv.Serve(listener)
	}()

	for {
		select {
		case err := <-errorChan:
			if err != nil {
				log.Fatal(err)
			}
		case s := <-signalChan:
			log.Println(fmt.Sprintf("Captured %v. Exiting ...", s))
			d := time.Now().Add(1 * time.Second)
			ctx, cancel := context.WithDeadline(context.Background(), d)
			defer cancel()
			srv.Shutdown(ctx)
			for _, b := range backends {
				b.server.Shutdown(ctx)
			}
			os.Exit(0)
		}
	}
}

func newBackends(errorChan chan<- error) []backend {
	backends := make([]backend, 10)

	for i := range backends {
		serveMux := http.NewServeMux()
		serveMux.HandleFunc("/", unreliableHandler(rand.Intn(5)+1))
		server := newServer(serveMux)
		listener, err := newListener("0")

		if err != nil {
			panic(err)
		}

		go func() {
			errorChan <- server.Serve(listener)
		}()

		backends[i] = backend{
			server:  server,
			address: listener.Addr().String(),
			name:    backendName(i),
		}
	}

	return backends
}

func backendName(i int) string {
	nameLen := len(backendServiceNames)
	return fmt.Sprintf("%s_%d", backendServiceNames[i%nameLen], i%nameLen)
}

func newListener(port string) (net.Listener, error) {
	return net.Listen("tcp", "0.0.0.0:"+port)
}

func newServer(serveMux http.Handler) *http.Server {
	return &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  120 * time.Second,
		Handler:      serveMux,
	}
}

func getDefaultConfig(name, fallback string) string {
	if val := os.Getenv(name); val != "" {
		return val
	}
	return fallback
}

func mainHandler(backends []backend) http.HandlerFunc {
	client := &http.Client{}

	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Frontend received request\n")

		results := make(chan KeyValue, len(backends))

		var wg sync.WaitGroup

		for _, b := range backends {
			wg.Add(1)

			go func(b backend, results chan<- KeyValue) {
				defer wg.Done()

				fmt.Printf("Sending request to backend %s\n", b.name)

				res, err := client.Get("http://" + b.address)

				fmt.Printf("Received response from backend %s\n", b.name)

				if err != nil {
					results <- KeyValue{b.name, err.Error()}
				} else {
					defer res.Body.Close()
					results <- KeyValue{b.name, res.Status}
				}
			}(b, results)
		}

		wg.Wait()

		values := make([]KeyValue, len(backends))
		for i := range values {
			values[i] = <-results
		}

		w.Header().Set("Content-Type", "text/html; charset=UTF-8")
		w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")

		if err := tmpl.Execute(w, values); err != nil {
			panic(err)
		}
	}
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "private, no-cache, no-store, must-revalidate")
	w.WriteHeader(http.StatusOK)
	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)
	json.NewEncoder(w).Encode(mem)
}

func unreliableHandler(percentageFailures int) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Backend received request\n")

		if rand.Intn(100) < percentageFailures {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{
  "errors": [
    {
      "status": "400",
      "source": { "pointer": "/data/attributes/first-name" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}`))
		} else {
			w.WriteHeader(http.StatusOK)
			w.Write([]byte(`{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}`))
		}
	}
}
<|endoftext|>


<commit_before>// $ go get -u all
package main

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

type Msg struct {
	hostname string
	stdout   string
	stderr   string
	err      error
}

var responseChannel = make(chan *Msg, 10)

func executeCmd(index int, hostname string) {
	resp, err := http.Get(fmt.Sprint("http://www.", hostname))
	//	if err != nil {
	//		fmt.Println(err)
	//		return ""
	//	}
	defer resp.Body.Close()

	responseChannel <- &Msg{err: err, hostname: fmt.Sprint(index, "] ", hostname, ": ", resp.Status)}
	//	return fmt.Sprint(index, "] ", hostname, ": ", resp.Status)

	//	body, err := ioutil.ReadAll(resp.Body)
	//	if err != nil {
	//		fmt.Println(err)
	//		return ""
	//	}
	//	return string(body)
}

func start() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Println("NumCPU", runtime.NumCPU())
	hosts := []string{
		"vk.ru",
		"apriori-vk.ru",
		"delioro.ru",
		"shokoladki.ru",
		"chocolatevk.ru",
		"shokoeshka.com",
	} //os.Args[2:]
	// записываем результаты в буфферизированный список

	//	results := make(chan string, 10)
	// через 5 сек в канал timeout придет сообщение
	timeout := time.After(time.Second * 5)
	timeStart := time.Now()
	// запускаем по одной goroutine на сервер
	for index, hostname := range hosts {
		//		fmt.Println(index)
		go executeCmd(index, hostname)
		//		fmt.Println(executeCmd(index, hostname))
	}
	// соберем результаты со всех серверов или напишем "Время вышло"
	for i := 0; i < len(hosts); i++ {
		select {
		case msg := <-responseChannel:
			fmt.Println(msg.hostname)
		case <-timeout:
			fmt.Println("Time out")
			return
		}
	}
	timeTotal := time.Since(timeStart)
	fmt.Println(timeTotal) // 564.789389ms / 3.861487534s
}

func main() {
	start()
}
<commit_msg>Add data as *Msg.<commit_after>// $ go get -u all
package main

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

type Msg struct {
	hostname string
	stdout   string
	stderr   string
	err      error
}

var responseChannel = make(chan *Msg, 10)

func executeCmd(index int, hostname string, data *Msg) {
	resp, err := http.Get(fmt.Sprint("http://www.", hostname))
	//	if err != nil {
	//		fmt.Println(err)
	//		return ""
	//	}
	defer resp.Body.Close()

	responseChannel <- &Msg{err: err, hostname: fmt.Sprint(data.hostname, "] ", hostname, ": ", resp.Status)}
	//	return fmt.Sprint(index, "] ", hostname, ": ", resp.Status)

	//	body, err := ioutil.ReadAll(resp.Body)
	//	if err != nil {
	//		fmt.Println(err)
	//		return ""
	//	}
	//	return string(body)
}

var list = []Msg{{}}

func start() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Println("NumCPU", runtime.NumCPU())
	hosts := []string{
		"vk.ru",
		"apriori-vk.ru",
		"delioro.ru",
		"shokoladki.ru",
		"chocolatevk.ru",
		"shokoeshka.com",
	} //os.Args[2:]
	// записываем результаты в буфферизированный список

	//	results := make(chan string, 10)
	// через 5 сек в канал timeout придет сообщение
	timeout := time.After(time.Second * 5)
	timeStart := time.Now()
	// запускаем по одной goroutine на сервер
	for index, hostname := range hosts {
		//		fmt.Println(index)
		list[index].hostname = fmt.Sprint(index)
		//		conv.Data.SessionID = fmt.Sprint(index)
		go executeCmd(index, hostname, &list[index])
		list = append(list, Msg{})
		//		fmt.Println(executeCmd(index, hostname))
	}
	// соберем результаты со всех серверов или напишем "Время вышло"
	for i := 0; i < len(hosts); i++ {
		select {
		case msg := <-responseChannel:
			fmt.Println(msg.hostname)
		case <-timeout:
			fmt.Println("Time out")
			return
		}
	}
	timeTotal := time.Since(timeStart)
	fmt.Println(timeTotal) // 564.789389ms / 3.861487534s
}

func main() {
	start()
}
<|endoftext|>