<commit_before>// Simple implementation of the raft concensus algorithm using golang rpc
// Cody Malick and Jacob Broderick
package main

import (
  "fmt"
  "net"
  "net/rpc"
  "strconv"
  "log"
  "net/http"
)

type Log struct {
	Item  int
	Epoch int
}

type Message struct {
	Source      int
	Destination int
  Value       int
}

type Server struct {
	Id    int
	Epoch int
	Log   []Log
  Port  int
}

func (t *Server) Respond(message *Message, reply *Message) error {
  message.Value += 1
  *reply = *message
  return nil
}

const (
	numServers = 5
)
// Reference: https://golang.org/pkg/net/rpc/
func spawnServer(server Server) {
  fmt.Println(server.Id)
  fmt.Println(server.Port)
  rpc.Register(server.Id)
  rpc.HandleHTTP()
  listen, err := net.Listen("tcp", ":" + strconv.Itoa(server.Port))
  if err != nil {
	   log.Fatal("listen error:", err)
   }
   go http.Serve(listen, nil)
}

func main() {
	server0 := Server{0, 0, make([]Log, numServers), 50000}
	server1 := Server{1, 0, make([]Log, numServers), 50001}
	server2 := Server{2, 0, make([]Log, numServers), 50002}
	server3 := Server{3, 0, make([]Log, numServers), 50003}
	server4 := Server{4, 0, make([]Log, numServers), 50004}
	servers := []Server{server0, server1, server2, server3, server4}

	for i := 0; i < numServers; i++ {
		go spawnServer(servers[i])
	}

  client, err := rpc.DialHTTP("tcp", "localhost:50004")
  if err != nil {
    log.Fatal("dialing:", err)
  }

  testMessage := Message{1,1,2}
  var reply Message
  //server6 := Server{5, 0, make([]Log, 6), 50005}
  mesCall := client.Go("Server.Respond", testMessage, reply, nil)
  replyCall := <-mesCall.Done

  fmt.Println("%v\n", replyCall.Reply)

}
<commit_msg>Commented out some stuff<commit_after>// Simple implementation of the raft concensus algorithm using golang rpc
// Cody Malick and Jacob Broderick
package main

import (
  "fmt"
  "net"
  "net/rpc"
  "strconv"
  "log"
  "net/http"
)

type Log struct {
	Item  int
	Epoch int
}

type Message struct {
	Source      int
	Destination int
  Value       int
}

type Server struct {
	Id    int
	Epoch int
	Log   []Log
  Port  int
}

func (t *Server) Respond(message *Message, reply *Message) error {
  message.Value += 1
  *reply = *message
  return nil
}

const (
	numServers = 5
)
// Reference: https://golang.org/pkg/net/rpc/
func spawnServer(server Server) {
  fmt.Println(server.Id)
  fmt.Println(server.Port)
  rpc.Register(server.Id)
  rpc.HandleHTTP()
  listen, err := net.Listen("tcp", ":" + strconv.Itoa(server.Port))
  if err != nil {
	   log.Fatal("listen error:", err)
   }
   fmt.Println("Test")
   go http.Serve(listen, nil)
}

func main() {
	server0 := Server{0, 0, make([]Log, numServers), 50000}
	server1 := Server{1, 0, make([]Log, numServers), 50001}
	server2 := Server{2, 0, make([]Log, numServers), 50002}
	server3 := Server{3, 0, make([]Log, numServers), 50003}
	server4 := Server{4, 0, make([]Log, numServers), 50004}
	servers := []Server{server0, server1, server2, server3, server4}

	for i := 0; i < numServers; i++ {
		go spawnServer(servers[i])
	}
  //
  // client, err := rpc.DialHTTP("tcp", "localhost:50004")
  // if err != nil {
  //   log.Fatal("dialing:", err)
  // }
  //
  // testMessage := Message{1,1,2}
  // var reply Message
  // //server6 := Server{5, 0, make([]Log, 6), 50005}
  // mesCall := client.Go("Server.Respond", testMessage, reply, nil)
  // replyCall := <-mesCall.Done
  //
  // fmt.Println("%v\n", replyCall.Reply)

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io"
	"log"
	"net/http"
	"os"
	"os/user"
	"path"
	"runtime"
	"sync"

	"github.com/PuerkitoBio/goquery"
)

var (
	downloadDir = path.Join("pictures", "bigpicture")
	dirHelp     = "Download dir. Defaults to ~" + downloadDir
	dir         = flag.String("dir", "", dirHelp)
)

func downloadImage(wg *sync.WaitGroup, href string) {
	defer wg.Done()

	name := path.Base(href)
	fp := path.Join(downloadDir, name)

	_, err := os.Stat(fp)
	if err != nil {
		img, err := http.Get("http:" + href)
		if err != nil {
			log.Printf("Error while downloading %s. Reason: %s\n", href, err.Error())
			return
		}

		file, err := os.Create(fp)
		if err != nil {
			log.Printf("Error while creating path %s. Reason: %s\n", fp, err.Error())
			return
		}

		io.Copy(file, img.Body)
		log.Printf(".")

		defer file.Close()
		defer img.Body.Close()

	} else {
		log.Printf("-")
	}
}

func loadPage(wg *sync.WaitGroup, href string) {
	defer wg.Done()

	doc, err := goquery.NewDocument("http://www.bostonglobe.com" + href)
	if err != nil {
		log.Fatal(err)
	}

	images := doc.Find(".photo img")
	var iwg sync.WaitGroup

	iwg.Add(images.Length())
	images.Each(func(i int, s *goquery.Selection) {
		src, _ := s.Attr("src")
		go downloadImage(&iwg, src)
	})
	iwg.Wait()
}

func init() {
	flag.StringVar(dir, "d", "", dirHelp)
}

func createDir(path string) {
	info, err := os.Stat(path)
	if os.IsNotExist(err) {
		if err = os.Mkdir(path, 0777); err != nil {
			log.Fatal(err)
			return
		}
	}

	if !info.IsDir() {
		log.Fatalf("%s exists but it's not a dir. Stopping.", path)
	}
}

func main() {
	flag.Parse()
	runtime.GOMAXPROCS(runtime.NumCPU())

	if *dir != "" {
		downloadDir = *dir
	} else {
		usr, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		downloadDir = path.Join(usr.HomeDir, downloadDir)
	}
	createDir(downloadDir)

	doc, err := goquery.NewDocument("http://www.bostonglobe.com/news/bigpicture")
	if err != nil {
		log.Fatal(err)
	}

	var wg sync.WaitGroup

	sel := doc.Find(".pictureInfo-headline")
	wg.Add(sel.Length())

	sel.Each(func(i int, s *goquery.Selection) {
		href, _ := s.Attr("href")
		go loadPage(&wg, href)
	})

	wg.Wait()
}
<commit_msg>Fix create dir bug<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/user"
	"path"
	"sync"

	"github.com/PuerkitoBio/goquery"
)

var (
	downloadDir = path.Join("Pictures", "bigpicture")
	dirHelp     = "Download dir. Defaults to ~" + downloadDir
	dir         = flag.String("dir", "", dirHelp)
)

func downloadImage(wg *sync.WaitGroup, href string) {
	defer wg.Done()

	name := path.Base(href)
	fp := path.Join(downloadDir, name)

	_, err := os.Stat(fp)
	if err != nil {
		img, err := http.Get("http:" + href)
		if err != nil {
			log.Printf("Error while downloading %s. Reason: %s\n", href, err.Error())
			return
		}

		file, err := os.Create(fp)
		if err != nil {
			log.Printf("Error while creating path %s. Reason: %s\n", fp, err.Error())
			return
		}

		io.Copy(file, img.Body)
		fmt.Printf("+")

		defer file.Close()
		defer img.Body.Close()

	} else {
		fmt.Printf(".")
	}
}

func loadPage(wg *sync.WaitGroup, href string) {
	defer wg.Done()

	doc, err := goquery.NewDocument("http://www.bostonglobe.com" + href)
	if err != nil {
		log.Fatal(err)
	}

	images := doc.Find(".photo img")
	var iwg sync.WaitGroup

	iwg.Add(images.Length())
	images.Each(func(i int, s *goquery.Selection) {
		src, _ := s.Attr("src")
		go downloadImage(&iwg, src)
	})
	iwg.Wait()
}

func init() {
	flag.StringVar(dir, "d", "", dirHelp)
}

func createDir(path string) {
	if info, err := os.Stat(path); os.IsNotExist(err) {
		if err = os.Mkdir(path, 0777); err != nil {
			log.Fatal(err)
			return
		}
	} else {
		if !info.IsDir() {
			log.Fatalf("%s exists but it's not a dir. Stopping.", path)
		}
	}
}

func main() {
	flag.Parse()

	if *dir != "" {
		downloadDir = *dir
	} else {
		usr, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		downloadDir = path.Join(usr.HomeDir, downloadDir)
	}

	createDir(downloadDir)

	doc, err := goquery.NewDocument("http://www.bostonglobe.com/news/bigpicture")
	if err != nil {
		log.Fatal(err)
	}

	var wg sync.WaitGroup

	sel := doc.Find(".pictureInfo-headline")
	wg.Add(sel.Length())

	sel.Each(func(i int, s *goquery.Selection) {
		href, _ := s.Attr("href")
		go loadPage(&wg, href)
	})

	wg.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"sort"
	"strconv"
	"strings"
	"sync"
)

const (
	CmdDisplayMax = 32
	// max length of /proc/$PID/comm
	CommMax = 16
	// from ps_mem - average error due to truncation in the kernel
	// pss calculations
	PssAdjust    = .5
	pageSize     = 4096
	mapDetailLen = len("Size:                  4 kB")

	usage = `Usage: %s [OPTION...]
Simple, accurate RAM and swap reporting.

Options:
`
)

var (
	memProfile string
	cpuProfile string

	tyPss          = []byte("Pss:")
	tySwap         = []byte("Swap:")
	tyPrivateClean = []byte("Private_Clean:")
	tyPrivateDirty = []byte("Private_Dirty:")
)

// store info about a command (group of processes), similar to how
// ps_mem works.
type CmdMemInfo struct {
	PIDs    []int
	Name    string
	Pss     float64
	Private uint64
	Swapped uint64
}

type MapInfo struct {
	Inode uint64
	Name  string
}

// mapLine is a line from /proc/$PID/maps, or one of the same header
// lines from smaps.
func NewMapInfo(mapLine []byte) MapInfo {
	var mi MapInfo
	var err error
	pieces := splitSpaces(mapLine)
	if len(pieces) == 6 {
		mi.Name = string(pieces[5])
	}
	mi.Inode, err = ParseUint(pieces[4], 10, 64)
	if err != nil {
		panic(fmt.Sprintf("NewMapInfo: Atoi(%s): %s (%s)",
			string(pieces[4]), err, string(mapLine)))
	}
	return mi
}

func (mi MapInfo) IsAnon() bool {
	return mi.Inode == 0
}

// isDigit returns true if the rune d represents an ascii digit
// between 0 and 9, inclusive.
func isDigit(d uint8) bool {
	return d >= '0' && d <= '9'
}

// pidList returns a list of the process-IDs of every currently
// running process on the local system.
func pidList() ([]int, error) {
	procLs, err := ioutil.ReadDir("/proc")
	if err != nil {
		return nil, fmt.Errorf("ReadDir(/proc): %s", err)
	}

	pids := make([]int, 0, len(procLs))
	for _, pInfo := range procLs {
		if !isDigit(pInfo.Name()[0]) || !pInfo.IsDir() {
			continue
		}
		pidInt, err := strconv.Atoi(pInfo.Name())
		if err != nil {
			return nil, fmt.Errorf("Atoi(%s): %s", pInfo.Name(), err)
		}
		pids = append(pids, pidInt)
	}
	return pids, nil
}

// procName gets the process name for a worker.  It first checks the
// value of /proc/$PID/cmdline.  If setproctitle(3) has been called,
// it will use this.  Otherwise it uses the value of
// path.Base(/proc/$PID/exe), which has info on whether the executable
// has changed since the process was exec'ed.
func procName(pid int) (string, error) {
	p, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
	// this would return an error if the PID doesn't
	// exist, or if the PID refers to a kernel thread.
	if err != nil {
		return "", nil
	}
	// cmdline is the null separated list of command line
	// arguments for the process, unless setproctitle(3)
	// has been called, in which case it is the
	argsB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
	if err != nil {
		return "", fmt.Errorf("ReadFile(%s): %s", fmt.Sprintf("/proc/%d/cmdline", pid), err)
	}
	args := strings.Split(string(argsB), "\000")
	n := args[0]

	nTrunc := n
	if len(n) > CommMax {
		nTrunc = n[:CommMax]
	}
	if strings.HasPrefix(p, nTrunc) {
		n = path.Base(p)
	}
	return n, nil
}

// splitSpaces returns a slice of byte slices which are the space
// delimited words from the original byte slice.  Unlike
// strings.Split($X, " "), runs of multiple spaces in a row are
// discarded.  NOTE WELL: this only checks for spaces (' '), other
// unicode whitespace isn't supported.
func splitSpaces(b []byte) [][]byte {
	// most lines in smaps have the form "Swap: 4 kB", so
	// preallocate the slice's array appropriately.
	res := make([][]byte, 0, 3)
	for i := 0; i < len(b); {
		if b[i] == ' ' {
			i++
			continue
		}
		end := bytes.IndexByte(b[i:], ' ')
		if end == -1 {
			end = len(b)
		} else {
			end += i
		}
		res = append(res, b[i:end])
		i = end
	}
	return res
}

// procMem returns the amount of Pss, shared, and swapped out memory
// used.  The swapped out amount refers to anonymous pages only.
func procMem(pid int) (pss float64, priv, swap uint64, err error) {
	fPath := fmt.Sprintf("/proc/%d/smaps", pid)
	f, err := os.Open(fPath)
	if err != nil {
		err = fmt.Errorf("os.Open(%s): %s", fPath, err)
		return
	}
	//var curr MapInfo
	r := bufio.NewReaderSize(f, pageSize)
	for {
		var l []byte
		var isPrefix bool
		l, isPrefix, err = r.ReadLine()
		// this should never happen, so take the easy way out.
		if isPrefix {
			err = fmt.Errorf("ReadLine(%s): isPrefix", fPath)
		}
		if err != nil {
			// if we've got EOF, then we're simply done
			// processing smaps.
			if err == io.EOF {
				err = nil
				break
			}
			// otherwise error out
			err = fmt.Errorf("ReadLine(%s): %s", fPath, err)
			return
		}

		if len(l) != mapDetailLen {
			//curr = NewMapInfo(l)
			continue
		}
		pieces := splitSpaces(l)
		ty := pieces[0]
		var v uint64
		if bytes.Equal(ty, tyPss) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			pss += float64(v) + PssAdjust
		} else if bytes.Equal(ty, tyPrivateClean) || bytes.Equal(ty, tyPrivateDirty) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			priv += v
		} else if bytes.Equal(ty, tySwap) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			swap += v
		}
	}
	return
}

func worker(pidRequest chan int, wg *sync.WaitGroup, result chan *CmdMemInfo) {
	for pid := range pidRequest {
		var err error
		cmi := new(CmdMemInfo)

		cmi.PIDs = []int{pid}
		cmi.Name, err = procName(pid)
		if err != nil {
			log.Printf("procName(%d): %s", pid, err)
			wg.Done()
			continue
		} else if cmi.Name == "" {
			// XXX: This happens with kernel
			// threads. maybe warn? idk.
			wg.Done()
			continue
		}

		cmi.Pss, cmi.Private, cmi.Swapped, err = procMem(pid)
		if err != nil {
			log.Printf("procMem(%d): %s", pid, err)
			wg.Done()
			continue
		}

		result <- cmi
		wg.Done()
	}
}

type byTotal []*CmdMemInfo

func (c byTotal) Len() int           { return len(c) }
func (c byTotal) Less(i, j int) bool { return c[i].Pss < c[j].Pss }
func (c byTotal) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	flag.StringVar(&memProfile, "memprofile", "",
		"write memory profile to this file")
	flag.StringVar(&cpuProfile, "cpuprofile", "",
		"write cpu profile to this file")

	flag.Parse()
}

// startProfiling enables memory and/or CPU profiling if the
// appropriate command line flags have been set.
func startProfiling() {
	var err error
	// if we've passed in filenames to dump profiling data too,
	// start collecting profiling data.
	if memProfile != "" {
		runtime.MemProfileRate = 1
	}
	if cpuProfile != "" {
		var f *os.File
		if f, err = os.Create(cpuProfile); err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
	}
}

func stopProfiling() {
	if memProfile != "" {
		runtime.GC()
		f, err := os.Create(memProfile)
		if err != nil {
			log.Println(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}
	if cpuProfile != "" {
		pprof.StopCPUProfile()
		cpuProfile = ""
	}
}

func main() {
	startProfiling()
	defer stopProfiling()

	// need to be root to read map info for other user's
	// processes.
	if os.Geteuid() != 0 {
		fmt.Printf("FATAL: root required.\n")
		return
	}

	pids, err := pidList()
	if err != nil {
		log.Printf("pidList: %s", err)
		return
	}

	var wg sync.WaitGroup
	work := make(chan int, len(pids))
	result := make(chan *CmdMemInfo, len(pids))

	// give us as much parallelism as possible
	nCPU := runtime.NumCPU()
	runtime.GOMAXPROCS(nCPU)
	for i := 0; i < nCPU; i++ {
		go worker(work, &wg, result)
	}

	wg.Add(len(pids))
	for _, pid := range pids {
		work <- pid
	}
	wg.Wait()

	// aggregate similar processes by command name.
	cmdMap := map[string]*CmdMemInfo{}
loop:
	for {
		// this only works correctly because we a channel
		// where the buffer size >= the number of potential
		// results.
		select {
		case c := <-result:
			n := c.Name
			if _, ok := cmdMap[n]; !ok {
				cmdMap[n] = c
				continue
			}
			cmdMap[n].PIDs = append(cmdMap[n].PIDs, c.PIDs...)
			cmdMap[n].Pss += c.Pss
			cmdMap[n].Private += c.Private
			cmdMap[n].Swapped += c.Swapped
		default:
			break loop
		}
	}

	// extract map values to a slice so we can sort them
	cmds := make([]*CmdMemInfo, 0, len(cmdMap))
	for _, c := range cmdMap {
		cmds = append(cmds, c)
	}
	sort.Sort(byTotal(cmds))

	// keep track of total RAM and swap usage
	var totPss, totSwap float64

	fmt.Printf("%10s%10s%10s\t%s\n", "MB RAM", "PRIVATE", "SWAPPED", "PROCESS (COUNT)")
	for _, c := range cmds {
		n := c.Name
		if len(n) > CmdDisplayMax {
			if n[0] == '[' {
				n = n[:strings.IndexRune(n, ']')+1]
			} else {
				n = n[:CmdDisplayMax]
			}
		}
		s := ""
		if c.Swapped > 0 {
			swap := float64(c.Swapped) / 1024.
			totSwap += swap
			s = fmt.Sprintf("%10.1f", swap)
		}
		pss := float64(c.Pss) / 1024.
		fmt.Printf("%10.1f%10.1f%10s\t%s (%d)\n", pss, float64(c.Private)/1024., s, n, len(c.PIDs))
		totPss += pss
	}
	fmt.Printf("#%9.1f%20.1f\tTOTAL USED BY PROCESSES\n", totPss, totSwap)
}
<commit_msg>Revert "splitSpaces: use bytes.IndexByte"<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"runtime"
	"runtime/pprof"
	"sort"
	"strconv"
	"strings"
	"sync"
)

const (
	CmdDisplayMax = 32
	// max length of /proc/$PID/comm
	CommMax = 16
	// from ps_mem - average error due to truncation in the kernel
	// pss calculations
	PssAdjust    = .5
	pageSize     = 4096
	mapDetailLen = len("Size:                  4 kB")

	usage = `Usage: %s [OPTION...]
Simple, accurate RAM and swap reporting.

Options:
`
)

var (
	memProfile string
	cpuProfile string

	tyPss          = []byte("Pss:")
	tySwap         = []byte("Swap:")
	tyPrivateClean = []byte("Private_Clean:")
	tyPrivateDirty = []byte("Private_Dirty:")
)

// store info about a command (group of processes), similar to how
// ps_mem works.
type CmdMemInfo struct {
	PIDs    []int
	Name    string
	Pss     float64
	Private uint64
	Swapped uint64
}

type MapInfo struct {
	Inode uint64
	Name  string
}

// mapLine is a line from /proc/$PID/maps, or one of the same header
// lines from smaps.
func NewMapInfo(mapLine []byte) MapInfo {
	var mi MapInfo
	var err error
	pieces := splitSpaces(mapLine)
	if len(pieces) == 6 {
		mi.Name = string(pieces[5])
	}
	mi.Inode, err = ParseUint(pieces[4], 10, 64)
	if err != nil {
		panic(fmt.Sprintf("NewMapInfo: Atoi(%s): %s (%s)",
			string(pieces[4]), err, string(mapLine)))
	}
	return mi
}

func (mi MapInfo) IsAnon() bool {
	return mi.Inode == 0
}

// isDigit returns true if the rune d represents an ascii digit
// between 0 and 9, inclusive.
func isDigit(d uint8) bool {
	return d >= '0' && d <= '9'
}

// pidList returns a list of the process-IDs of every currently
// running process on the local system.
func pidList() ([]int, error) {
	procLs, err := ioutil.ReadDir("/proc")
	if err != nil {
		return nil, fmt.Errorf("ReadDir(/proc): %s", err)
	}

	pids := make([]int, 0, len(procLs))
	for _, pInfo := range procLs {
		if !isDigit(pInfo.Name()[0]) || !pInfo.IsDir() {
			continue
		}
		pidInt, err := strconv.Atoi(pInfo.Name())
		if err != nil {
			return nil, fmt.Errorf("Atoi(%s): %s", pInfo.Name(), err)
		}
		pids = append(pids, pidInt)
	}
	return pids, nil
}

// procName gets the process name for a worker.  It first checks the
// value of /proc/$PID/cmdline.  If setproctitle(3) has been called,
// it will use this.  Otherwise it uses the value of
// path.Base(/proc/$PID/exe), which has info on whether the executable
// has changed since the process was exec'ed.
func procName(pid int) (string, error) {
	p, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
	// this would return an error if the PID doesn't
	// exist, or if the PID refers to a kernel thread.
	if err != nil {
		return "", nil
	}
	// cmdline is the null separated list of command line
	// arguments for the process, unless setproctitle(3)
	// has been called, in which case it is the
	argsB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
	if err != nil {
		return "", fmt.Errorf("ReadFile(%s): %s", fmt.Sprintf("/proc/%d/cmdline", pid), err)
	}
	args := strings.Split(string(argsB), "\000")
	n := args[0]

	nTrunc := n
	if len(n) > CommMax {
		nTrunc = n[:CommMax]
	}
	if strings.HasPrefix(p, nTrunc) {
		n = path.Base(p)
	}
	return n, nil
}

// splitSpaces returns a slice of byte slices which are the space
// delimited words from the original byte slice.  Unlike
// strings.Split($X, " "), runs of multiple spaces in a row are
// discarded.  NOTE WELL: this only checks for spaces (' '), other
// unicode whitespace isn't supported.
func splitSpaces(b []byte) [][]byte {
	// most lines in smaps have the form "Swap: 4 kB", so
	// preallocate the slice's array appropriately.
	res := make([][]byte, 0, 3)
	start := 0
	lenB := len(b)
	for i := 0; i < lenB - 1; i++ {
		if b[i] == ' ' {
			start = i + 1
		} else if b[i+1] == ' ' {
			res = append(res, b[start:i+1])
			start = i + 1
		}
	}
	if start != lenB && b[start] != ' ' {
		res = append(res, b[start:lenB])
	}
	return res
}

// procMem returns the amount of Pss, shared, and swapped out memory
// used.  The swapped out amount refers to anonymous pages only.
func procMem(pid int) (pss float64, priv, swap uint64, err error) {
	fPath := fmt.Sprintf("/proc/%d/smaps", pid)
	f, err := os.Open(fPath)
	if err != nil {
		err = fmt.Errorf("os.Open(%s): %s", fPath, err)
		return
	}
	//var curr MapInfo
	r := bufio.NewReaderSize(f, pageSize)
	for {
		var l []byte
		var isPrefix bool
		l, isPrefix, err = r.ReadLine()
		// this should never happen, so take the easy way out.
		if isPrefix {
			err = fmt.Errorf("ReadLine(%s): isPrefix", fPath)
		}
		if err != nil {
			// if we've got EOF, then we're simply done
			// processing smaps.
			if err == io.EOF {
				err = nil
				break
			}
			// otherwise error out
			err = fmt.Errorf("ReadLine(%s): %s", fPath, err)
			return
		}

		if len(l) != mapDetailLen {
			//curr = NewMapInfo(l)
			continue
		}
		pieces := splitSpaces(l)
		ty := pieces[0]
		var v uint64
		if bytes.Equal(ty, tyPss) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			pss += float64(v) + PssAdjust
		} else if bytes.Equal(ty, tyPrivateClean) || bytes.Equal(ty, tyPrivateDirty) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			priv += v
		} else if bytes.Equal(ty, tySwap) {
			v, err = ParseUint(pieces[1], 10, 64)
			if err != nil {
				err = fmt.Errorf("Atoi(%s): %s", string(pieces[1]), err)
				return
			}
			swap += v
		}
	}
	return
}

func worker(pidRequest chan int, wg *sync.WaitGroup, result chan *CmdMemInfo) {
	for pid := range pidRequest {
		var err error
		cmi := new(CmdMemInfo)

		cmi.PIDs = []int{pid}
		cmi.Name, err = procName(pid)
		if err != nil {
			log.Printf("procName(%d): %s", pid, err)
			wg.Done()
			continue
		} else if cmi.Name == "" {
			// XXX: This happens with kernel
			// threads. maybe warn? idk.
			wg.Done()
			continue
		}

		cmi.Pss, cmi.Private, cmi.Swapped, err = procMem(pid)
		if err != nil {
			log.Printf("procMem(%d): %s", pid, err)
			wg.Done()
			continue
		}

		result <- cmi
		wg.Done()
	}
}

type byTotal []*CmdMemInfo

func (c byTotal) Len() int           { return len(c) }
func (c byTotal) Less(i, j int) bool { return c[i].Pss < c[j].Pss }
func (c byTotal) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	flag.StringVar(&memProfile, "memprofile", "",
		"write memory profile to this file")
	flag.StringVar(&cpuProfile, "cpuprofile", "",
		"write cpu profile to this file")

	flag.Parse()
}

// startProfiling enables memory and/or CPU profiling if the
// appropriate command line flags have been set.
func startProfiling() {
	var err error
	// if we've passed in filenames to dump profiling data too,
	// start collecting profiling data.
	if memProfile != "" {
		runtime.MemProfileRate = 1
	}
	if cpuProfile != "" {
		var f *os.File
		if f, err = os.Create(cpuProfile); err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
	}
}

func stopProfiling() {
	if memProfile != "" {
		runtime.GC()
		f, err := os.Create(memProfile)
		if err != nil {
			log.Println(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}
	if cpuProfile != "" {
		pprof.StopCPUProfile()
		cpuProfile = ""
	}
}

func main() {
	startProfiling()
	defer stopProfiling()

	// need to be root to read map info for other user's
	// processes.
	if os.Geteuid() != 0 {
		fmt.Printf("FATAL: root required.\n")
		return
	}

	pids, err := pidList()
	if err != nil {
		log.Printf("pidList: %s", err)
		return
	}

	var wg sync.WaitGroup
	work := make(chan int, len(pids))
	result := make(chan *CmdMemInfo, len(pids))

	// give us as much parallelism as possible
	nCPU := runtime.NumCPU()
	runtime.GOMAXPROCS(nCPU)
	for i := 0; i < nCPU; i++ {
		go worker(work, &wg, result)
	}

	wg.Add(len(pids))
	for _, pid := range pids {
		work <- pid
	}
	wg.Wait()

	// aggregate similar processes by command name.
	cmdMap := map[string]*CmdMemInfo{}
loop:
	for {
		// this only works correctly because we a channel
		// where the buffer size >= the number of potential
		// results.
		select {
		case c := <-result:
			n := c.Name
			if _, ok := cmdMap[n]; !ok {
				cmdMap[n] = c
				continue
			}
			cmdMap[n].PIDs = append(cmdMap[n].PIDs, c.PIDs...)
			cmdMap[n].Pss += c.Pss
			cmdMap[n].Private += c.Private
			cmdMap[n].Swapped += c.Swapped
		default:
			break loop
		}
	}

	// extract map values to a slice so we can sort them
	cmds := make([]*CmdMemInfo, 0, len(cmdMap))
	for _, c := range cmdMap {
		cmds = append(cmds, c)
	}
	sort.Sort(byTotal(cmds))

	// keep track of total RAM and swap usage
	var totPss, totSwap float64

	fmt.Printf("%10s%10s%10s\t%s\n", "MB RAM", "PRIVATE", "SWAPPED", "PROCESS (COUNT)")
	for _, c := range cmds {
		n := c.Name
		if len(n) > CmdDisplayMax {
			if n[0] == '[' {
				n = n[:strings.IndexRune(n, ']')+1]
			} else {
				n = n[:CmdDisplayMax]
			}
		}
		s := ""
		if c.Swapped > 0 {
			swap := float64(c.Swapped) / 1024.
			totSwap += swap
			s = fmt.Sprintf("%10.1f", swap)
		}
		pss := float64(c.Pss) / 1024.
		fmt.Printf("%10.1f%10.1f%10s\t%s (%d)\n", pss, float64(c.Private)/1024., s, n, len(c.PIDs))
		totPss += pss
	}
	fmt.Printf("#%9.1f%20.1f\tTOTAL USED BY PROCESSES\n", totPss, totSwap)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	flags "github.com/jessevdk/go-flags"
	"github.com/monochromegane/terminal"
	"github.com/monochromegane/the_platinum_searcher/search"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"os"
	"runtime"
	"strings"
)

var opts option.Option

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "pt"
	parser.Usage = "[OPTIONS] PATTERN [PATH]"

	args, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}

	opts.Proc = runtime.NumCPU()

	if !terminal.IsTerminal(os.Stdout) {
		opts.NoColor = true
		opts.NoGroup = true
	}

	if len(args) == 0 {
		parser.WriteHelp(os.Stdout)
		os.Exit(1)
	}

	var root = "."
	if len(args) == 2 {
		root = strings.TrimRight(args[1], string(os.PathSeparator))
		_, err := os.Lstat(root)
		if err != nil {
			fmt.Printf("%s\n", err)
			os.Exit(1)
		}
	}

	searcher := search.Searcher{root, args[0], &opts}
	searcher.Search()
}
<commit_msg>Revert "Aboid the error when specified the following path."<commit_after>package main

import (
	"fmt"
	flags "github.com/jessevdk/go-flags"
	"github.com/monochromegane/terminal"
	"github.com/monochromegane/the_platinum_searcher/search"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"os"
	"runtime"
)

var opts option.Option

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "pt"
	parser.Usage = "[OPTIONS] PATTERN [PATH]"

	args, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}

	opts.Proc = runtime.NumCPU()

	if !terminal.IsTerminal(os.Stdout) {
		opts.NoColor = true
		opts.NoGroup = true
	}

	if len(args) == 0 {
		parser.WriteHelp(os.Stdout)
		os.Exit(1)
	}

	var root = "."
	if len(args) == 2 {
		root = args[1]
		_, err := os.Lstat(root)
		if err != nil {
			fmt.Printf("%s\n", err)
			os.Exit(1)
		}
	}

	searcher := search.Searcher{root, args[0], &opts}
	searcher.Search()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"fmt"
	"os"

	"github.com/spf13/viper"
	"golang.org/x/sync/errgroup"

	"github.com/zitryss/aye-and-nay/delivery/http"
	"github.com/zitryss/aye-and-nay/domain/model"
	"github.com/zitryss/aye-and-nay/domain/service"
	"github.com/zitryss/aye-and-nay/infrastructure/compressor"
	"github.com/zitryss/aye-and-nay/infrastructure/database"
	"github.com/zitryss/aye-and-nay/infrastructure/storage"
	"github.com/zitryss/aye-and-nay/pkg/errors"
	"github.com/zitryss/aye-and-nay/pkg/log"
)

var (
	ballast []byte
)

func main() {
	conf := ""
	flag.StringVar(&conf, "config", ".", "relative path to config file")
	flag.Parse()

	viper.SetConfigName("config")
	viper.AddConfigPath(conf)
	err := viper.ReadInConfig()
	if err != nil {
		_, _ = fmt.Fprintln(os.Stderr, "critical:", err)
		os.Exit(1)
	}

	ballast = make([]byte, viper.GetInt64("app.ballast"))

	lvl := viper.GetString("app.log")
	log.SetOutput(os.Stderr)
	log.SetLevel(lvl)
	log.Info("logging initialized")

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	comp := model.Compresser(nil)
	if viper.GetBool("shortpixel.use") {
		log.Info("connecting to shortpixel")
		sp := compressor.NewShortPixel()
		err = sp.Ping()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		sp.Monitor()
		comp = &sp
	} else {
		mock := compressor.NewMock()
		comp = &mock
	}

	stor := model.Storager(nil)
	if viper.GetBool("minio.use") {
		log.Info("connecting to minio")
		minio, err := storage.NewMinio()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		stor = &minio
	} else {
		mock := storage.NewMock()
		stor = &mock
	}

	pers := model.Persister(nil)
	if viper.GetBool("mongo.use") {
		log.Info("connecting to mongo")
		mongo, err := database.NewMongo()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		pers = &mongo
	} else {
		mem := database.NewMem()
		pers = &mem
	}

	temp := model.Temper(nil)
	if viper.GetBool("redis.use") {
		log.Info("connecting to redis")
		redis, err := database.NewRedis()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		temp = &redis
	} else {
		mem := database.NewMem()
		mem.Monitor()
		temp = &mem
	}

	queue1 := service.NewQueue("calculation", temp)
	queue1.Monitor(ctx)

	queue2 := (*service.Queue)(nil)
	if viper.GetBool("shortpixel.use") {
		queue2 = service.NewQueue("compression", temp)
		queue2.Monitor(ctx)
	}

	pqueue := service.NewPQueue("deletion", temp)
	pqueue.Monitor(ctx)

	serv := service.NewService(comp, stor, pers, temp, queue1, queue2, pqueue)

	g1, ctx1 := errgroup.WithContext(ctx)
	log.Info("starting calculation worker pool")
	serv.StartWorkingPoolCalc(ctx1, g1)

	g2 := (*errgroup.Group)(nil)
	ctx2 := context.Context(nil)
	if viper.GetBool("shortpixel.use") {
		g2, ctx2 = errgroup.WithContext(ctx)
		log.Info("starting compression worker pool")
		serv.StartWorkingPoolComp(ctx2, g2)
	}

	g3, ctx3 := errgroup.WithContext(ctx)
	log.Info("starting deletion worker pool")
	serv.StartWorkingPoolDel(ctx3, g3)

	srvWait := make(chan error, 1)
	srv := http.NewServer(&serv, cancel, srvWait)
	srv.Monitor()
	log.Info("starting web server")
	err = srv.Start()

	log.Info("stopping web server")
	if err != nil && !errors.Is(err, http.ErrServerClosed) {
		log.Error(err)
		return
	}
	err = <-srvWait
	if err != nil {
		log.Error(err)
		return
	}
	if viper.GetBool("shortpixel.use") {
		log.Info("stopping compression worker pool")
		err = g2.Wait()
		if err != nil {
			log.Error(err)
			return
		}
	}

	log.Info("stopping calculation worker pool")
	err = g1.Wait()
	if err != nil {
		log.Error(err)
		return
	}
}
<commit_msg>Wait for queue response<commit_after>package main

import (
	"context"
	"flag"
	"fmt"
	"os"

	"github.com/spf13/viper"
	"golang.org/x/sync/errgroup"

	"github.com/zitryss/aye-and-nay/delivery/http"
	"github.com/zitryss/aye-and-nay/domain/model"
	"github.com/zitryss/aye-and-nay/domain/service"
	"github.com/zitryss/aye-and-nay/infrastructure/compressor"
	"github.com/zitryss/aye-and-nay/infrastructure/database"
	"github.com/zitryss/aye-and-nay/infrastructure/storage"
	"github.com/zitryss/aye-and-nay/pkg/errors"
	"github.com/zitryss/aye-and-nay/pkg/log"
)

var (
	ballast []byte
)

func main() {
	conf := ""
	flag.StringVar(&conf, "config", ".", "relative path to config file")
	flag.Parse()

	viper.SetConfigName("config")
	viper.AddConfigPath(conf)
	err := viper.ReadInConfig()
	if err != nil {
		_, _ = fmt.Fprintln(os.Stderr, "critical:", err)
		os.Exit(1)
	}

	ballast = make([]byte, viper.GetInt64("app.ballast"))

	lvl := viper.GetString("app.log")
	log.SetOutput(os.Stderr)
	log.SetLevel(lvl)
	log.Info("logging initialized")

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	comp := model.Compresser(nil)
	if viper.GetBool("shortpixel.use") {
		log.Info("connecting to shortpixel")
		sp := compressor.NewShortPixel()
		err = sp.Ping()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		sp.Monitor()
		comp = &sp
	} else {
		mock := compressor.NewMock()
		comp = &mock
	}

	stor := model.Storager(nil)
	if viper.GetBool("minio.use") {
		log.Info("connecting to minio")
		minio, err := storage.NewMinio()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		stor = &minio
	} else {
		mock := storage.NewMock()
		stor = &mock
	}

	pers := model.Persister(nil)
	if viper.GetBool("mongo.use") {
		log.Info("connecting to mongo")
		mongo, err := database.NewMongo()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		pers = &mongo
	} else {
		mem := database.NewMem()
		pers = &mem
	}

	temp := model.Temper(nil)
	if viper.GetBool("redis.use") {
		log.Info("connecting to redis")
		redis, err := database.NewRedis()
		if err != nil {
			log.Critical(err)
			os.Exit(1)
		}
		temp = &redis
	} else {
		mem := database.NewMem()
		mem.Monitor()
		temp = &mem
	}

	queue1 := service.NewQueue("calculation", temp)
	queue1.Monitor(ctx)

	queue2 := (*service.Queue)(nil)
	if viper.GetBool("shortpixel.use") {
		queue2 = service.NewQueue("compression", temp)
		queue2.Monitor(ctx)
	}

	pqueue := service.NewPQueue("deletion", temp)
	pqueue.Monitor(ctx)

	serv := service.NewService(comp, stor, pers, temp, queue1, queue2, pqueue)

	g1, ctx1 := errgroup.WithContext(ctx)
	log.Info("starting calculation worker pool")
	serv.StartWorkingPoolCalc(ctx1, g1)

	g2 := (*errgroup.Group)(nil)
	ctx2 := context.Context(nil)
	if viper.GetBool("shortpixel.use") {
		g2, ctx2 = errgroup.WithContext(ctx)
		log.Info("starting compression worker pool")
		serv.StartWorkingPoolComp(ctx2, g2)
	}

	g3, ctx3 := errgroup.WithContext(ctx)
	log.Info("starting deletion worker pool")
	serv.StartWorkingPoolDel(ctx3, g3)

	srvWait := make(chan error, 1)
	srv := http.NewServer(&serv, cancel, srvWait)
	srv.Monitor()
	log.Info("starting web server")
	err = srv.Start()

	log.Info("stopping web server")
	if err != nil && !errors.Is(err, http.ErrServerClosed) {
		log.Error(err)
		return
	}
	err = <-srvWait
	if err != nil {
		log.Error(err)
		return
	}

	log.Info("stopping deletion worker pool")
	err = g3.Wait()
	if err != nil {
		log.Error(err)
		return
	}

	if viper.GetBool("shortpixel.use") {
		log.Info("stopping compression worker pool")
		err = g2.Wait()
		if err != nil {
			log.Error(err)
			return
		}
	}

	log.Info("stopping calculation worker pool")
	err = g1.Wait()
	if err != nil {
		log.Error(err)
		return
	}
}
<|endoftext|>


<commit_before>// Package main is the CLI.
// You can use the CLI via Terminal.
// import "github.com/mattes/migrate/migrate" for usage within Go.
package main

import (
	"flag"
	"fmt"
	"github.com/fatih/color"
	"github.com/mattes/migrate/file"
	"github.com/mattes/migrate/migrate"
	"github.com/mattes/migrate/migrate/direction"
	pipep "github.com/mattes/migrate/pipe"
	"os"
	"strconv"
	"time"
)

var url = flag.String("url", "", "")
var migrationsPath = flag.String("path", "", "")
var version = flag.Bool("version", false, "Show migrate version")

func main() {
	flag.Parse()
	command := flag.Arg(0)

	if *version {
		fmt.Println(Version)
		os.Exit(0)
	}

	if *migrationsPath == "" {
		*migrationsPath, _ = os.Getwd()
	}

	switch command {
	case "create":
		verifyMigrationsPath(*migrationsPath)
		name := flag.Arg(1)
		if name == "" {
			fmt.Println("Please specify name.")
			os.Exit(1)
		}

		migrationFile, err := migrate.Create(*url, *migrationsPath, name)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Printf("Version %v migration files created in %v:\n", migrationFile.Version, *migrationsPath)
		fmt.Println(migrationFile.UpFile.FileName)
		fmt.Println(migrationFile.DownFile.FileName)

	case "migrate":
		verifyMigrationsPath(*migrationsPath)
		relativeN := flag.Arg(1)
		relativeNInt, err := strconv.Atoi(relativeN)
		if err != nil {
			fmt.Println("Unable to parse param <n>.")
			os.Exit(1)
		}
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "goto":
		verifyMigrationsPath(*migrationsPath)
		toVersion := flag.Arg(1)
		toVersionInt, err := strconv.Atoi(toVersion)
		if err != nil || toVersionInt < 0 {
			fmt.Println("Unable to parse param <v>.")
			os.Exit(1)
		}

		currentVersion, err := migrate.Version(*url, *migrationsPath)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		relativeNInt := toVersionInt - int(currentVersion)

		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "up":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Up(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "down":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Down(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "redo":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Redo(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "reset":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Reset(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "version":
		verifyMigrationsPath(*migrationsPath)
		version, err := migrate.Version(*url, *migrationsPath)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(version)

	default:
		fallthrough
	case "help":
		helpCmd()
	}
}

func writePipe(pipe chan interface{}) bool {
	errorFlag := false
	if pipe != nil {
		for {
			select {
			case item, ok := <-pipe:
				if !ok {
					return !errorFlag
				} else {
					switch item.(type) {

					case string:
						fmt.Println(item.(string))

					case error:
						c := color.New(color.FgRed)
						c.Println(item.(error).Error(), "\n")
						errorFlag = true

					case file.File:
						f := item.(file.File)
						c := color.New(color.FgBlue)
						if f.Direction == direction.Up {
							c.Print(">")
						} else if f.Direction == direction.Down {
							c.Print("<")
						}
						fmt.Printf(" %s\n", f.FileName)

					default:
						text := fmt.Sprint(item)
						fmt.Println(text)
					}
				}
			}
		}
	}
	return errorFlag
}

func verifyMigrationsPath(path string) {
	if path == "" {
		fmt.Println("Please specify path")
		os.Exit(1)
	}
}

var timerStart time.Time

func printTimer() {
	diff := time.Now().Sub(timerStart).Seconds()
	if diff > 60 {
		fmt.Printf("\n%.4f minutes\n", diff/60)
	} else {
		fmt.Printf("\n%.4f seconds\n", diff)
	}
}

func helpCmd() {
	os.Stderr.WriteString(
		`usage: migrate [-path=<path>] -url=<url> <command> [<args>]

Commands:
   create <name>  Create a new migration
   up             Apply all -up- migrations
   down           Apply all -down- migrations
   reset          Down followed by Up
   redo           Roll back most recent migration, then apply it again
   version        Show current migration version
   migrate <n>    Apply migrations -n|+n
   goto <v>       Migrate to version v
   help           Show this help

'-path' defaults to current working directory.
`)
}
<commit_msg>rename errorFlag to okFlag to make it even more clearer #22<commit_after>// Package main is the CLI.
// You can use the CLI via Terminal.
// import "github.com/mattes/migrate/migrate" for usage within Go.
package main

import (
	"flag"
	"fmt"
	"github.com/fatih/color"
	"github.com/mattes/migrate/file"
	"github.com/mattes/migrate/migrate"
	"github.com/mattes/migrate/migrate/direction"
	pipep "github.com/mattes/migrate/pipe"
	"os"
	"strconv"
	"time"
)

var url = flag.String("url", "", "")
var migrationsPath = flag.String("path", "", "")
var version = flag.Bool("version", false, "Show migrate version")

func main() {
	flag.Parse()
	command := flag.Arg(0)

	if *version {
		fmt.Println(Version)
		os.Exit(0)
	}

	if *migrationsPath == "" {
		*migrationsPath, _ = os.Getwd()
	}

	switch command {
	case "create":
		verifyMigrationsPath(*migrationsPath)
		name := flag.Arg(1)
		if name == "" {
			fmt.Println("Please specify name.")
			os.Exit(1)
		}

		migrationFile, err := migrate.Create(*url, *migrationsPath, name)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Printf("Version %v migration files created in %v:\n", migrationFile.Version, *migrationsPath)
		fmt.Println(migrationFile.UpFile.FileName)
		fmt.Println(migrationFile.DownFile.FileName)

	case "migrate":
		verifyMigrationsPath(*migrationsPath)
		relativeN := flag.Arg(1)
		relativeNInt, err := strconv.Atoi(relativeN)
		if err != nil {
			fmt.Println("Unable to parse param <n>.")
			os.Exit(1)
		}
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "goto":
		verifyMigrationsPath(*migrationsPath)
		toVersion := flag.Arg(1)
		toVersionInt, err := strconv.Atoi(toVersion)
		if err != nil || toVersionInt < 0 {
			fmt.Println("Unable to parse param <v>.")
			os.Exit(1)
		}

		currentVersion, err := migrate.Version(*url, *migrationsPath)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		relativeNInt := toVersionInt - int(currentVersion)

		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "up":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Up(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "down":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Down(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "redo":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Redo(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "reset":
		verifyMigrationsPath(*migrationsPath)
		timerStart = time.Now()
		pipe := pipep.New()
		go migrate.Reset(pipe, *url, *migrationsPath)
		ok := writePipe(pipe)
		printTimer()
		if !ok {
			os.Exit(1)
		}

	case "version":
		verifyMigrationsPath(*migrationsPath)
		version, err := migrate.Version(*url, *migrationsPath)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(version)

	default:
		fallthrough
	case "help":
		helpCmd()
	}
}

func writePipe(pipe chan interface{}) (ok bool) {
	okFlag := true
	if pipe != nil {
		for {
			select {
			case item, ok := <-pipe:
				if !ok {
					return false
				} else {
					switch item.(type) {

					case string:
						fmt.Println(item.(string))

					case error:
						c := color.New(color.FgRed)
						c.Println(item.(error).Error(), "\n")
						okFlag = false

					case file.File:
						f := item.(file.File)
						c := color.New(color.FgBlue)
						if f.Direction == direction.Up {
							c.Print(">")
						} else if f.Direction == direction.Down {
							c.Print("<")
						}
						fmt.Printf(" %s\n", f.FileName)

					default:
						text := fmt.Sprint(item)
						fmt.Println(text)
					}
				}
			}
		}
	}
	return okFlag
}

func verifyMigrationsPath(path string) {
	if path == "" {
		fmt.Println("Please specify path")
		os.Exit(1)
	}
}

var timerStart time.Time

func printTimer() {
	diff := time.Now().Sub(timerStart).Seconds()
	if diff > 60 {
		fmt.Printf("\n%.4f minutes\n", diff/60)
	} else {
		fmt.Printf("\n%.4f seconds\n", diff)
	}
}

func helpCmd() {
	os.Stderr.WriteString(
		`usage: migrate [-path=<path>] -url=<url> <command> [<args>]

Commands:
   create <name>  Create a new migration
   up             Apply all -up- migrations
   down           Apply all -down- migrations
   reset          Down followed by Up
   redo           Roll back most recent migration, then apply it again
   version        Show current migration version
   migrate <n>    Apply migrations -n|+n
   goto <v>       Migrate to version v
   help           Show this help

'-path' defaults to current working directory.
`)
}
<|endoftext|>


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

package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"github.com/xiam/arpfox/arp"

	"github.com/ArturoVM/targetparser"
)

var (
	flagInterface    = flag.String("i", "eth0", `Network interface.`)
	flagTarget       = flag.String("t", "", `Target host(s). Provide a single IP: "1.2.3.4", a list of IPs: "1.2.3.4, 5.6.7.8", a CIDR block "1.2.3.0/24" or an IP range: "1.2.3-7.4-12"`)
	flagWaitInterval = flag.Float64("w", 5.0, `Wait <w> seconds between every broadcast, <w> must be a value greater than 0.1.`)
	flagHelp         = flag.Bool("h", false, `Print usage instructions and exit.`)
)

func main() {
	flag.Parse()

	if *flagHelp {
		fmt.Println("arpspoof sends specially crafted ARP packets to a given target on a LAN in")
		fmt.Println("order to alter the target's ARP cache table and make the target send network")
		fmt.Println("packets to the user's machine instead of to the legitimate host.")
		fmt.Println("")
		fmt.Println("Kernel IP forwarding must be turned on ahead of time.")
		fmt.Println("")
		fmt.Println("Usage: ")
		fmt.Println("arpspoof [-i interface] -t target host")
		fmt.Println("")
		flag.PrintDefaults()
		os.Exit(0)
	}

	if *flagWaitInterval < 0.1 {
		*flagWaitInterval = 0.1
	}

	if *flagTarget == "" {
		log.Fatal("Missing target (-t 192.168.1.7).")
	}

	iface, err := net.InterfaceByName(*flagInterface)
	if err != nil {
		log.Fatalf("Could not use interface %s: %v", *flagInterface, err)
	}

	handler, err := pcap.OpenLive(iface.Name, 65535, true, pcap.BlockForever)
	if err != nil {
		log.Fatal(err)
	}
	defer handler.Close()

	var ifaceAddr *net.IPNet
	ifaceAddrs, err := iface.Addrs()
	if err != nil {
		log.Fatal(err)
	}

	for _, addr := range ifaceAddrs {
		if ipnet, ok := addr.(*net.IPNet); ok {
			if ip4 := ipnet.IP.To4(); ip4 != nil {
				ifaceAddr = &net.IPNet{
					IP:   ip4,
					Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff}),
				}
				break
			}
		}
	}
	if ifaceAddr == nil {
		log.Fatal("Could not get interface address.")
	}

	var targetAddrs []net.IP
	if *flagTarget != "" {
		addrRange, err := targetparser.Parse(*flagTarget)
		if err != nil {
			log.Fatal("Wrong format for target.")
		}
		targetAddrs = expandIPRange(ipRange(addrRange.Min, addrRange.Max))
		if len(targetAddrs) == 0 {
			log.Fatalf("No valid targets given.")
		}
	}

	hostIP := ifaceAddr.IP
	if argHostIP := flag.Arg(0); argHostIP != "" {
		hostIP = net.ParseIP(argHostIP)
		if hostIP == nil {
			log.Fatalf("Wrong format for host IP.")
		}
		hostIP = hostIP.To4()
	}

	stop := make(chan struct{}, 2)

	// Waiting for ^C
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt)
	go func() {
		for {
			select {
			case <-c:
				close(stop)
				return
			}
		}
	}()

	go readARP(handler, stop, iface)

	// Get original source
	origSrc, err := arp.Lookup(hostIP.To4().String())
	if err != nil {
		log.Fatalf("Unable to lookup hw address for %s: %v", hostIP, err)
	}

	fakeSrc := arp.Address{
		IP:           hostIP,
		HardwareAddr: iface.HardwareAddr,
	}

	<-writeARP(handler, stop, targetAddrs, &fakeSrc, time.Duration(*flagWaitInterval*1000.0)*time.Millisecond)

	<-cleanUpAndReARP(handler, targetAddrs, origSrc)

	os.Exit(0)
}

func cleanUpAndReARP(handler *pcap.Handle, targetAddrs []net.IP, src *arp.Address) chan struct{} {
	log.Printf("Cleaning up and re-ARPing targets...")

	stopReARPing := make(chan struct{})
	go func() {
		t := time.NewTicker(time.Second * 5)
		<-t.C
		close(stopReARPing)
	}()

	return writeARP(handler, stopReARPing, targetAddrs, src, 500*time.Millisecond)
}

func writeARP(handler *pcap.Handle, stop chan struct{}, targetAddrs []net.IP, src *arp.Address, waitInterval time.Duration) chan struct{} {
	stoppedWriting := make(chan struct{})
	go func(stoppedWriting chan struct{}) {
		t := time.NewTicker(waitInterval)
		for {
			select {
			case <-stop:
				stoppedWriting <- struct{}{}
				return
			case <-t.C:
				for _, ip := range targetAddrs {
					arpAddr, err := arp.Lookup(ip.String())
					if err != nil {
						log.Printf("Could not retrieve %v's MAC address: %v", ip, err)
						continue
					}
					dst := &arp.Address{
						IP:           ip,
						HardwareAddr: arpAddr.HardwareAddr,
					}
					buf, err := arp.NewARPRequest(src, dst)
					if err != nil {
						log.Print("NewARPRequest: ", err)
						continue
					}
					if err := handler.WritePacketData(buf); err != nil {
						log.Print("WritePacketData: ", err)
					}
				}
			}
		}
	}(stoppedWriting)
	return stoppedWriting
}

func readARP(handle *pcap.Handle, stop chan struct{}, iface *net.Interface) {
	src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	in := src.Packets()
	for {
		var packet gopacket.Packet
		select {
		case <-stop:
			return
		case packet = <-in:
			arpLayer := packet.Layer(layers.LayerTypeARP)
			if arpLayer == nil {
				continue
			}
			packet := arpLayer.(*layers.ARP)
			if !bytes.Equal([]byte(iface.HardwareAddr), packet.SourceHwAddress) {
				continue
			}
			if packet.Operation == layers.ARPReply {
				arp.Add(net.IP(packet.SourceProtAddress), net.HardwareAddr(packet.SourceHwAddress))
			}
			log.Printf("ARP packet (%d): %v (%v) -> %v (%v)", packet.Operation, net.IP(packet.SourceProtAddress), net.HardwareAddr(packet.SourceHwAddress), net.IP(packet.DstProtAddress), net.HardwareAddr(packet.DstHwAddress))
		}
	}
}
<commit_msg>changed import path<commit_after>// Copyright (c) 2016 José Nieto, https://menteslibres.net/xiam
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"github.com/xiam/arpfox/arp"

	"github.com/xiam/arpfox/targetparser"
)

var (
	flagInterface    = flag.String("i", "eth0", `Network interface.`)
	flagTarget       = flag.String("t", "", `Target host(s). Provide a single IP: "1.2.3.4", a list of IPs: "1.2.3.4, 5.6.7.8", a CIDR block "1.2.3.0/24" or an IP range: "1.2.3-7.4-12"`)
	flagWaitInterval = flag.Float64("w", 5.0, `Wait <w> seconds between every broadcast, <w> must be a value greater than 0.1.`)
	flagHelp         = flag.Bool("h", false, `Print usage instructions and exit.`)
)

func main() {
	flag.Parse()

	if *flagHelp {
		fmt.Println("arpspoof sends specially crafted ARP packets to a given target on a LAN in")
		fmt.Println("order to alter the target's ARP cache table and make the target send network")
		fmt.Println("packets to the user's machine instead of to the legitimate host.")
		fmt.Println("")
		fmt.Println("Kernel IP forwarding must be turned on ahead of time.")
		fmt.Println("")
		fmt.Println("Usage: ")
		fmt.Println("arpspoof [-i interface] -t target host")
		fmt.Println("")
		flag.PrintDefaults()
		os.Exit(0)
	}

	if *flagWaitInterval < 0.1 {
		*flagWaitInterval = 0.1
	}

	if *flagTarget == "" {
		log.Fatal("Missing target (-t 192.168.1.7).")
	}

	iface, err := net.InterfaceByName(*flagInterface)
	if err != nil {
		log.Fatalf("Could not use interface %s: %v", *flagInterface, err)
	}

	handler, err := pcap.OpenLive(iface.Name, 65535, true, pcap.BlockForever)
	if err != nil {
		log.Fatal(err)
	}
	defer handler.Close()

	var ifaceAddr *net.IPNet
	ifaceAddrs, err := iface.Addrs()
	if err != nil {
		log.Fatal(err)
	}

	for _, addr := range ifaceAddrs {
		if ipnet, ok := addr.(*net.IPNet); ok {
			if ip4 := ipnet.IP.To4(); ip4 != nil {
				ifaceAddr = &net.IPNet{
					IP:   ip4,
					Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff}),
				}
				break
			}
		}
	}
	if ifaceAddr == nil {
		log.Fatal("Could not get interface address.")
	}

	var targetAddrs []net.IP
	if *flagTarget != "" {
		addrRange, err := targetparser.Parse(*flagTarget)
		if err != nil {
			log.Fatal("Wrong format for target.")
		}
		targetAddrs = expandIPRange(ipRange(addrRange.Min, addrRange.Max))
		if len(targetAddrs) == 0 {
			log.Fatalf("No valid targets given.")
		}
	}

	hostIP := ifaceAddr.IP
	if argHostIP := flag.Arg(0); argHostIP != "" {
		hostIP = net.ParseIP(argHostIP)
		if hostIP == nil {
			log.Fatalf("Wrong format for host IP.")
		}
		hostIP = hostIP.To4()
	}

	stop := make(chan struct{}, 2)

	// Waiting for ^C
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt)
	go func() {
		for {
			select {
			case <-c:
				close(stop)
				return
			}
		}
	}()

	go readARP(handler, stop, iface)

	// Get original source
	origSrc, err := arp.Lookup(hostIP.To4().String())
	if err != nil {
		log.Fatalf("Unable to lookup hw address for %s: %v", hostIP, err)
	}

	fakeSrc := arp.Address{
		IP:           hostIP,
		HardwareAddr: iface.HardwareAddr,
	}

	<-writeARP(handler, stop, targetAddrs, &fakeSrc, time.Duration(*flagWaitInterval*1000.0)*time.Millisecond)

	<-cleanUpAndReARP(handler, targetAddrs, origSrc)

	os.Exit(0)
}

func cleanUpAndReARP(handler *pcap.Handle, targetAddrs []net.IP, src *arp.Address) chan struct{} {
	log.Printf("Cleaning up and re-ARPing targets...")

	stopReARPing := make(chan struct{})
	go func() {
		t := time.NewTicker(time.Second * 5)
		<-t.C
		close(stopReARPing)
	}()

	return writeARP(handler, stopReARPing, targetAddrs, src, 500*time.Millisecond)
}

func writeARP(handler *pcap.Handle, stop chan struct{}, targetAddrs []net.IP, src *arp.Address, waitInterval time.Duration) chan struct{} {
	stoppedWriting := make(chan struct{})
	go func(stoppedWriting chan struct{}) {
		t := time.NewTicker(waitInterval)
		for {
			select {
			case <-stop:
				stoppedWriting <- struct{}{}
				return
			case <-t.C:
				for _, ip := range targetAddrs {
					arpAddr, err := arp.Lookup(ip.String())
					if err != nil {
						log.Printf("Could not retrieve %v's MAC address: %v", ip, err)
						continue
					}
					dst := &arp.Address{
						IP:           ip,
						HardwareAddr: arpAddr.HardwareAddr,
					}
					buf, err := arp.NewARPRequest(src, dst)
					if err != nil {
						log.Print("NewARPRequest: ", err)
						continue
					}
					if err := handler.WritePacketData(buf); err != nil {
						log.Print("WritePacketData: ", err)
					}
				}
			}
		}
	}(stoppedWriting)
	return stoppedWriting
}

func readARP(handle *pcap.Handle, stop chan struct{}, iface *net.Interface) {
	src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	in := src.Packets()
	for {
		var packet gopacket.Packet
		select {
		case <-stop:
			return
		case packet = <-in:
			arpLayer := packet.Layer(layers.LayerTypeARP)
			if arpLayer == nil {
				continue
			}
			packet := arpLayer.(*layers.ARP)
			if !bytes.Equal([]byte(iface.HardwareAddr), packet.SourceHwAddress) {
				continue
			}
			if packet.Operation == layers.ARPReply {
				arp.Add(net.IP(packet.SourceProtAddress), net.HardwareAddr(packet.SourceHwAddress))
			}
			log.Printf("ARP packet (%d): %v (%v) -> %v (%v)", packet.Operation, net.IP(packet.SourceProtAddress), net.HardwareAddr(packet.SourceHwAddress), net.IP(packet.DstProtAddress), net.HardwareAddr(packet.DstHwAddress))
		}
	}
}
<|endoftext|>


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

package cbauth

import (
	"crypto/tls"
	"encoding/json"
	"net/http"
	"os"
	"strings"
)

// SetRequestAuthVia sets basic auth header in given http request
// according to given authenticator. It will extract target
// hostname/port from request and figure out right service credentials
// for that endpoint. If nil authenticator is passed, Default
// authenticator is used.
func SetRequestAuthVia(req *http.Request, a Authenticator) error {
	return WithAuthenticator(a, func(a Authenticator) (err error) {
		user, pwd, err := a.GetHTTPServiceAuth(req.URL.Host)
		if err != nil {
			return
		}
		req.SetBasicAuth(user, pwd)
		return
	})
}

// SetRequestAuth sets basic auth header in given http request
// according to default authenticator. Simply calls SetRequestAuthVia
// with nil authenticator.
func SetRequestAuth(req *http.Request) error {
	return SetRequestAuthVia(req, nil)
}

func duplicateStringsSlice(in []string) []string {
	return append([]string{}, in...)
}

func dupHeaders(h http.Header) http.Header {
	rv := make(http.Header)
	for k, v := range h {
		rv[k] = duplicateStringsSlice(v)
	}
	return rv
}

func dupRequest(req *http.Request) *http.Request {
	rv := *req
	rv.Header = dupHeaders(req.Header)
	rv.Trailer = dupHeaders(req.Trailer)
	return &rv
}

type cbauthRoundTripper struct {
	slave http.RoundTripper
	a     Authenticator
}

func (rt *cbauthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req = dupRequest(req)
	if err := SetRequestAuthVia(req, rt.a); err != nil {
		return nil, err
	}
	return rt.slave.RoundTrip(req)
}

// WrapHTTPTransport constructs http transport that automatically does
// SetRequestAuthVia for requests it sends. As usual, if nil
// authenticator is passed, default authenticator is used.
func WrapHTTPTransport(transport http.RoundTripper, a Authenticator) http.RoundTripper {
	return &cbauthRoundTripper{
		slave: transport,
		a:     a,
	}
}

// SendUnauthorized sends 401 Unauthorized response on given response writer.
func SendUnauthorized(w http.ResponseWriter) {
	w.Header().Set("WWW-Authenticate", "Basic realm=\"Couchbase\"")
	http.Error(w, "Authentication Failure.", http.StatusUnauthorized)
}

// ForbiddenJSON returns json 403 response for given permission
func ForbiddenJSON(permission string) ([]byte, error) {
	jsonStruct := map[string]interface{}{
		"message":     "Forbidden. User needs one of the following permissions",
		"permissions": [...]string{permission},
	}
	return json.Marshal(jsonStruct)
}

// SendForbidden sends 403 Forbidden with json payload that contains list
// of required permissions to response on given response writer.
func SendForbidden(w http.ResponseWriter, permission string) error {
	b, err := ForbiddenJSON(permission)
	if err != nil {
		return err
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusForbidden)
	w.Write(b)
	return nil
}

var ciphersHigh = []uint16{
	tls.TLS_RSA_WITH_AES_128_CBC_SHA,
	tls.TLS_RSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}

var ciphersMedium = []uint16{
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}

type tlsConfig struct {
	MinTLSVersion   string
	CiphersStrength []string
}

func getTLSConfig() tlsConfig {
	res := tlsConfig{}
	v := os.Getenv("CBAUTH_TLS_CONFIG")
	if err := json.Unmarshal([]byte(v), &res); err != nil {
		panic(err)
	}
	return res
}

func CipherSuites() []uint16 {
	config := getTLSConfig()

	high := false
	medium := false

	for _, val := range config.CiphersStrength {
		val = strings.TrimSpace(val)
		if strings.EqualFold(val, "high") {
			high = true
		} else if strings.EqualFold(val, "medium") {
			medium = true
		}
	}

	if high && medium {
		return append(ciphersHigh, ciphersMedium...)
	} else if medium {
		return ciphersMedium
	} else {
		return ciphersHigh
	}
}

func MinTLSVersion() uint16 {
	config := getTLSConfig()

	switch strings.ToLower(config.MinTLSVersion) {
	case "tlsv1":
		return tls.VersionTLS10
	case "tlsv1.1":
		return tls.VersionTLS11
	case "tlsv1.2":
		return tls.VersionTLS12
	default:
		return tls.VersionTLS10
	}
}
<commit_msg>MB-25518 Add check to avoid panic if TLS_CONFIG is not set.<commit_after>// @author Couchbase <info@couchbase.com>
// @copyright 2014 Couchbase, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cbauth

import (
	"crypto/tls"
	"encoding/json"
	"net/http"
	"os"
	"strings"
)

// SetRequestAuthVia sets basic auth header in given http request
// according to given authenticator. It will extract target
// hostname/port from request and figure out right service credentials
// for that endpoint. If nil authenticator is passed, Default
// authenticator is used.
func SetRequestAuthVia(req *http.Request, a Authenticator) error {
	return WithAuthenticator(a, func(a Authenticator) (err error) {
		user, pwd, err := a.GetHTTPServiceAuth(req.URL.Host)
		if err != nil {
			return
		}
		req.SetBasicAuth(user, pwd)
		return
	})
}

// SetRequestAuth sets basic auth header in given http request
// according to default authenticator. Simply calls SetRequestAuthVia
// with nil authenticator.
func SetRequestAuth(req *http.Request) error {
	return SetRequestAuthVia(req, nil)
}

func duplicateStringsSlice(in []string) []string {
	return append([]string{}, in...)
}

func dupHeaders(h http.Header) http.Header {
	rv := make(http.Header)
	for k, v := range h {
		rv[k] = duplicateStringsSlice(v)
	}
	return rv
}

func dupRequest(req *http.Request) *http.Request {
	rv := *req
	rv.Header = dupHeaders(req.Header)
	rv.Trailer = dupHeaders(req.Trailer)
	return &rv
}

type cbauthRoundTripper struct {
	slave http.RoundTripper
	a     Authenticator
}

func (rt *cbauthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req = dupRequest(req)
	if err := SetRequestAuthVia(req, rt.a); err != nil {
		return nil, err
	}
	return rt.slave.RoundTrip(req)
}

// WrapHTTPTransport constructs http transport that automatically does
// SetRequestAuthVia for requests it sends. As usual, if nil
// authenticator is passed, default authenticator is used.
func WrapHTTPTransport(transport http.RoundTripper, a Authenticator) http.RoundTripper {
	return &cbauthRoundTripper{
		slave: transport,
		a:     a,
	}
}

// SendUnauthorized sends 401 Unauthorized response on given response writer.
func SendUnauthorized(w http.ResponseWriter) {
	w.Header().Set("WWW-Authenticate", "Basic realm=\"Couchbase\"")
	http.Error(w, "Authentication Failure.", http.StatusUnauthorized)
}

// ForbiddenJSON returns json 403 response for given permission
func ForbiddenJSON(permission string) ([]byte, error) {
	jsonStruct := map[string]interface{}{
		"message":     "Forbidden. User needs one of the following permissions",
		"permissions": [...]string{permission},
	}
	return json.Marshal(jsonStruct)
}

// SendForbidden sends 403 Forbidden with json payload that contains list
// of required permissions to response on given response writer.
func SendForbidden(w http.ResponseWriter, permission string) error {
	b, err := ForbiddenJSON(permission)
	if err != nil {
		return err
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusForbidden)
	w.Write(b)
	return nil
}

var ciphersHigh = []uint16{
	tls.TLS_RSA_WITH_AES_128_CBC_SHA,
	tls.TLS_RSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}

var ciphersMedium = []uint16{
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}

type tlsConfig struct {
	MinTLSVersion   string
	CiphersStrength []string
}

func getTLSConfig() tlsConfig {
	res := tlsConfig{}
	v := os.Getenv("CBAUTH_TLS_CONFIG")
	if len(strings.TrimSpace(v)) != 0 {
		if err := json.Unmarshal([]byte(v), &res); err != nil {
			panic(err)
		}
	}

	return res
}

func CipherSuites() []uint16 {
	config := getTLSConfig()

	high := false
	medium := false

	for _, val := range config.CiphersStrength {
		val = strings.TrimSpace(val)
		if strings.EqualFold(val, "high") {
			high = true
		} else if strings.EqualFold(val, "medium") {
			medium = true
		}
	}

	if high && medium {
		return append(ciphersHigh, ciphersMedium...)
	} else if medium {
		return ciphersMedium
	} else {
		return ciphersHigh
	}
}

func MinTLSVersion() uint16 {
	config := getTLSConfig()

	switch strings.ToLower(config.MinTLSVersion) {
	case "tlsv1":
		return tls.VersionTLS10
	case "tlsv1.1":
		return tls.VersionTLS11
	case "tlsv1.2":
		return tls.VersionTLS12
	default:
		return tls.VersionTLS10
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"go/format"
	"os"
	"sort"

	schema "github.com/lestrrat/go-jsschema"
	jsval "github.com/lestrrat/go-jsval"
	"github.com/pkg/errors"

	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

const (
	version = "0.0.1"
)

var (
	app = kingpin.New("prmdg", "prmd generated JSON Hyper Schema to Go")
	pkg = app.Flag("package", "package name for Go file").Default("main").Short('p').String()
	fp  = app.Flag("file", "path JSON Schema").Required().Short('f').String()
	op  = app.Flag("output", "path to Go output file").Short('o').String()

	structCmd = app.Command("struct", "generate struct file")
	jsValCmd  = app.Command(
		"jsval", "generate validator file using github.com/lestrrat/go-jsval")
	validatorCmd = app.Command(
		"validator", "generate validator file using github.com/go-playground/validator")

	scValidator = structCmd.Flag("validate-tag", "add `validate` tag to struct").Bool()
	scUseTitle  = structCmd.Flag("use-title", "use title tag in request/response struct name").Bool()
	scNullable  = structCmd.Flag("nullable", "use github.com/guregu/null for not required value").Bool()
)

func main() {
	cmd := kingpin.MustParse(app.Parse(os.Args[1:]))

	switch cmd {
	case structCmd.FullCommand():
		if err := generateStructFile(pkg, *fp, op, *scValidator, *scUseTitle); err != nil {
			app.Errorf("failed to generate struct file: %s", err)
		}
	case jsValCmd.FullCommand():
		if err := generateJsValValidatorFile(pkg, *fp, op); err != nil {
			app.Errorf("failed to generate jsval validator file: %s", err)
		}
	case validatorCmd.FullCommand():
		if err := generateValidatorFile(pkg, *fp, op); err != nil {
			app.Errorf("failed to generate validator file: %s", err)
		}
	}
}

func generateValidatorFile(pkg *string, fp string, op *string) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	vals, err := parser.ParseValidators()
	if err != nil {
		return err
	}
	var src []byte
	src = append(src, []byte(fmt.Sprintf("package %s\n\n", *pkg))...)
	ss, err := format.Source(vals.Render())
	if err != nil {
		return err
	}
	src = append(src, ss...)
	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
	} else {
		out = os.Stdout
	}
	if _, err := out.Write(src); err != nil {
		return err
	}
	return nil
}

func generateStructFile(pkg *string, fp string, op *string, val bool, useTitle bool) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	resources, err := parser.ParseResources()
	if err != nil {
		return err
	}
	links, err := parser.ParseActions(resources)
	if err != nil {
		return err
	}

	var src []byte
	src = append(src, []byte(fmt.Sprintf("package %s\n\n", *pkg))...)

	var resKeys []string
	for key := range resources {
		resKeys = append(resKeys, key)
	}
	stOpt := FormatOption{
		Validator: val,
		Schema:    false,
		UseTitle:  useTitle,
	}
	sort.Strings(resKeys)
	for _, k := range resKeys {
		res := resources[k]
		ss, err := format.Source(res.Struct(stOpt))
		if err != nil {
			return errors.Wrapf(err, "failed to format resource: %s: %s", res.Name, res.Title)
		}
		src = append(src, ss...)
	}

	var linkKeys []string
	for key := range links {
		linkKeys = append(linkKeys, key)
	}
	sort.Strings(linkKeys)
	for _, k := range linkKeys {
		actions := links[k]
		for _, action := range actions {
			var reqOpt FormatOption
			if action.Method == "GET" {
				reqOpt = FormatOption{
					Validator: val,
					Schema:    true,
					UseTitle:  useTitle,
				}
			} else {
				reqOpt = FormatOption{
					Validator: val,
					Schema:    false,
					UseTitle:  useTitle,
				}
			}
			req, err := format.Source(action.RequestStruct(reqOpt))
			if err != nil {
				return errors.Wrapf(err, "failed to format request struct: %s, %s", k, action.Href)
			}
			src = append(src, req...)
			resp, err := format.Source(action.ResponseStruct(reqOpt))
			if err != nil {
				return errors.Wrapf(err, "failed to format response struct: %s, %s", k, action.Href)
			}
			src = append(src, resp...)
		}
	}

	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
	} else {
		out = os.Stdout
	}
	if _, err := out.Write(src); err != nil {
		return err
	}
	return nil
}

func generateJsValValidatorFile(pkg *string, fp string, op *string) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	validators, err := parser.ParseJsValValidators()
	if err != nil {
		return err
	}
	generator := jsval.NewGenerator()
	var src bytes.Buffer
	fmt.Fprintf(&src, "package %s\n", *pkg)
	fmt.Fprint(&src, "import \"github.com/lestrrat/go-jsval\"\n")
	if err := generator.Process(&src, validators...); err != nil {
		return err
	}

	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
	} else {
		out = os.Stdout
	}
	if _, err := out.Write(src.Bytes()); err != nil {
		return err
	}
	return nil
}
<commit_msg>Add goimport command<commit_after>package main

import (
	"bytes"
	"fmt"
	"go/format"
	"os"
	"os/exec"
	"sort"

	schema "github.com/lestrrat/go-jsschema"
	jsval "github.com/lestrrat/go-jsval"
	"github.com/pkg/errors"

	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

const (
	version = "0.0.1"
)

var (
	app = kingpin.New("prmdg", "prmd generated JSON Hyper Schema to Go")
	pkg = app.Flag("package", "package name for Go file").Default("main").Short('p').String()
	fp  = app.Flag("file", "path JSON Schema").Required().Short('f').String()
	op  = app.Flag("output", "path to Go output file").Short('o').String()

	structCmd = app.Command("struct", "generate struct file")
	jsValCmd  = app.Command(
		"jsval", "generate validator file using github.com/lestrrat/go-jsval")
	validatorCmd = app.Command(
		"validator", "generate validator file using github.com/go-playground/validator")

	scValidator = structCmd.Flag("validate-tag", "add `validate` tag to struct").Bool()
	scUseTitle  = structCmd.Flag("use-title", "use title tag in request/response struct name").Bool()
	scNullable  = structCmd.Flag("nullable", "use github.com/guregu/null for not required value").Bool()
)

func main() {
	cmd := kingpin.MustParse(app.Parse(os.Args[1:]))

	switch cmd {
	case structCmd.FullCommand():
		if err := generateStructFile(pkg, *fp, op, *scValidator, *scUseTitle); err != nil {
			app.Errorf("failed to generate struct file: %s", err)
		}
	case jsValCmd.FullCommand():
		if err := generateJsValValidatorFile(pkg, *fp, op); err != nil {
			app.Errorf("failed to generate jsval validator file: %s", err)
		}
	case validatorCmd.FullCommand():
		if err := generateValidatorFile(pkg, *fp, op); err != nil {
			app.Errorf("failed to generate validator file: %s", err)
		}
	}
}

func generateValidatorFile(pkg *string, fp string, op *string) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	vals, err := parser.ParseValidators()
	if err != nil {
		return err
	}
	var src []byte
	src = append(src, []byte(fmt.Sprintf("package %s\n\n", *pkg))...)
	ss, err := format.Source(vals.Render())
	if err != nil {
		return err
	}
	src = append(src, ss...)
	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
		if _, err := out.Write(src); err != nil {
			return err
		}
		params := []string{"-w", *op}
		if err := exec.Command("goimports", params...).Run(); err != nil {
			return err
		}
	} else {
		if _, err := os.Stdout.Write(src); err != nil {
			return err
		}
	}
	return nil
}

func generateStructFile(pkg *string, fp string, op *string, val bool, useTitle bool) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	resources, err := parser.ParseResources()
	if err != nil {
		return err
	}
	links, err := parser.ParseActions(resources)
	if err != nil {
		return err
	}

	var src []byte
	src = append(src, []byte(fmt.Sprintf("package %s\n\n", *pkg))...)

	var resKeys []string
	for key := range resources {
		resKeys = append(resKeys, key)
	}
	stOpt := FormatOption{
		Validator: val,
		Schema:    false,
		UseTitle:  useTitle,
	}
	sort.Strings(resKeys)
	for _, k := range resKeys {
		res := resources[k]
		ss, err := format.Source(res.Struct(stOpt))
		if err != nil {
			return errors.Wrapf(err, "failed to format resource: %s: %s", res.Name, res.Title)
		}
		src = append(src, ss...)
	}

	var linkKeys []string
	for key := range links {
		linkKeys = append(linkKeys, key)
	}
	sort.Strings(linkKeys)
	for _, k := range linkKeys {
		actions := links[k]
		for _, action := range actions {
			var reqOpt FormatOption
			if action.Method == "GET" {
				reqOpt = FormatOption{
					Validator: val,
					Schema:    true,
					UseTitle:  useTitle,
				}
			} else {
				reqOpt = FormatOption{
					Validator: val,
					Schema:    false,
					UseTitle:  useTitle,
				}
			}
			req, err := format.Source(action.RequestStruct(reqOpt))
			if err != nil {
				return errors.Wrapf(err, "failed to format request struct: %s, %s", k, action.Href)
			}
			src = append(src, req...)
			resp, err := format.Source(action.ResponseStruct(reqOpt))
			if err != nil {
				return errors.Wrapf(err, "failed to format response struct: %s, %s", k, action.Href)
			}
			src = append(src, resp...)
		}
	}

	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
		if _, err := out.Write(src); err != nil {
			return err
		}
		params := []string{"-w", *op}
		if err := exec.Command("goimports", params...).Run(); err != nil {
			return err
		}
	} else {
		if _, err := os.Stdout.Write(src); err != nil {
			return err
		}
	}
	return nil
}

func generateJsValValidatorFile(pkg *string, fp string, op *string) error {
	sc, err := schema.ReadFile(fp)
	if err != nil {
		return errors.Wrapf(err, "failed to read %s", fp)
	}
	parser := NewParser(sc, *pkg)
	validators, err := parser.ParseJsValValidators()
	if err != nil {
		return err
	}
	generator := jsval.NewGenerator()
	var src bytes.Buffer
	fmt.Fprintf(&src, "package %s\n", *pkg)
	fmt.Fprint(&src, "import \"github.com/lestrrat/go-jsval\"\n")
	if err := generator.Process(&src, validators...); err != nil {
		return err
	}

	var out *os.File
	if *op != "" {
		out, err = os.Create(*op)
		if err != nil {
			return errors.Wrapf(err, "failed to create %s", *op)
		}
		defer out.Close()
		if _, err := out.Write(src.Bytes()); err != nil {
			return err
		}
		params := []string{"-w", *op}
		if err := exec.Command("goimports", params...).Run(); err != nil {
			return err
		}
	} else {
		if _, err := os.Stdout.Write(src.Bytes()); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"text/template"
)

const postsPerPage = 10
const version = "1.0"

var repo *FileRepository
var config *Config
var themePath string

func home(w http.ResponseWriter, req *http.Request) {

	id, err := strconv.Atoi(req.URL.Query().Get("p"))

	if err == nil {

		post, _ := repo.PostWithId(id)
		showSinglePost(post, w, req)

		return
	}

	term := req.URL.Query().Get("search")
	pageNumber, err := strconv.ParseInt(req.URL.Query().Get("page"), 10, 32)

	if err != nil {
		pageNumber = 0
	} else {

		// We want to use 0-based page numbers internally, but expose them as
		// 1-based.
		pageNumber -= 1

		if pageNumber < 0 {
			pageNumber = 0
		}
	}

	var previousURL string
	var nextURL string

	posts, count := repo.SearchPosts(term, int(pageNumber)*postsPerPage, postsPerPage)

	if pageNumber > 0 {
		if len(term) > 0 {
			nextURL = fmt.Sprintf("/?search=%v&page=%v", term, pageNumber)
		} else {
			nextURL = fmt.Sprintf("/?page=%v", pageNumber)
		}
	}

	if int(pageNumber+1) < count/postsPerPage {
		if len(term) > 0 {
			previousURL = fmt.Sprintf("/?search=%v&page=%v", term, pageNumber+2)
		} else {
			previousURL = fmt.Sprintf("/?page=%v", pageNumber+2)
		}
	}

	page := struct {
		Posts       BlogPosts
		Config      *Config
		NextURL     string
		PreviousURL string
	}{
		posts,
		config,
		nextURL,
		previousURL,
	}

	t, _ := template.ParseFiles(themePath + "/templates/home.html")
	t.Execute(w, page)
}

func taggedPosts(w http.ResponseWriter, req *http.Request) {

	tag := req.URL.Query().Get(":tag")
	pageNumber, err := strconv.ParseInt(req.URL.Query().Get(":page"), 10, 32)

	if err != nil {
		pageNumber = 0
	} else {

		// We want to use 0-based page numbers internally, but expose them as
		// 1-based.
		pageNumber -= 1

		if pageNumber < 0 {
			pageNumber = 0
		}
	}

	var previousURL string
	var nextURL string

	posts, count := repo.PostsWithTag(tag, int(pageNumber)*postsPerPage, postsPerPage)

	if pageNumber > 0 {
		nextURL = fmt.Sprintf("/tags/%v/%v", tag, pageNumber)
	}

	if int(pageNumber) < count/postsPerPage {
		previousURL = fmt.Sprintf("/tags/%v/%v", tag, pageNumber+2)
	}

	page := struct {
		Posts       BlogPosts
		Config      *Config
		NextURL     string
		PreviousURL string
	}{
		posts,
		config,
		nextURL,
		previousURL,
	}

	t, _ := template.ParseFiles(themePath + "/templates/home.html")
	t.Execute(w, page)
}

func tags(w http.ResponseWriter, req *http.Request) {

	tags := repo.AllTags()

	page := struct {
		Tags   map[string]int
		Config *Config
	}{
		tags,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/tags.html")
	t.Execute(w, page)
}

func archive(w http.ResponseWriter, req *http.Request) {

	posts := repo.AllPosts()

	page := struct {
		Posts  BlogPosts
		Config *Config
	}{
		posts,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/archive.html")
	t.Execute(w, page)
}

func rss(w http.ResponseWriter, req *http.Request) {

	posts, _ := repo.SearchPosts("", 0, 10)

	page := struct {
		Posts      BlogPosts
		SiteConfig *Config
	}{
		posts,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/rss.html")
	t.Execute(w, page)
}

func printInfo() {
	fmt.Printf("Gobble Blogging Engine (version %v)\n", version)
	fmt.Println("http://simianzombie.com")
	fmt.Println("")
	fmt.Println("Copyright (C) 2013 Antony Dzeryn")
	fmt.Println("")
}

func loadConfig() {
	configPath := flag.String("config", "./gobble.conf", "config file path")
	flag.Parse()

	var err error

	config, err = LoadConfig(*configPath)

	if err != nil {
		log.Println("Could not load config file", *configPath)
		log.Fatal(err)
	}

	themePath = config.ThemePath + string(filepath.Separator) + config.Theme

	_, err = os.Stat(themePath)

	if err != nil {
		log.Fatal("Could not load theme", themePath)
	}

	_, err = os.Stat(config.PostPath)

	if err != nil {
		log.Fatal("Could not load posts from", config.PostPath)
	}
}

func prepareHandler() {

	repo = NewFileRepository(config.PostPath)

	m := pat.New()
	m.Get("/tags/:tag/:page", http.HandlerFunc(taggedPosts))
	m.Get("/tags/:tag", http.HandlerFunc(taggedPosts))
	m.Get("/tags/", http.HandlerFunc(tags))
	m.Get("/archive/", http.HandlerFunc(archive))
	m.Get("/rss/", http.HandlerFunc(rss))
	m.Get("/posts/:year/:month/:day/:title", http.HandlerFunc(post))
	m.Get("/", http.HandlerFunc(home))

	m.Post("/posts/:year/:month/:day/:title/comments", http.HandlerFunc(createComment))

	http.Handle("/", m)
	http.Handle("/theme/", http.StripPrefix("/theme/", http.FileServer(http.Dir(themePath))))
	http.Handle("/rainbow/", http.StripPrefix("/rainbow/", http.FileServer(http.Dir("rainbow"))))
	http.Handle("/media/", http.StripPrefix("/media/", http.FileServer(http.Dir(config.MediaPath))))

	fmt.Printf("Listening on port %v\n", config.Port)
	fmt.Printf("Using theme \"%v\"\n", config.Theme)
	fmt.Printf("Post data stored in \"%v\"\n", config.PostPath)
	fmt.Printf("Media stored in \"%v\"\n", config.MediaPath)
	fmt.Printf("Themes stored in \"%v\"\n", config.ThemePath)

	http.ListenAndServe(":"+strconv.FormatInt(config.Port, 10), nil)
}

func main() {
	printInfo()
	loadConfig()
	prepareHandler()
}
<commit_msg>Fixed RSS feed.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"text/template"
)

const postsPerPage = 10
const version = "1.0"

var repo *FileRepository
var config *Config
var themePath string

func home(w http.ResponseWriter, req *http.Request) {

	id, err := strconv.Atoi(req.URL.Query().Get("p"))

	if err == nil {

		post, _ := repo.PostWithId(id)
		showSinglePost(post, w, req)

		return
	}

	term := req.URL.Query().Get("search")
	pageNumber, err := strconv.ParseInt(req.URL.Query().Get("page"), 10, 32)

	if err != nil {
		pageNumber = 0
	} else {

		// We want to use 0-based page numbers internally, but expose them as
		// 1-based.
		pageNumber -= 1

		if pageNumber < 0 {
			pageNumber = 0
		}
	}

	var previousURL string
	var nextURL string

	posts, count := repo.SearchPosts(term, int(pageNumber)*postsPerPage, postsPerPage)

	if pageNumber > 0 {
		if len(term) > 0 {
			nextURL = fmt.Sprintf("/?search=%v&page=%v", term, pageNumber)
		} else {
			nextURL = fmt.Sprintf("/?page=%v", pageNumber)
		}
	}

	if int(pageNumber+1) < count/postsPerPage {
		if len(term) > 0 {
			previousURL = fmt.Sprintf("/?search=%v&page=%v", term, pageNumber+2)
		} else {
			previousURL = fmt.Sprintf("/?page=%v", pageNumber+2)
		}
	}

	page := struct {
		Posts       BlogPosts
		Config      *Config
		NextURL     string
		PreviousURL string
	}{
		posts,
		config,
		nextURL,
		previousURL,
	}

	t, _ := template.ParseFiles(themePath + "/templates/home.html")
	t.Execute(w, page)
}

func taggedPosts(w http.ResponseWriter, req *http.Request) {

	tag := req.URL.Query().Get(":tag")
	pageNumber, err := strconv.ParseInt(req.URL.Query().Get(":page"), 10, 32)

	if err != nil {
		pageNumber = 0
	} else {

		// We want to use 0-based page numbers internally, but expose them as
		// 1-based.
		pageNumber -= 1

		if pageNumber < 0 {
			pageNumber = 0
		}
	}

	var previousURL string
	var nextURL string

	posts, count := repo.PostsWithTag(tag, int(pageNumber)*postsPerPage, postsPerPage)

	if pageNumber > 0 {
		nextURL = fmt.Sprintf("/tags/%v/%v", tag, pageNumber)
	}

	if int(pageNumber) < count/postsPerPage {
		previousURL = fmt.Sprintf("/tags/%v/%v", tag, pageNumber+2)
	}

	page := struct {
		Posts       BlogPosts
		Config      *Config
		NextURL     string
		PreviousURL string
	}{
		posts,
		config,
		nextURL,
		previousURL,
	}

	t, _ := template.ParseFiles(themePath + "/templates/home.html")
	t.Execute(w, page)
}

func tags(w http.ResponseWriter, req *http.Request) {

	tags := repo.AllTags()

	page := struct {
		Tags   map[string]int
		Config *Config
	}{
		tags,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/tags.html")
	t.Execute(w, page)
}

func archive(w http.ResponseWriter, req *http.Request) {

	posts := repo.AllPosts()

	page := struct {
		Posts  BlogPosts
		Config *Config
	}{
		posts,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/archive.html")
	t.Execute(w, page)
}

func rss(w http.ResponseWriter, req *http.Request) {

	posts, _ := repo.SearchPosts("", 0, 10)

	page := struct {
		Posts      BlogPosts
		Config     *Config
	}{
		posts,
		config,
	}

	t, _ := template.ParseFiles(themePath + "/templates/rss.html")
	t.Execute(w, page)
}

func printInfo() {
	fmt.Printf("Gobble Blogging Engine (version %v)\n", version)
	fmt.Println("http://simianzombie.com")
	fmt.Println("")
	fmt.Println("Copyright (C) 2013 Antony Dzeryn")
	fmt.Println("")
}

func loadConfig() {
	configPath := flag.String("config", "./gobble.conf", "config file path")
	flag.Parse()

	var err error

	config, err = LoadConfig(*configPath)

	if err != nil {
		log.Println("Could not load config file", *configPath)
		log.Fatal(err)
	}

	themePath = config.ThemePath + string(filepath.Separator) + config.Theme

	_, err = os.Stat(themePath)

	if err != nil {
		log.Fatal("Could not load theme", themePath)
	}

	_, err = os.Stat(config.PostPath)

	if err != nil {
		log.Fatal("Could not load posts from", config.PostPath)
	}
}

func prepareHandler() {

	repo = NewFileRepository(config.PostPath)

	m := pat.New()
	m.Get("/tags/:tag/:page", http.HandlerFunc(taggedPosts))
	m.Get("/tags/:tag", http.HandlerFunc(taggedPosts))
	m.Get("/tags/", http.HandlerFunc(tags))
	m.Get("/archive/", http.HandlerFunc(archive))
	m.Get("/rss", http.HandlerFunc(rss))
	m.Get("/posts/:year/:month/:day/:title", http.HandlerFunc(post))
	m.Get("/", http.HandlerFunc(home))

	m.Post("/posts/:year/:month/:day/:title/comments", http.HandlerFunc(createComment))

	http.Handle("/", m)
	http.Handle("/theme/", http.StripPrefix("/theme/", http.FileServer(http.Dir(themePath))))
	http.Handle("/rainbow/", http.StripPrefix("/rainbow/", http.FileServer(http.Dir("rainbow"))))
	http.Handle("/media/", http.StripPrefix("/media/", http.FileServer(http.Dir(config.MediaPath))))

	fmt.Printf("Listening on port %v\n", config.Port)
	fmt.Printf("Using theme \"%v\"\n", config.Theme)
	fmt.Printf("Post data stored in \"%v\"\n", config.PostPath)
	fmt.Printf("Media stored in \"%v\"\n", config.MediaPath)
	fmt.Printf("Themes stored in \"%v\"\n", config.ThemePath)

	http.ListenAndServe(":"+strconv.FormatInt(config.Port, 10), nil)
}

func main() {
	printInfo()
	loadConfig()
	prepareHandler()
}
<|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 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
	}
}
<commit_msg>add basic metricsHandler<commit_after>package main

import (
	"encoding/json"
	"flag"
	"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

	// metrics collection
	metricsC *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")
	metricsC = session.DB("recon-dev").C("metrics")

	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")
	switch r.Method {
	case "GET":
		var metrics []map[string]interface{}
		err := metricsC.Find(nil).All(&metrics)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		enc := json.NewEncoder(w)
		if err := enc.Encode(metrics); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	case "POST":
		var data map[string]interface{}
		dec := json.NewDecoder(r.Body)
		if err := dec.Decode(&data); err != nil {
			http.Error(w, "unable to decode json", http.StatusBadRequest)
			return
		}
		err := metricsC.Insert(data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusCreated)
		return
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}
}

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
	}
}
<|endoftext|>