<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"log"
	"mime"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"runtime"
	"time"

	"golang.org/x/crypto/acme/autocert"
	"golang.org/x/net/http2"
)

const version = "0.1"
const name = "simple-httpd"
const indexHTMLFile = "index.html"
const pathSeperator = "/"

const (
	cert    = "cert.pem"
	key     = "key.pem"
	certDir = "/.autocert"
)

// gitSHA is populated at build time from
// `-ldflags "-X main.gitSHA=$(shell git rev-parse HEAD)"`
var gitSHA string

// Data holds the data passed to the template engine
type Data struct {
	Name         string
	LastModified string
	URI          string
	Size         int64
}

// httpServer holds the relavent info/state
type httpServer struct {
	Directory string
	Port      int
	template  *template.Template
}

// requestData holds data about the request for logging
type requestData struct {
	Timestamp   string `json:"timestamp,omitempty"`
	Method      string `json:"method,omitempty"`
	HTTPVersion string `json:"http_version,omitempty"`
	RemoteAddr  string `json:"remote_addr,omitempty"`
	Path        string `json:"path,omitempty"`
	Status      int    `json:"status,omitempty"`
	UserAgent   string `json:"user_agent,omitempty"`
	Error       string `json:"error,omitempty,omitempty"`
}

func (r requestData) Format(f fmt.State, c rune) {
	switch c {
	case 'v', 's':
		enc := json.NewEncoder(f)
		enc.Encode(r)
	}
}

// setHeaders sets the base headers for all requests
func setHeaders(w http.ResponseWriter) {
	w.Header().Set("Server", name+pathSeperator+version)
	w.Header().Add("Date", time.Now().Format(time.RFC822))
}

// ServeHTTP handles inbound requests
func (h *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			http.Error(w, fmt.Sprintln(err), http.StatusInternalServerError)
			log.Printf("recovering from error: %s\n", err)
		}
	}()

	rd := requestData{
		Timestamp:  time.Now().Format("2006-01-02 15:04:05"),
		RemoteAddr: req.RemoteAddr,
		Method:     req.Method,
		Path:       req.RequestURI,
		UserAgent:  req.UserAgent(),
	}

	queryStr, err := url.QueryUnescape(req.RequestURI)
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusInternalServerError
		fmt.Println(rd)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	fullpath := filepath.Join(h.Directory, queryStr[1:])

	file, err := os.Open(fullpath)
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusNotFound
		fmt.Println(rd)
		http.NotFound(w, req)
		return
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusInternalServerError
		fmt.Println(rd)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	setHeaders(w)

	if stat.IsDir() {
		contents, err := file.Readdir(-1)
		if err != nil {
			rd.Status = http.StatusInternalServerError
			rd.Error = err.Error()
			fmt.Println(rd)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		files := make([]Data, 0, len(contents))
		for _, entry := range contents {
			if entry.Name() == indexHTMLFile {
				w.Header().Set("Content-type", "text/html; charset=UTF-8")
				w.Header().Set("Content-Length", fmt.Sprintf("%v", entry.Size()))

				hf, err := os.Open(fullpath + pathSeperator + entry.Name())
				if err != nil {
					fmt.Println(err)
					return
				}
				io.Copy(w, hf)

				rd.Status = http.StatusOK
				fmt.Println(rd)
				return
			}
			file := Data{
				Name:         entry.Name(),
				LastModified: entry.ModTime().Format(time.RFC1123),
				URI:          path.Join(queryStr, entry.Name()),
			}
			if entry.IsDir() {
				file.Name = entry.Name() + pathSeperator
				file.Size = entry.Size()
			}
			files = append(files, file)
		}

		rd.Status = http.StatusOK

		w.Header().Set("Content-type", "text/html; charset=UTF-8")

		h.template.Execute(w, map[string]interface{}{
			"files":           files,
			"version":         gitSHA,
			"port":            h.Port,
			"relativePath":    queryStr,
			"goVersion":       runtime.Version(),
			"parentDirectory": path.Dir(queryStr),
		})

		fmt.Println(rd)

		return
	}

	if mimetype := mime.TypeByExtension(path.Ext(file.Name())); mimetype != "" {
		fmt.Println(mimetype)
		w.Header().Set("Content-type", "text/html; charset=UTF-8")
	} else {
		w.Header().Set("Content-type", "application/octet-stream")
	}

	io.Copy(w, file)

	rd.Status = http.StatusOK
	fmt.Println(rd)
}

// serveTLS
func serveTLS(domain string, port int) error {
	u, err := user.Current()
	if err != nil {
		return err
	}
	cacheDir := u.HomeDir + certDir
	if err := os.MkdirAll(cacheDir, 0700); err != nil {
		return err
	}

	m := autocert.Manager{
		Cache:      autocert.DirCache(cacheDir),
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist(domain),
	}

	srv := &http.Server{
		TLSConfig: &tls.Config{
			GetCertificate: m.GetCertificate,
		},
	}

	http2.ConfigureServer(srv, &http2.Server{
		NewWriteScheduler: func() http2.WriteScheduler {
			return http2.NewPriorityWriteScheduler(nil)
		},
	})

	ln, err := net.ListenTCP("tcp", &net.TCPAddr{
		Port: port,
	})
	if err != nil {
		return err
	}

	return srv.Serve(tls.NewListener(keepAliveListener{ln}, srv.TLSConfig))
}

// keepAliveListener
type keepAliveListener struct {
	*net.TCPListener
}

// Accept
func (k keepAliveListener) Accept() (net.Conn, error) {
	tc, err := k.AcceptTCP()
	if err != nil {
		return nil, err
	}

	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(time.Minute * 3)

	return tc, nil
}

func getpwd() string {
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	return pwd
}

func homeDir() string {
	u, err := user.Current()
	if err != nil {
		return ""
	}

	return u.HomeDir
}

func main() {
	var port int
	var le string
	var gs bool

	pwd := getpwd()

	flag.IntVar(&port, "p", 8000, "bind port")
	flag.StringVar(&le, "l", "", "enable TLS with Let's Encrypt for the given domain name. Port = port + 1 ")
	flag.BoolVar(&gs, "g", false, "generate and use a self signed certificate")
	flag.Parse()

	if le != "" {
		var srv http.Server
		http2.ConfigureServer(&srv, new(http2.Server))

		tlsPort := port + 1

		go func() {
			fmt.Printf("Serving HTTPS on 0.0.0.0 port %v ...\n", tlsPort)
			log.Fatal(serveTLS(le, tlsPort))
		}()
	}

	h := &httpServer{
		Port:      port,
		Directory: pwd,
		template:  template.Must(template.New("listing").Parse(htmlTemplate)),
	}

	if gs {
		hd := homeDir()

		certPath := hd + certDir + pathSeperator + cert
		keyPath := hd + certDir + pathSeperator + key

		if err := generateCertificates(certPath, keyPath); err != nil {
			log.Fatalln(err)
		}

		fmt.Printf("Serving HTTPS on 0.0.0.0 port %v ...\n", h.Port+1)
		log.Fatal(http.ListenAndServeTLS(fmt.Sprintf("0.0.0.0:%d", port+1), certPath, keyPath, h))
	}

	fmt.Printf("Serving HTTP on 0.0.0.0 port %v ...\n", h.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), h))

}

const htmlTemplate = `
<!DOCTYPE html>

    <meta charset="utf-8">
    <title>simple-httpd</title>

Directory listing for {{.relativePath}}

        Name
		Last Modified
		Size

	    {{.parentDirectory}}

      {{range .files}}

	    {{.Name}}
		{{.LastModified}}
		{{.Size}}

      {{end}}

simple-httpd - {{.version}} / {{.goVersion}}

`
<commit_msg>Fix handling of URIs with ?queries<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"log"
	"mime"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"runtime"
	"time"

	"golang.org/x/crypto/acme/autocert"
	"golang.org/x/net/http2"
)

const version = "0.1"
const name = "simple-httpd"
const indexHTMLFile = "index.html"
const pathSeperator = "/"

const (
	cert    = "cert.pem"
	key     = "key.pem"
	certDir = "/.autocert"
)

// gitSHA is populated at build time from
// `-ldflags "-X main.gitSHA=$(shell git rev-parse HEAD)"`
var gitSHA string

// Data holds the data passed to the template engine
type Data struct {
	Name         string
	LastModified string
	URI          string
	Size         int64
}

// httpServer holds the relavent info/state
type httpServer struct {
	Directory string
	Port      int
	template  *template.Template
}

// requestData holds data about the request for logging
type requestData struct {
	Timestamp   string `json:"timestamp,omitempty"`
	Method      string `json:"method,omitempty"`
	HTTPVersion string `json:"http_version,omitempty"`
	RemoteAddr  string `json:"remote_addr,omitempty"`
	Path        string `json:"path,omitempty"`
	Status      int    `json:"status,omitempty"`
	UserAgent   string `json:"user_agent,omitempty"`
	Error       string `json:"error,omitempty,omitempty"`
}

func (r requestData) Format(f fmt.State, c rune) {
	switch c {
	case 'v', 's':
		enc := json.NewEncoder(f)
		enc.Encode(r)
	}
}

// setHeaders sets the base headers for all requests
func setHeaders(w http.ResponseWriter) {
	w.Header().Set("Server", name+pathSeperator+version)
	w.Header().Add("Date", time.Now().Format(time.RFC822))
}

// ServeHTTP handles inbound requests
func (h *httpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			http.Error(w, fmt.Sprintln(err), http.StatusInternalServerError)
			log.Printf("recovering from error: %s\n", err)
		}
	}()

	rd := requestData{
		Timestamp:  time.Now().Format("2006-01-02 15:04:05"),
		RemoteAddr: req.RemoteAddr,
		Method:     req.Method,
		Path:       req.RequestURI,
		UserAgent:  req.UserAgent(),
	}

	parsedURL, err := url.Parse(req.RequestURI)
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusInternalServerError
		fmt.Println(rd)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	escapedPath := parsedURL.EscapedPath()
	fullpath := filepath.Join(h.Directory, escapedPath[1:])

	file, err := os.Open(fullpath)
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusNotFound
		fmt.Println(rd)
		http.NotFound(w, req)
		return
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		rd.Error = err.Error()
		rd.Status = http.StatusInternalServerError
		fmt.Println(rd)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	setHeaders(w)

	if stat.IsDir() {
		contents, err := file.Readdir(-1)
		if err != nil {
			rd.Status = http.StatusInternalServerError
			rd.Error = err.Error()
			fmt.Println(rd)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		files := make([]Data, 0, len(contents))
		for _, entry := range contents {
			if entry.Name() == indexHTMLFile {
				w.Header().Set("Content-type", "text/html; charset=UTF-8")
				w.Header().Set("Content-Length", fmt.Sprintf("%v", entry.Size()))

				hf, err := os.Open(fullpath + pathSeperator + entry.Name())
				if err != nil {
					fmt.Println(err)
					return
				}
				io.Copy(w, hf)

				rd.Status = http.StatusOK
				fmt.Println(rd)
				return
			}
			file := Data{
				Name:         entry.Name(),
				LastModified: entry.ModTime().Format(time.RFC1123),
				URI:          path.Join(escapedPath, entry.Name()),
			}
			if entry.IsDir() {
				file.Name = entry.Name() + pathSeperator
				file.Size = entry.Size()
			}
			files = append(files, file)
		}

		rd.Status = http.StatusOK

		w.Header().Set("Content-type", "text/html; charset=UTF-8")

		h.template.Execute(w, map[string]interface{}{
			"files":           files,
			"version":         gitSHA,
			"port":            h.Port,
			"relativePath":    escapedPath,
			"goVersion":       runtime.Version(),
			"parentDirectory": path.Dir(escapedPath),
		})

		fmt.Println(rd)

		return
	}

	if mimetype := mime.TypeByExtension(path.Ext(file.Name())); mimetype != "" {
		fmt.Println(mimetype)
		w.Header().Set("Content-type", "text/html; charset=UTF-8")
	} else {
		w.Header().Set("Content-type", "application/octet-stream")
	}

	io.Copy(w, file)

	rd.Status = http.StatusOK
	fmt.Println(rd)
}

// serveTLS
func serveTLS(domain string, port int) error {
	u, err := user.Current()
	if err != nil {
		return err
	}
	cacheDir := u.HomeDir + certDir
	if err := os.MkdirAll(cacheDir, 0700); err != nil {
		return err
	}

	m := autocert.Manager{
		Cache:      autocert.DirCache(cacheDir),
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist(domain),
	}

	srv := &http.Server{
		TLSConfig: &tls.Config{
			GetCertificate: m.GetCertificate,
		},
	}

	http2.ConfigureServer(srv, &http2.Server{
		NewWriteScheduler: func() http2.WriteScheduler {
			return http2.NewPriorityWriteScheduler(nil)
		},
	})

	ln, err := net.ListenTCP("tcp", &net.TCPAddr{
		Port: port,
	})
	if err != nil {
		return err
	}

	return srv.Serve(tls.NewListener(keepAliveListener{ln}, srv.TLSConfig))
}

// keepAliveListener
type keepAliveListener struct {
	*net.TCPListener
}

// Accept
func (k keepAliveListener) Accept() (net.Conn, error) {
	tc, err := k.AcceptTCP()
	if err != nil {
		return nil, err
	}

	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(time.Minute * 3)

	return tc, nil
}

func getpwd() string {
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	return pwd
}

func homeDir() string {
	u, err := user.Current()
	if err != nil {
		return ""
	}

	return u.HomeDir
}

func main() {
	var port int
	var le string
	var gs bool

	pwd := getpwd()

	flag.IntVar(&port, "p", 8000, "bind port")
	flag.StringVar(&le, "l", "", "enable TLS with Let's Encrypt for the given domain name. Port = port + 1 ")
	flag.BoolVar(&gs, "g", false, "generate and use a self signed certificate")
	flag.Parse()

	if le != "" {
		var srv http.Server
		http2.ConfigureServer(&srv, new(http2.Server))

		tlsPort := port + 1

		go func() {
			fmt.Printf("Serving HTTPS on 0.0.0.0 port %v ...\n", tlsPort)
			log.Fatal(serveTLS(le, tlsPort))
		}()
	}

	h := &httpServer{
		Port:      port,
		Directory: pwd,
		template:  template.Must(template.New("listing").Parse(htmlTemplate)),
	}

	if gs {
		hd := homeDir()

		certPath := hd + certDir + pathSeperator + cert
		keyPath := hd + certDir + pathSeperator + key

		if err := generateCertificates(certPath, keyPath); err != nil {
			log.Fatalln(err)
		}

		fmt.Printf("Serving HTTPS on 0.0.0.0 port %v ...\n", h.Port+1)
		log.Fatal(http.ListenAndServeTLS(fmt.Sprintf("0.0.0.0:%d", port+1), certPath, keyPath, h))
	}

	fmt.Printf("Serving HTTP on 0.0.0.0 port %v ...\n", h.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), h))

}

const htmlTemplate = `
<!DOCTYPE html>

    <meta charset="utf-8">
    <title>simple-httpd</title>

Directory listing for {{.relativePath}}

        Name
		Last Modified
		Size

	    {{.parentDirectory}}

      {{range .files}}

	    {{.Name}}
		{{.LastModified}}
		{{.Size}}

      {{end}}

simple-httpd - {{.version}} / {{.goVersion}}

`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"os"
	"syscall"
	"unsafe"

	"github.com/nfnt/resize"
)

type dot int

const (
	black dot = 1
	white dot = 0
)

func main2() {
	var dots pattern
	dots[0] = [4]dot{
		white,
		black,
		white,
		black,
	}
	fmt.Println(dots.String())
}

func main() {
	img, _, err := image.Decode(os.Stdin)
	if err != nil {
		panic(err)
	}

	w, _, err := GetTerminalSize()
	if err != nil {
		panic(err)
	}

	w = w * 2 // Since each symbol is two dots wide

	img = resize.Thumbnail(uint(w), uint(img.Bounds().Dy()), img, resize.NearestNeighbor)

	var picture string

	bounds := img.Bounds()

	// An image's bounds do not necessarily start at (0, 0), so the two loops start
	// at bounds.Min.Y and bounds.Min.X. Looping over Y first and X second is more
	// likely to result in better memory access patterns than X first and Y second.
	for py := bounds.Min.Y; py < bounds.Max.Y; py += 4 {
		for px := bounds.Min.X; px < bounds.Max.X; px += 2 {
			var dots pattern
			// Draw left-right, top-bottom.
			for y := 0; y < 4; y++ {
				for x := 0; x < 2; x++ {
					dots[x][y] = dotAt(img, px+x, py+y)
				}
			}
			picture += dots.String()
		}
		picture += "\n"
	}

	fmt.Println(picture)
}

// func dotAt(img image.Image, x, y int) dot {
// 	r, g, b, a := img.At(x, y).RGBA()
// 	fmt.Printf("(%d,%d) %d, %d, %d, %d\n", x, y, r, g, b, a)
// 	if a < 65535 {
// 		return black
// 	}
// 	if r < 65535 {
// 		return white
// 	}
// 	return black
// }

// 32,767 is half bright
func dotAt(img image.Image, x, y int) dot {
	v := grayByLuminosity(img.At(x, y).RGBA())
	// fmt.Printf("(%d,%d) %d, %d, %d, %d\n", x, y, r, g, b, a)
	// fmt.Printf("(%d,%d) %d\n", x, y, v)
	if v <= 30767 {
		return white
	}
	return black
}

// 0.21 R + 0.72 G + 0.07 B
func grayByLuminosity(r, g, b, a uint32) uint32 {
	weighted := 0.21*float32(r) + 0.72*float32(g) + 0.07*float32(b)
	return uint32(weighted)
}

// Represents an 8 dot braille pattern using x,y coordinates. Eg:
// +----------+
// |(0,0)(1,0)|
// |(0,1)(1,1)|
// |(0,2)(1,2)|
// |(0,3)(1,3)|
// +----------+
type pattern [2][4]dot

// CodePoint maps each point in pattern to a braille number and
// calculates the corresponding unicode symbol.
// +------+
// |(1)(4)|
// |(2)(5)|
// |(3)(6)|
// |(7)(8)|
// +------+
// See https://en.wikipedia.org/wiki/Braille_Patterns#Identifying.2C_naming_and_ordering)
func (dots pattern) CodePoint() rune {
	lowEndian := [8]dot{dots[0][0], dots[0][1], dots[0][2], dots[1][0], dots[1][1], dots[1][2], dots[0][3], dots[1][3]}
	var v int
	for i, x := range lowEndian {
		v += int(x) << uint(i)
	}
	return rune(v) + '\u2800'
}

func (dots pattern) String() string {
	return string(dots.CodePoint())
}

func GetTerminalSize() (width, height int, err error) {
	var dimensions [4]uint16

	_, _, e := syscall.Syscall6(
		syscall.SYS_IOCTL,
		uintptr(syscall.Stdout),
		uintptr(syscall.TIOCGWINSZ),
		uintptr(unsafe.Pointer(&dimensions)),
		0, 0, 0,
	)
	if e != 0 {
		return -1, -1, e
	}
	return int(dimensions[1]), int(dimensions[0]), nil
}
<commit_msg>adds luminosity flag<commit_after>package main

import (
	"flag"
	"fmt"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"os"
	"syscall"
	"unsafe"

	"github.com/nfnt/resize"
)

type dot int

const (
	black dot = 1
	white dot = 0
)

var (
	luminosity = flag.Float64("lum", 50, "the percentage luminosity cutoff to determine black or white pixels")
)

func main() {
	flag.Parse()
	fmt.Println(*luminosity)

	img, _, err := image.Decode(os.Stdin)
	if err != nil {
		panic(err)
	}

	w, _, err := GetTerminalSize()
	if err != nil {
		panic(err)
	}

	w = w * 2 // Since each symbol is two dots wide

	img = resize.Thumbnail(uint(w), uint(img.Bounds().Dy()), img, resize.NearestNeighbor)

	var picture string

	bounds := img.Bounds()

	// An image's bounds do not necessarily start at (0, 0), so the two loops start
	// at bounds.Min.Y and bounds.Min.X. Looping over Y first and X second is more
	// likely to result in better memory access patterns than X first and Y second.
	for py := bounds.Min.Y; py < bounds.Max.Y; py += 4 {
		for px := bounds.Min.X; px < bounds.Max.X; px += 2 {
			var dots pattern
			// Draw left-right, top-bottom.
			for y := 0; y < 4; y++ {
				for x := 0; x < 2; x++ {
					dots[x][y] = dotAt(img, px+x, py+y)
				}
			}
			picture += dots.String()
		}
		picture += "\n"
	}

	fmt.Println(picture)
}

func dotAt(img image.Image, x, y int) dot {
	v := grayByLuminosity(img.At(x, y).RGBA())
	// 32,767 is half bright
	if v <= uint32(65535/(100 / *luminosity)) {
		return white
	}

	return black
}

// 0.21 R + 0.72 G + 0.07 B
func grayByLuminosity(r, g, b, a uint32) uint32 {
	weighted := 0.21*float32(r) + 0.72*float32(g) + 0.07*float32(b)
	return uint32(weighted)
}

// Represents an 8 dot braille pattern using x,y coordinates. Eg:
// +----------+
// |(0,0)(1,0)|
// |(0,1)(1,1)|
// |(0,2)(1,2)|
// |(0,3)(1,3)|
// +----------+
type pattern [2][4]dot

// CodePoint maps each point in pattern to a braille number and
// calculates the corresponding unicode symbol.
// +------+
// |(1)(4)|
// |(2)(5)|
// |(3)(6)|
// |(7)(8)|
// +------+
// See https://en.wikipedia.org/wiki/Braille_Patterns#Identifying.2C_naming_and_ordering)
func (dots pattern) CodePoint() rune {
	lowEndian := [8]dot{dots[0][0], dots[0][1], dots[0][2], dots[1][0], dots[1][1], dots[1][2], dots[0][3], dots[1][3]}
	var v int
	for i, x := range lowEndian {
		v += int(x) << uint(i)
	}
	return rune(v) + '\u2800'
}

func (dots pattern) String() string {
	return string(dots.CodePoint())
}

func GetTerminalSize() (width, height int, err error) {
	var dimensions [4]uint16

	_, _, e := syscall.Syscall6(
		syscall.SYS_IOCTL,
		uintptr(syscall.Stdout),
		uintptr(syscall.TIOCGWINSZ),
		uintptr(unsafe.Pointer(&dimensions)),
		0, 0, 0,
	)
	if e != 0 {
		return -1, -1, e
	}
	return int(dimensions[1]), int(dimensions[0]), nil
}
<|endoftext|>


<commit_before>package core

import (
	"encoding/hex"
	"log"
	"os"
	"os/user"

	"golang.org/x/crypto/bcrypt"
)

/*
Tinzenite is the struct on which all important operations should be called.
*/
type Tinzenite struct {
	Path     string
	auth     *Authentication
	selfpeer *Peer
	channel  *Channel
	allPeers []*Peer
	model    *model
}

/*
CreateTinzenite makes a directory a new Tinzenite directory. Will return error
if already so.
*/
func CreateTinzenite(dirname, dirpath, peername, username string) (*Tinzenite, error) {
	if IsTinzenite(dirpath) {
		return nil, ErrIsTinzenite
	}
	id, err := newIdentifier()
	if err != nil {
		return nil, err
	}
	// Bcrypt username
	userbyte, err := bcrypt.GenerateFromPassword([]byte(username), 10)
	if err != nil {
		return nil, err
	}
	userhash := hex.EncodeToString(userbyte)
	// Build
	tinzenite := &Tinzenite{
		Path: dirpath,
		auth: &Authentication{
			User:    userhash,
			Dirname: dirname,
			DirID:   id,
			Key:     "TODO"}}
	// build channel
	channel, err := CreateChannel(peername, nil, tinzenite)
	if err != nil {
		return nil, err
	}
	tinzenite.channel = channel
	// build self peer
	address, err := channel.Address()
	if err != nil {
		return nil, err
	}
	peerhash, err := newIdentifier()
	if err != nil {
		return nil, err
	}
	peer := &Peer{
		Name:           peername,
		Address:        address,
		Protocol:       Tox,
		Identification: peerhash}
	tinzenite.selfpeer = peer
	tinzenite.allPeers = []*Peer{peer}
	// save that this directory is now a tinzenite dir
	err = tinzenite.storeGlobalConfig()
	if err != nil {
		return nil, err
	}
	// make .tinzenite so that model can work
	err = makeDirectory(dirpath + "/" + TINZENITEDIR)
	if err != nil {
		return nil, err
	}
	// build model (can block for long!)
	m, err := createModel(dirpath, peer.Identification)
	if err != nil {
		return nil, err
	}
	tinzenite.model = m
	// finally store initial copy
	err = tinzenite.Store()
	if err != nil {
		return nil, err
	}
	/*TODO later implement that model updates are sent to all online peers --> channel and func must be init here*/
	return tinzenite, nil
}

/*
LoadTinzenite will try to load the given directory path as a Tinzenite directory.
If not one it won't work: use CreateTinzenite to create a new peer.
*/
func LoadTinzenite(dirpath string) (*Tinzenite, error) {
	if !IsTinzenite(dirpath) {
		return nil, ErrNotTinzenite
	}
	t := &Tinzenite{Path: dirpath}
	// load auth
	auth, err := loadAuthentication(dirpath)
	if err != nil {
		return nil, err
	}
	t.auth = auth
	// load model
	model, err := loadModel(dirpath)
	if err != nil {
		return nil, err
	}
	t.model = model
	// load peer list
	peers, err := loadPeers(dirpath)
	if err != nil {
		return nil, err
	}
	t.allPeers = peers
	// load tox dump
	selfToxDump, err := loadToxDump(dirpath)
	if err != nil {
		return nil, err
	}
	t.selfpeer = selfToxDump.SelfPeer
	// prepare channel
	channel, err := CreateChannel(t.selfpeer.Name, selfToxDump.ToxData, t)
	if err != nil {
		return nil, err
	}
	t.channel = channel
	return t, nil
}

/*
RemoveTinzenite directory. Specifically leaves all user files but removes all
Tinzenite specific items.
*/
func RemoveTinzenite(path string) error {
	if !IsTinzenite(path) {
		return ErrNotTinzenite
	}
	/* TODO remove from directory list*/
	return os.RemoveAll(path + "/" + TINZENITEDIR)
}

/*
SyncModel TODO

fetches model from other peers and syncs (this is for manual sync)
*/
func (t *Tinzenite) SyncModel() error {
	// first ensure that local model is up to date
	err := t.model.Update()
	if err != nil {
		return err
	}
	// iterate over all known peers
	for _, peer := range t.allPeers {
		if peer == t.selfpeer {
			continue
		}
		log.Println("Sending request.")
		/*TODO - also make this concurrent?*/
		t.channel.Send(peer.Address, "Want update! <-- TODO replace this message")
		// if online -> continue
		// if not init -> init
		// sync
		/*TODO must store init state in allPeers too, also in future encryption*/
	}
	return nil
}

/*
Address of this Tinzenite peer.
*/
func (t *Tinzenite) Address() string {
	return t.selfpeer.Address
}

/*
Close cleanly stores everything and shuts Tinzenite down.
*/
func (t *Tinzenite) Close() {
	// store all information
	t.Store()
	// FINALLY close (afterwards because I still need info from channel for store!)
	t.channel.Close()
}

/*
Store the tinzenite directory structure to disk. Will resolve all important
objects and store them so that it can later be reloaded.
*/
func (t *Tinzenite) Store() error {
	root := t.Path + "/" + TINZENITEDIR
	// build directory structure
	err := makeDirectories(root,
		ORGDIR+"/"+PEERSDIR, "temp", "removed", LOCAL)
	if err != nil {
		return err
	}
	// write all peers to files
	for _, peer := range t.allPeers {
		err := peer.store(t.Path)
		if err != nil {
			return err
		}
	}
	// store local peer info with toxdata
	toxData, err := t.channel.ToxData()
	if err != nil {
		return err
	}
	toxPeerDump := &toxPeerDump{
		SelfPeer: t.selfpeer,
		ToxData:  toxData}
	err = toxPeerDump.store(t.Path)
	if err != nil {
		return err
	}
	// finally store auth file
	return t.auth.store(t.Path)
}

/*
Connect this tinzenite to another peer, beginning the bootstrap process.
*/
func (t *Tinzenite) Connect(address string) error {
	return t.channel.RequestConnection(address, t.selfpeer)
}

/*
CallbackNewConnection is called when a new connection request comes in.
*/
func (t *Tinzenite) CallbackNewConnection(address, message string) {
	log.Printf("New connection from <%s> with message <%s>\n", address, message)
	err := t.channel.AcceptConnection(address)
	if err != nil {
		log.Println(err.Error())
		return
	}
	/*TODO actually this should be read from disk once the peer has synced... oO
	Correction: read from message other peer info */
	newID, _ := newIdentifier()
	t.allPeers = append(t.allPeers, &Peer{
		Identification: newID,   // must be read from message
		Name:           message, // must be read from message
		Address:        address,
		Protocol:       Tox})
	// actually we just want to get type and confidence from the user here, and if everything
	// is okay we accept the connection --> then what? need to bootstrap him...
}

/*
CallbackMessage is called when a message is received.
*/
func (t *Tinzenite) CallbackMessage(address, message string) {
	// log.Printf("Message from <%s> with message <%s>\n", address, message)
	switch message {
	case "model":
		t.channel.Send(address, t.model.String())
	default:
		t.channel.Send(address, "ACK")
	}
}

/*
storeGlobalConfig stores the path value into the user's home directory so that clients
can locate it.
*/
func (t *Tinzenite) storeGlobalConfig() error {
	// ready outside data
	user, err := user.Current()
	if err != nil {
		return err
	}
	path := user.HomeDir + "/.config/tinzenite"
	err = makeDirectory(path)
	if err != nil {
		return err
	}
	path += "/" + DIRECTORYLIST
	file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_APPEND, FILEPERMISSIONMODE)
	if err != nil {
		return err
	}
	defer file.Close()
	// write path to file
	_, err = file.WriteString(t.Path + "\n")
	if err != nil {
		return err
	}
	// ensure that the file is valid
	return PrettifyDirectoryList()
}
<commit_msg>small stuff<commit_after>package core

import (
	"encoding/json"
	"log"
	"os"
	"os/user"

	"golang.org/x/crypto/bcrypt"
)

/*
Tinzenite is the struct on which all important operations should be called.
*/
type Tinzenite struct {
	Path     string
	auth     *Authentication
	selfpeer *Peer
	channel  *Channel
	allPeers []*Peer
	model    *model
}

/*
CreateTinzenite makes a directory a new Tinzenite directory. Will return error
if already so.
*/
func CreateTinzenite(dirname, dirpath, peername, username string) (*Tinzenite, error) {
	if IsTinzenite(dirpath) {
		return nil, ErrIsTinzenite
	}
	id, err := newIdentifier()
	if err != nil {
		return nil, err
	}
	// Bcrypt username
	userhash, err := bcrypt.GenerateFromPassword([]byte(username), 10)
	if err != nil {
		return nil, err
	}
	// Build
	tinzenite := &Tinzenite{
		Path: dirpath,
		auth: &Authentication{
			User:    string(userhash),
			Dirname: dirname,
			DirID:   id,
			Key:     "TODO"}}
	// build channel
	channel, err := CreateChannel(peername, nil, tinzenite)
	if err != nil {
		return nil, err
	}
	tinzenite.channel = channel
	// build self peer
	address, err := channel.Address()
	if err != nil {
		return nil, err
	}
	peerhash, err := newIdentifier()
	if err != nil {
		return nil, err
	}
	peer := &Peer{
		Name:           peername,
		Address:        address,
		Protocol:       Tox,
		Identification: peerhash}
	tinzenite.selfpeer = peer
	tinzenite.allPeers = []*Peer{peer}
	// save that this directory is now a tinzenite dir
	err = tinzenite.storeGlobalConfig()
	if err != nil {
		return nil, err
	}
	// make .tinzenite so that model can work
	err = makeDirectory(dirpath + "/" + TINZENITEDIR)
	if err != nil {
		return nil, err
	}
	// build model (can block for long!)
	m, err := createModel(dirpath, peer.Identification)
	if err != nil {
		return nil, err
	}
	tinzenite.model = m
	// finally store initial copy
	err = tinzenite.Store()
	if err != nil {
		return nil, err
	}
	/*TODO later implement that model updates are sent to all online peers --> channel and func must be init here*/
	return tinzenite, nil
}

/*
LoadTinzenite will try to load the given directory path as a Tinzenite directory.
If not one it won't work: use CreateTinzenite to create a new peer.
*/
func LoadTinzenite(dirpath string) (*Tinzenite, error) {
	if !IsTinzenite(dirpath) {
		return nil, ErrNotTinzenite
	}
	t := &Tinzenite{Path: dirpath}
	// load auth
	auth, err := loadAuthentication(dirpath)
	if err != nil {
		return nil, err
	}
	t.auth = auth
	// load model
	model, err := loadModel(dirpath)
	if err != nil {
		return nil, err
	}
	t.model = model
	// load peer list
	peers, err := loadPeers(dirpath)
	if err != nil {
		return nil, err
	}
	t.allPeers = peers
	// load tox dump
	selfToxDump, err := loadToxDump(dirpath)
	if err != nil {
		return nil, err
	}
	t.selfpeer = selfToxDump.SelfPeer
	// prepare channel
	channel, err := CreateChannel(t.selfpeer.Name, selfToxDump.ToxData, t)
	if err != nil {
		return nil, err
	}
	t.channel = channel
	return t, nil
}

/*
RemoveTinzenite directory. Specifically leaves all user files but removes all
Tinzenite specific items.
*/
func RemoveTinzenite(path string) error {
	if !IsTinzenite(path) {
		return ErrNotTinzenite
	}
	/* TODO remove from directory list*/
	return os.RemoveAll(path + "/" + TINZENITEDIR)
}

/*
SyncModel TODO

fetches model from other peers and syncs (this is for manual sync)
*/
func (t *Tinzenite) SyncModel() error {
	// first ensure that local model is up to date
	err := t.model.Update()
	if err != nil {
		return err
	}
	// iterate over all known peers
	for _, peer := range t.allPeers {
		if peer == t.selfpeer {
			continue
		}
		log.Println("Sending request.")
		/*TODO - also make this concurrent?*/
		t.channel.Send(peer.Address, "Want update! <-- TODO replace this message")
		// if online -> continue
		// if not init -> init
		// sync
		/*TODO must store init state in allPeers too, also in future encryption*/
	}
	return nil
}

/*
Address of this Tinzenite peer.
*/
func (t *Tinzenite) Address() string {
	return t.selfpeer.Address
}

/*
Close cleanly stores everything and shuts Tinzenite down.
*/
func (t *Tinzenite) Close() {
	// store all information
	t.Store()
	// FINALLY close (afterwards because I still need info from channel for store!)
	t.channel.Close()
}

/*
Store the tinzenite directory structure to disk. Will resolve all important
objects and store them so that it can later be reloaded.
*/
func (t *Tinzenite) Store() error {
	root := t.Path + "/" + TINZENITEDIR
	// build directory structure
	err := makeDirectories(root,
		ORGDIR+"/"+PEERSDIR, "temp", "removed", LOCAL)
	if err != nil {
		return err
	}
	// write all peers to files
	for _, peer := range t.allPeers {
		err := peer.store(t.Path)
		if err != nil {
			return err
		}
	}
	// store local peer info with toxdata
	toxData, err := t.channel.ToxData()
	if err != nil {
		return err
	}
	toxPeerDump := &toxPeerDump{
		SelfPeer: t.selfpeer,
		ToxData:  toxData}
	err = toxPeerDump.store(t.Path)
	if err != nil {
		return err
	}
	// finally store auth file
	return t.auth.store(t.Path)
}

/*
Connect this tinzenite to another peer, beginning the bootstrap process.
*/
func (t *Tinzenite) Connect(address string) error {
	return t.channel.RequestConnection(address, t.selfpeer)
}

/*
CallbackNewConnection is called when a new connection request comes in.
*/
func (t *Tinzenite) CallbackNewConnection(address, message string) {
	log.Printf("New connection from <%s> with message <%s>\n", address, message)
	err := t.channel.AcceptConnection(address)
	if err != nil {
		log.Println(err.Error())
		return
	}
	/*TODO actually this should be read from disk once the peer has synced... oO
	Correction: read from message other peer info */
	newID, _ := newIdentifier()
	t.allPeers = append(t.allPeers, &Peer{
		Identification: newID,   // must be read from message
		Name:           message, // must be read from message
		Address:        address,
		Protocol:       Tox})
	// actually we just want to get type and confidence from the user here, and if everything
	// is okay we accept the connection --> then what? need to bootstrap him...
}

/*
CallbackMessage is called when a message is received.
*/
func (t *Tinzenite) CallbackMessage(address, message string) {
	// log.Printf("Message from <%s> with message <%s>\n", address, message)
	switch message {
	case "model":
		t.channel.Send(address, t.model.String())
	case "auth":
		authbin, _ := json.Marshal(t.auth)
		t.channel.Send(address, string(authbin))
	default:
		t.channel.Send(address, "ACK")
	}
}

/*
storeGlobalConfig stores the path value into the user's home directory so that clients
can locate it.
*/
func (t *Tinzenite) storeGlobalConfig() error {
	// ready outside data
	user, err := user.Current()
	if err != nil {
		return err
	}
	path := user.HomeDir + "/.config/tinzenite"
	err = makeDirectory(path)
	if err != nil {
		return err
	}
	path += "/" + DIRECTORYLIST
	file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_APPEND, FILEPERMISSIONMODE)
	if err != nil {
		return err
	}
	defer file.Close()
	// write path to file
	_, err = file.WriteString(t.Path + "\n")
	if err != nil {
		return err
	}
	// ensure that the file is valid
	return PrettifyDirectoryList()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	bootstrapperPkg "github.com/cloudfoundry-incubator/cf-mysql-bootstrap/bootstrapper"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/bootstrapper/node_manager"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/clock"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/config"
	"github.com/pivotal-golang/lager"
)

func main() {
	rootConfig, err := config.NewConfig(os.Args)
	err = rootConfig.BuildLogger()
	logger := rootConfig.Logger

	if err != nil {
		logger.Fatal("Failed to parse config", err, lager.Data{
			"config": rootConfig,
		})
	}

	nodeManager := node_manager.New(rootConfig, clock.DefaultClock())
	bootstrapper := bootstrapperPkg.New(nodeManager)
	err = bootstrapper.Bootstrap()

	if err != nil {
		logger.Error("Failed to bootstrap cluster", err, lager.Data{
			"config": rootConfig,
		})
		printHumanReadableErr(err)
		os.Exit(1)
	}

	logger.Info("Successfully bootstrapped cluster")
	fmt.Println("Successfully bootstrapped cluster")
}

func printHumanReadableErr(err error) {
	fmt.Printf(`
		##################################################################################
		Error: %s

		Reference the docs for more information:
		https://github.com/cloudfoundry/cf-mysql-release/blob/master/docs/bootstrapping.md
		##################################################################################
		`, err)
}
<commit_msg>Validate config and handle errors<commit_after>package main

import (
	"fmt"
	"os"

	bootstrapperPkg "github.com/cloudfoundry-incubator/cf-mysql-bootstrap/bootstrapper"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/bootstrapper/node_manager"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/clock"
	"github.com/cloudfoundry-incubator/cf-mysql-bootstrap/config"
	"github.com/pivotal-golang/lager"
)

func main() {
	rootConfig, err := config.NewConfig(os.Args)
	if err != nil {
		panic(fmt.Sprintf("Failed to parse config: %s", err.Error()))
	}

	err = rootConfig.Validate()
	if err != nil {
		panic(fmt.Sprintf("Invalid config: %s", err.Error()))
	}

	err = rootConfig.BuildLogger()
	if err != nil {
		panic(fmt.Sprintf("Failed to build logger: %s", err.Error()))
	}
	logger := rootConfig.Logger

	nodeManager := node_manager.New(rootConfig, clock.DefaultClock())
	bootstrapper := bootstrapperPkg.New(nodeManager)
	err = bootstrapper.Bootstrap()

	if err != nil {
		logger.Error("Failed to bootstrap cluster", err, lager.Data{
			"config": rootConfig,
		})
		printHumanReadableErr(err)
		os.Exit(1)
	}

	logger.Info("Successfully bootstrapped cluster")
	fmt.Println("Successfully bootstrapped cluster")
}

func printHumanReadableErr(err error) {
	fmt.Printf(`
		##################################################################################
		Error: %s

		Reference the docs for more information:
		https://github.com/cloudfoundry/cf-mysql-release/blob/master/docs/bootstrapping.md
		##################################################################################
		`, err)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 The SkyDNS Authors. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"errors"
	"flag"
	"github.com/goraft/raft"
	"github.com/miekg/dns"
	"github.com/skynetservices/skydns/server"
	"github.com/skynetservices/skydns/stats"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

var (
	join, ldns, lhttp, dataDir, domain string
	rtimeout, wtimeout                 time.Duration
	discover,norr                      bool
	secret                             string
	nameserver                         string
	dnssec                             string
)

func init() {
	flag.StringVar(&join, "join", "", "Member of SkyDNS cluster to join can be comma separated list")
	flag.BoolVar(&discover, "discover", false, "Auto discover SkyDNS cluster. Performs an NS lookup on the -domain to find SkyDNS members")
	flag.StringVar(&domain, "domain",
		func() string {
			if x := os.Getenv("SKYDNS_DOMAIN"); x != "" {
				return x
			}
			return "skydns.local"
		}(), "Domain to anchor requests to or env. var. SKYDNS_DOMAIN")
	flag.StringVar(&ldns, "dns",
		func() string {
			if x := os.Getenv("SKYDNS_DNS"); x != "" {
				return x
			}
			return "127.0.0.1:53"
		}(), "IP:Port to bind to for DNS or env. var SKYDNS_DNS")
	flag.StringVar(&lhttp, "http",
		func() string {
			if x := os.Getenv("SKYDNS"); x != "" {
				// get rid of http or https
				x1 := strings.TrimPrefix(x, "https://")
				x1 = strings.TrimPrefix(x1, "http://")
				return x1
			}
			return "127.0.0.1:8080"
		}(), "IP:Port to bind to for HTTP or env. var. SKYDNS")
	flag.StringVar(&dataDir, "data", "./data", "SkyDNS data directory")
	flag.DurationVar(&rtimeout, "rtimeout", 2*time.Second, "Read timeout")
	flag.DurationVar(&wtimeout, "wtimeout", 2*time.Second, "Write timeout")
	flag.StringVar(&secret, "secret", "", "Shared secret for use with http api")
	flag.StringVar(&nameserver, "nameserver", "", "Nameserver address to forward (non-local) queries to e.g. 8.8.8.8:53,8.8.4.4:53")
	flag.StringVar(&dnssec, "dnssec", "", "Basename of DNSSEC key file e.q. Kskydns.local.+005+38250")
	flag.BoolVar(&norr, "no-round-robin", false, "Do not round robin A/AAAA replies")
}

func main() {
	members := make([]string, 0)
	raft.SetLogLevel(0)
	flag.Parse()
	nameservers := strings.Split(nameserver, ",")
	// empty argument given
	if len(nameservers) == 1 && nameservers[0] == "" {
		nameservers = make([]string, 0)
		config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
		if err == nil {
			for _, s := range config.Servers {
				nameservers = append(nameservers, net.JoinHostPort(s, config.Port))
			}
		} else {
			log.Fatal(err)
			return
		}
	}

	if discover {
		ns, err := net.LookupNS(domain)

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

		if len(ns) < 1 {
			log.Fatal("No NS records found for ", domain)
			return
		}

		for _, n := range ns {
			members = append(members, strings.TrimPrefix(n.Host, "."))
		}
	} else if join != "" {
		members = strings.Split(join, ",")
	}

	s := server.NewServer(members, domain, ldns, lhttp, dataDir, rtimeout, wtimeout, secret, nameservers, !norr)

	if dnssec != "" {
		k, p, e := server.ParseKeyFile(dnssec)
		if e != nil {
			log.Fatal(e)
			return
		}
		if k.Header().Name != dns.Fqdn(domain) {
			log.Fatal(errors.New("Owner name of DNSKEY must match SkyDNS domain"))
			return
		}
		s.SetKeys(k, p)
	}

	stats.Collect()

	waiter, err := s.Start()
	if err != nil {
		log.Fatal(err)
		return
	}
	waiter.Wait()
}
<commit_msg>Fix merge<commit_after>// Copyright (c) 2013 The SkyDNS Authors. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"errors"
	"flag"
	"github.com/goraft/raft"
	"github.com/miekg/dns"
	"github.com/skynetservices/skydns/server"
	"github.com/skynetservices/skydns/stats"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

var (
	join, ldns, lhttp, dataDir, domain string
	rtimeout, wtimeout                 time.Duration
	discover,norr                      bool
	secret                             string
	nameserver                         string
	dnssec                             string
)

func init() {
	flag.StringVar(&join, "join", "", "Member of SkyDNS cluster to join can be comma separated list")
	flag.BoolVar(&discover, "discover", false, "Auto discover SkyDNS cluster. Performs an NS lookup on the -domain to find SkyDNS members")
	flag.StringVar(&domain, "domain",
		func() string {
			if x := os.Getenv("SKYDNS_DOMAIN"); x != "" {
				return x
			}
			return "skydns.local"
		}(), "Domain to anchor requests to or env. var. SKYDNS_DOMAIN")
	flag.StringVar(&ldns, "dns",
		func() string {
			if x := os.Getenv("SKYDNS_DNS"); x != "" {
				return x
			}
			return "127.0.0.1:53"
		}(), "IP:Port to bind to for DNS or env. var SKYDNS_DNS")
	flag.StringVar(&lhttp, "http",
		func() string {
			if x := os.Getenv("SKYDNS"); x != "" {
				// get rid of http or https
				x1 := strings.TrimPrefix(x, "https://")
				x1 = strings.TrimPrefix(x1, "http://")
				return x1
			}
			return "127.0.0.1:8080"
		}(), "IP:Port to bind to for HTTP or env. var. SKYDNS")
	flag.StringVar(&dataDir, "data", "./data", "SkyDNS data directory")
	flag.DurationVar(&rtimeout, "rtimeout", 2*time.Second, "Read timeout")
	flag.DurationVar(&wtimeout, "wtimeout", 2*time.Second, "Write timeout")
	flag.StringVar(&secret, "secret", "", "Shared secret for use with http api")
	flag.StringVar(&nameserver, "nameserver", "", "Nameserver address to forward (non-local) queries to e.g. 8.8.8.8:53,8.8.4.4:53")
	flag.StringVar(&dnssec, "dnssec", "", "Basename of DNSSEC key file e.q. Kskydns.local.+005+38250")
	flag.BoolVar(&norr, "no-round-robin", false, "Do not round robin A/AAAA replies")
}

func main() {
	members := make([]string, 0)
	raft.SetLogLevel(0)
	flag.Parse()
	nameservers := strings.Split(nameserver, ",")
	// empty argument given
	if len(nameservers) == 1 && nameservers[0] == "" {
		nameservers = make([]string, 0)
		config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
		if err == nil {
			for _, s := range config.Servers {
				nameservers = append(nameservers, net.JoinHostPort(s, config.Port))
			}
		} else {
			log.Fatal(err)
			return
		}
	}

	if discover {
		ns, err := net.LookupNS(domain)

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

		if len(ns) < 1 {
			log.Fatal("No NS records found for ", domain)
			return
		}

		for _, n := range ns {
			members = append(members, strings.TrimPrefix(n.Host, "."))
		}
	} else if join != "" {
		members = strings.Split(join, ",")
	}

	s := server.NewServer(members, domain, ldns, lhttp, dataDir, rtimeout, wtimeout, secret, nameservers, !norr)
<<<<<<< HEAD

	if dnssec != "" {
		k, p, e := server.ParseKeyFile(dnssec)
		if e != nil {
			log.Fatal(e)
			return
		}
		if k.Header().Name != dns.Fqdn(domain) {
			log.Fatal(errors.New("Owner name of DNSKEY must match SkyDNS domain"))
			return
		}
		s.SetKeys(k, p)
	}
=======
>>>>>>> 4ae15f347a84502e895c65780fa5bd9e91090781

	stats.Collect()

	waiter, err := s.Start()
	if err != nil {
		log.Fatal(err)
		return
	}
	waiter.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"net"
	"os"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

// preload initializes any global options and configuration
// before the main or sub commands are run
func preload(context *cli.Context) error {
	if context.GlobalBool("debug") {
		log.SetLevel(log.DebugLevel)
	}
	return nil
}

// hostHosts returns a list of host addresses that are specified on the
// command line and also in a hosts file separated by new lines.
func loadHosts(context *cli.Context) ([]string, error) {
	hosts := []string(context.GlobalStringSlice("host"))
	if hostsFile := context.GlobalString("hosts"); hostsFile != "" {
		f, err := os.Open(hostsFile)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			if err := s.Err(); err != nil {
				return nil, err
			}
			hosts = append(hosts, s.Text())
		}
	}
	return hosts, nil
}

// multiplexAction uses the arguments passed via the command line and
// multiplexes them across multiple SSH connections
func multiplexAction(context *cli.Context) {
	c, err := newCommand(context)
	if err != nil {
		log.Fatal(err)
	}
	log.Debug(c)

	hosts, err := loadHosts(context)
	if err != nil {
		log.Fatal(err)
	}

	sections, err := parseSshConfigFile(filepath.Join(os.Getenv("HOME"), ".ssh", "config"))
	if err != nil {
		log.Fatal(err)
	}

	if len(hosts) == 0 {
		log.Fatal("no host specified for command to run")
	}
	log.Debugf("hosts %v", hosts)
	group := &sync.WaitGroup{}
	for _, h := range hosts {
		group.Add(1)
		go executeCommand(c, h, sections[h], context.GlobalBool("A"), context.GlobalBool("quiet"), group)
	}
	group.Wait()
	log.Debugf("finished executing %s on all hosts", c)
}

func executeCommand(c command, host string, section *SshConfigFileSection, agentForwarding, quiet bool, group *sync.WaitGroup) {
	defer group.Done()
	var (
		err          error
		originalHost = host
	)
	if host, err = cleanHost(host); err != nil {
		log.WithField("host", originalHost).Error(err)
		return
	}

	if err = runSSH(c, host, section, agentForwarding, quiet); err != nil {
		log.WithField("host", host).Error(err)
		return
	}
}

// runSSH executes the given command on the given host
func runSSH(c command, host string, section *SshConfigFileSection, agentForwarding, quiet bool) error {
	config, err := newSshClientConfig(host, section, c.User, c.Identity, agentForwarding)
	if err != nil {
		return err
	}

	session, err := config.NewSession(config.host)
	if err != nil {
		return err
	}
	if !quiet {
		w := newBufCloser(os.Stdout)
		defer w.Close()
		session.Stderr, session.Stdout = w, w
	}
	defer func() {
		session.Close()
		log.Printf("Session complete from %s", host)
	}()

	for key, value := range c.Env {
		if err := session.Setenv(key, value); err != nil {
			return err
		}
	}
	return session.Run(c.Cmd)
}

// cleanHost parses out the hostname/ip and port.  If no port is
// specified then port 22 is appended to the hostname/ip
func cleanHost(host string) (string, error) {
	h, port, err := net.SplitHostPort(host)
	if err != nil {
		if !strings.Contains(err.Error(), "missing port in address") {
			return "", err
		}
		port = "22"
		h = host
	}
	if port == "" {
		port = "22"
	}
	return net.JoinHostPort(h, port), nil
}

func main() {
	app := cli.NewApp()
	app.Name = "slex"
	app.Usage = "SSH commands multiplexed"
	app.Version = "1"
	app.Author = "@crosbymichael"
	app.Email = "crosbymichael@gmail.com"
	app.Before = preload
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for the logs",
		},
		cli.StringSliceFlag{
			Name:  "host",
			Value: &cli.StringSlice{},
			Usage: "SSH host address",
		},
		cli.StringFlag{
			Name:  "hosts",
			Usage: "file containing host addresses separated by a new line",
		},
		cli.StringFlag{
			Name:  "user,u",
			Value: "root",
			Usage: "user to execute the command as",
		},
		cli.StringFlag{
			Name:  "identity,i",
			Value: "id_rsa",
			Usage: "SSH identity to use for connecting to the host",
		},
		cli.BoolFlag{
			Name:  "agent,A",
			Usage: "Forward authentication request to the ssh agent",
		},
		cli.StringSliceFlag{
			Name:  "env,e",
			Usage: "set environment variables for SSH command",
			Value: &cli.StringSlice{},
		},
		cli.BoolFlag{
			Name:  "quiet,q",
			Usage: "disable output from the ssh command",
		},
	}
	app.Action = multiplexAction
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add username to log output for each executed command.<commit_after>package main

import (
	"bufio"
	"net"
	"os"
	"path/filepath"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

// preload initializes any global options and configuration
// before the main or sub commands are run
func preload(context *cli.Context) error {
	if context.GlobalBool("debug") {
		log.SetLevel(log.DebugLevel)
	}
	return nil
}

// hostHosts returns a list of host addresses that are specified on the
// command line and also in a hosts file separated by new lines.
func loadHosts(context *cli.Context) ([]string, error) {
	hosts := []string(context.GlobalStringSlice("host"))
	if hostsFile := context.GlobalString("hosts"); hostsFile != "" {
		f, err := os.Open(hostsFile)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			if err := s.Err(); err != nil {
				return nil, err
			}
			hosts = append(hosts, s.Text())
		}
	}
	return hosts, nil
}

// multiplexAction uses the arguments passed via the command line and
// multiplexes them across multiple SSH connections
func multiplexAction(context *cli.Context) {
	c, err := newCommand(context)
	if err != nil {
		log.Fatal(err)
	}
	log.Debug(c)

	hosts, err := loadHosts(context)
	if err != nil {
		log.Fatal(err)
	}

	sections, err := parseSshConfigFile(filepath.Join(os.Getenv("HOME"), ".ssh", "config"))
	if err != nil {
		log.Fatal(err)
	}

	if len(hosts) == 0 {
		log.Fatal("no host specified for command to run")
	}
	log.Debugf("hosts %v", hosts)
	group := &sync.WaitGroup{}
	for _, h := range hosts {
		group.Add(1)
		go executeCommand(c, h, sections[h], context.GlobalBool("A"), context.GlobalBool("quiet"), group)
	}
	group.Wait()
	log.Debugf("finished executing %s on all hosts", c)
}

func executeCommand(c command, host string, section *SshConfigFileSection, agentForwarding, quiet bool, group *sync.WaitGroup) {
	defer group.Done()
	var (
		err          error
		originalHost = host
	)
	if host, err = cleanHost(host); err != nil {
		log.WithField("host", originalHost).Error(err)
		return
	}

	if err = runSSH(c, host, section, agentForwarding, quiet); err != nil {
		log.WithField("host", host).Error(err)
		return
	}
}

// runSSH executes the given command on the given host
func runSSH(c command, host string, section *SshConfigFileSection, agentForwarding, quiet bool) error {
	config, err := newSshClientConfig(host, section, c.User, c.Identity, agentForwarding)
	if err != nil {
		return err
	}

	session, err := config.NewSession(config.host)
	if err != nil {
		return err
	}
	if !quiet {
		w := newBufCloser(os.Stdout)
		defer w.Close()
		session.Stderr, session.Stdout = w, w
	}
	defer func() {
		session.Close()
		log.Printf("Session complete from %s@%s", section.User, host)
	}()

	for key, value := range c.Env {
		if err := session.Setenv(key, value); err != nil {
			return err
		}
	}
	return session.Run(c.Cmd)
}

// cleanHost parses out the hostname/ip and port.  If no port is
// specified then port 22 is appended to the hostname/ip
func cleanHost(host string) (string, error) {
	h, port, err := net.SplitHostPort(host)
	if err != nil {
		if !strings.Contains(err.Error(), "missing port in address") {
			return "", err
		}
		port = "22"
		h = host
	}
	if port == "" {
		port = "22"
	}
	return net.JoinHostPort(h, port), nil
}

func main() {
	app := cli.NewApp()
	app.Name = "slex"
	app.Usage = "SSH commands multiplexed"
	app.Version = "1"
	app.Author = "@crosbymichael"
	app.Email = "crosbymichael@gmail.com"
	app.Before = preload
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for the logs",
		},
		cli.StringSliceFlag{
			Name:  "host",
			Value: &cli.StringSlice{},
			Usage: "SSH host address",
		},
		cli.StringFlag{
			Name:  "hosts",
			Usage: "file containing host addresses separated by a new line",
		},
		cli.StringFlag{
			Name:  "user,u",
			Value: "root",
			Usage: "user to execute the command as",
		},
		cli.StringFlag{
			Name:  "identity,i",
			Value: "id_rsa",
			Usage: "SSH identity to use for connecting to the host",
		},
		cli.BoolFlag{
			Name:  "agent,A",
			Usage: "Forward authentication request to the ssh agent",
		},
		cli.StringSliceFlag{
			Name:  "env,e",
			Usage: "set environment variables for SSH command",
			Value: &cli.StringSlice{},
		},
		cli.BoolFlag{
			Name:  "quiet,q",
			Usage: "disable output from the ssh command",
		},
	}
	app.Action = multiplexAction
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"mime"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/ONSdigital/florence/assets"
	"github.com/ONSdigital/go-ns/handlers/reverseProxy"
	"github.com/ONSdigital/go-ns/log"
	"github.com/ONSdigital/go-ns/server"
	"github.com/gorilla/pat"
)

var bindAddr = ":8081"
var babbageURL = "http://localhost:8080"
var zebedeeURL = "http://localhost:8082"

var getAsset = assets.Asset

func main() {

	if v := os.Getenv("BIND_ADDR"); len(v) > 0 {
		bindAddr = v
	}
	if v := os.Getenv("BABBAGE_URL"); len(v) > 0 {
		babbageURL = v
	}
	if v := os.Getenv("ZEBEDEE_URL"); len(v) > 0 {
		zebedeeURL = v
	}

	log.Namespace = "florence"

	babbageURL, err := url.Parse(babbageURL)
	if err != nil {
		log.Error(err, nil)
		os.Exit(1)
	}

	babbageProxy := reverseProxy.Create(babbageURL, nil)

	zebedeeURL, err := url.Parse(zebedeeURL)
	if err != nil {
		log.Error(err, nil)
		os.Exit(1)
	}

	zebedeeProxy := reverseProxy.Create(zebedeeURL, zebedeeDirector)

	router := pat.New()

	router.Handle("/zebedee/{uri:.*}", zebedeeProxy)
	router.HandleFunc("/florence/dist/{uri:.*}", staticFiles)
	router.HandleFunc("/florence", refactoredIndexFile)
	router.HandleFunc("/florence/index.html", legacyIndexFile)
	router.HandleFunc("/florence{uri:|/.*}", refactoredIndexFile)
	router.Handle("/{uri:.*}", babbageProxy)

	log.Debug("Starting server", log.Data{
		"bind_addr":   bindAddr,
		"babbage_url": babbageURL,
		"zebedee_url": zebedeeURL,
	})

	s := server.New(bindAddr, router)

	s.ListenAndServe()
}

func staticFiles(w http.ResponseWriter, req *http.Request) {
	path := req.URL.Query().Get(":uri")

	b, err := getAsset("../dist/" + path)
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, mime.TypeByExtension(filepath.Ext(path)))
	w.WriteHeader(200)
	w.Write(b)
}

func legacyIndexFile(w http.ResponseWriter, req *http.Request) {
	log.Debug("Getting legacy HTML file", nil)

	b, err := getAsset("../dist/legacy-assets/index.html")
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, "text/html")
	w.WriteHeader(200)
	w.Write(b)
}

func refactoredIndexFile(w http.ResponseWriter, req *http.Request) {
	log.Debug("Getting refactored HTML file", nil)

	b, err := getAsset("../dist/refactored.html")
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, "text/html")
	w.WriteHeader(200)
	w.Write(b)
}

func zebedeeDirector(req *http.Request) {
	if c, err := req.Cookie(`access_token`); err == nil && len(c.Value) > 0 {
		req.Header.Set(`X-Florence-Token`, c.Value)
	}
	req.URL.Path = strings.TrimPrefix(req.URL.Path, "/zebedee")
}

type transport struct {
	http.RoundTripper
}

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	/* May need this to handle location later

	resp, err = t.RoundTripper.RoundTrip(req)
	if err != nil {
		return nil, err
	}
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	err = resp.Body.Close()
	if err != nil {
		return nil, err
	}
	b = bytes.Replace(b, []byte("server"), []byte("schmerver"), -1)
	body := ioutil.NopCloser(bytes.NewReader(b))
	resp.Body = body
	resp.ContentLength = int64(len(b))
	resp.Header.Set("Content-Length", strconv.Itoa(len(b)))
	return resp, nil */

	return t.RoundTripper.RoundTrip(req)
}

var _ http.RoundTripper = &transport{}
<commit_msg>Add comment about proxying redirects<commit_after>package main

import (
	"mime"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/ONSdigital/florence/assets"
	"github.com/ONSdigital/go-ns/handlers/reverseProxy"
	"github.com/ONSdigital/go-ns/log"
	"github.com/ONSdigital/go-ns/server"
	"github.com/gorilla/pat"
)

var bindAddr = ":8081"
var babbageURL = "http://localhost:8080"
var zebedeeURL = "http://localhost:8082"

var getAsset = assets.Asset

func main() {

	if v := os.Getenv("BIND_ADDR"); len(v) > 0 {
		bindAddr = v
	}
	if v := os.Getenv("BABBAGE_URL"); len(v) > 0 {
		babbageURL = v
	}
	if v := os.Getenv("ZEBEDEE_URL"); len(v) > 0 {
		zebedeeURL = v
	}

	log.Namespace = "florence"

	/*
		NOTE:
		If there's any issues with this Florence server proxying redirects from either Babbage or Zebedee then the code in the previous Java Florence server might give some clues for a solution :- https://github.com/ONSdigital/florence/blob/b13df0708b30493b98e9ce239103c59d7f409f98/src/main/java/com/github/onsdigital/florence/filter/Proxy.java#L125-L135

		The code has purposefully not been included in this Go replacement because we can't see what issue it's fixing and whether it's necessary.
	*/

	babbageURL, err := url.Parse(babbageURL)
	if err != nil {
		log.Error(err, nil)
		os.Exit(1)
	}

	babbageProxy := reverseProxy.Create(babbageURL, nil)

	zebedeeURL, err := url.Parse(zebedeeURL)
	if err != nil {
		log.Error(err, nil)
		os.Exit(1)
	}

	zebedeeProxy := reverseProxy.Create(zebedeeURL, zebedeeDirector)

	router := pat.New()

	router.Handle("/zebedee/{uri:.*}", zebedeeProxy)
	router.HandleFunc("/florence/dist/{uri:.*}", staticFiles)
	router.HandleFunc("/florence", refactoredIndexFile)
	router.HandleFunc("/florence/index.html", legacyIndexFile)
	router.HandleFunc("/florence{uri:|/.*}", refactoredIndexFile)
	router.Handle("/{uri:.*}", babbageProxy)

	log.Debug("Starting server", log.Data{
		"bind_addr":   bindAddr,
		"babbage_url": babbageURL,
		"zebedee_url": zebedeeURL,
	})

	s := server.New(bindAddr, router)

	s.ListenAndServe()
}

func staticFiles(w http.ResponseWriter, req *http.Request) {
	path := req.URL.Query().Get(":uri")

	b, err := getAsset("../dist/" + path)
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, mime.TypeByExtension(filepath.Ext(path)))
	w.WriteHeader(200)
	w.Write(b)
}

func legacyIndexFile(w http.ResponseWriter, req *http.Request) {
	log.Debug("Getting legacy HTML file", nil)

	b, err := getAsset("../dist/legacy-assets/index.html")
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, "text/html")
	w.WriteHeader(200)
	w.Write(b)
}

func refactoredIndexFile(w http.ResponseWriter, req *http.Request) {
	log.Debug("Getting refactored HTML file", nil)

	b, err := getAsset("../dist/refactored.html")
	if err != nil {
		log.Error(err, nil)
		w.WriteHeader(404)
		return
	}

	w.Header().Set(`Content-Type`, "text/html")
	w.WriteHeader(200)
	w.Write(b)
}

func zebedeeDirector(req *http.Request) {
	if c, err := req.Cookie(`access_token`); err == nil && len(c.Value) > 0 {
		req.Header.Set(`X-Florence-Token`, c.Value)
	}
	req.URL.Path = strings.TrimPrefix(req.URL.Path, "/zebedee")
}

type transport struct {
	http.RoundTripper
}

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	/* May need this to handle location later

	resp, err = t.RoundTripper.RoundTrip(req)
	if err != nil {
		return nil, err
	}
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	err = resp.Body.Close()
	if err != nil {
		return nil, err
	}
	b = bytes.Replace(b, []byte("server"), []byte("schmerver"), -1)
	body := ioutil.NopCloser(bytes.NewReader(b))
	resp.Body = body
	resp.ContentLength = int64(len(b))
	resp.Header.Set("Content-Length", strconv.Itoa(len(b)))
	return resp, nil */

	return t.RoundTripper.RoundTrip(req)
}

var _ http.RoundTripper = &transport{}
<|endoftext|>


<commit_before>package main

import (
	"./sdl"
)

func main() {
	sdl.Init(sdl.INIT_VIDEO)
	window := sdl.CreateWindow("Hello World!", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
				800, 600, sdl.WINDOW_SHOWN | sdl.WINDOW_OPENGL)
	renderer := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)

	renderer.SetDrawColor(0, 0, 255, 255)
	renderer.DrawLine(0, 0, 200, 200)

	points := []sdl.Point { {0, 0}, {100, 300}, {100, 300}, {200, 0} }
	renderer.SetDrawColor(255, 255, 0, 255)
	renderer.DrawLines(&points, 4)

	rect := sdl.Rect { 300, 0, 200, 200 }
	renderer.SetDrawColor(255, 0, 0, 255)
	renderer.DrawRect(&rect)

	rects := []sdl.Rect { {400, 400, 100, 100}, {550, 350, 200, 200} }
	renderer.SetDrawColor(0, 255, 255, 255)
	renderer.DrawRects(&rects, 2)

	rect = sdl.Rect { 250, 250, 200, 200 }
	renderer.SetDrawColor(0, 255, 0, 255)
	renderer.FillRect(&rect)

	rects = []sdl.Rect { {500, 300, 100, 100}, {200, 300, 200, 200} }
	renderer.SetDrawColor(255, 0, 255, 255)
	renderer.FillRects(&rects, 2)

	renderer.Present()

	sdl.Delay(1000)
}
<commit_msg>Updated main.go<commit_after>package main

import (
	"./sdl"
)

func main() {
	sdl.Init(sdl.INIT_VIDEO)
	window := sdl.CreateWindow("Hello World!", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
				800, 600, sdl.WINDOW_SHOWN | sdl.WINDOW_OPENGL)
	renderer := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)

	renderer.SetDrawColor(255, 255, 255, 255)
	renderer.DrawPoint(150, 300)

	renderer.SetDrawColor(0, 0, 255, 255)
	renderer.DrawLine(0, 0, 200, 200)

	points := []sdl.Point { {0, 0}, {100, 300}, {100, 300}, {200, 0} }
	renderer.SetDrawColor(255, 255, 0, 255)
	renderer.DrawLines(&points, 4)

	rect := sdl.Rect { 300, 0, 200, 200 }
	renderer.SetDrawColor(255, 0, 0, 255)
	renderer.DrawRect(&rect)

	rects := []sdl.Rect { {400, 400, 100, 100}, {550, 350, 200, 200} }
	renderer.SetDrawColor(0, 255, 255, 255)
	renderer.DrawRects(&rects, 2)

	rect = sdl.Rect { 250, 250, 200, 200 }
	renderer.SetDrawColor(0, 255, 0, 255)
	renderer.FillRect(&rect)

	rects = []sdl.Rect { {500, 300, 100, 100}, {200, 300, 200, 200} }
	renderer.SetDrawColor(255, 0, 255, 255)
	renderer.FillRects(&rects, 2)

	renderer.Present()

	sdl.Delay(1000)
	sdl.Quit()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"runtime"
	"unicode/utf8"

	"github.com/vheon/picker/terminal"
	"github.com/vheon/picker/tty"
)

func appendChar(s string, b rune) string {
	return s + string(b)
}

func backspace(s string) string {
	if l := len(s); l > 0 {
		_, size := utf8.DecodeLastRuneInString(s)
		return s[:l-size]
	}
	return s
}

func readAllCandidates(r io.Reader) []Candidate {
	scanner := bufio.NewScanner(r)
	var lines []Candidate
	for scanner.Scan() {
		lines = append(lines, NewCandidate(scanner.Text()))
	}
	return lines
}

func handle_input(picker *Picker, view *View, key rune) *View {
	switch key {
	case terminal.Ctrl_N:
		view.Down()
	case terminal.Ctrl_P:
		view.Up()
	case terminal.Backspace:
		view = picker.Answer(backspace(view.Query))
	case terminal.LF:
		view.Done = true
		view.ClearPrompt()
	case terminal.Ctrl_U, terminal.Ctrl_W:
		view = picker.Answer("")
	default:
		view = picker.Answer(appendChar(view.Query, key))
	}
	return view
}

var visibleRows = flag.Int("h", 20, "Number of visible candidates")

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

	tty := tty.New()
	tty.Stty("-echo", "-icanon")
	defer tty.Restore()

	terminal := terminal.NewTerminal(tty)

	if *visibleRows > terminal.Height {
		*visibleRows = terminal.Height - 1
	}
	if *visibleRows < 1 {
		*visibleRows = 1
	}

	picker := NewPicker(readAllCandidates(os.Stdin), *visibleRows)
	view := picker.Answer("")
	terminal.MakeRoom(view.Height)
	view.DrawOnTerminal(terminal)
	for !view.Done {
		view = handle_input(picker, view, tty.ReadRune())
		view.DrawOnTerminal(terminal)
	}
	fmt.Println(view.Selected())
}
<commit_msg>Rename variable<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"runtime"
	"unicode/utf8"

	"github.com/vheon/picker/terminal"
	"github.com/vheon/picker/tty"
)

func appendChar(s string, b rune) string {
	return s + string(b)
}

func backspace(s string) string {
	if l := len(s); l > 0 {
		_, size := utf8.DecodeLastRuneInString(s)
		return s[:l-size]
	}
	return s
}

func readAllCandidates(r io.Reader) []Candidate {
	scanner := bufio.NewScanner(r)
	var lines []Candidate
	for scanner.Scan() {
		lines = append(lines, NewCandidate(scanner.Text()))
	}
	return lines
}

func handle_input(picker *Picker, view *View, key rune) *View {
	switch key {
	case terminal.Ctrl_N:
		view.Down()
	case terminal.Ctrl_P:
		view.Up()
	case terminal.Backspace:
		view = picker.Answer(backspace(view.Query))
	case terminal.LF:
		view.Done = true
		view.ClearPrompt()
	case terminal.Ctrl_U, terminal.Ctrl_W:
		view = picker.Answer("")
	default:
		view = picker.Answer(appendChar(view.Query, key))
	}
	return view
}

var visibleRows = flag.Int("h", 20, "Number of visible candidates")

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

	tty := tty.New()
	tty.Stty("-echo", "-icanon")
	defer tty.Restore()

	term := terminal.NewTerminal(tty)

	if *visibleRows > term.Height {
		*visibleRows = term.Height - 1
	}
	if *visibleRows < 1 {
		*visibleRows = 1
	}

	picker := NewPicker(readAllCandidates(os.Stdin), *visibleRows)
	view := picker.Answer("")
	term.MakeRoom(view.Height)
	view.DrawOnTerminal(term)
	for !view.Done {
		view = handle_input(picker, view, tty.ReadRune())
		view.DrawOnTerminal(term)
	}
	fmt.Println(view.Selected())
}
<|endoftext|>


<commit_before>package main

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

	"github.com/urfave/cli"
	"github.com/gorilla/handlers"
)

func main() {
	app := cli.NewApp()
	app.Name = "serve"
	app.Usage = "Simple HTTP Server"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "dir, d",
			Value: ".",
			Usage: "Directory to serve",
		},
		cli.StringFlag{
			Name:  "address, a",
			Value: ":8080",
			Usage: "Address to listen on",
		},
		cli.BoolFlag{
			Name:  "log,l",
			Usage: "Log to stderr",
		},
		cli.StringFlag{
			Name:  "cert,c",
			Value: "",
			Usage: "Certificate for TLS",
		},
		cli.StringFlag{
			Name:  "key,k",
			Value: "",
			Usage: "Key for TLS",
		},
	}
	app.Action = func(c *cli.Context) {
		address := ":8080"
		dir := "."

		if c.String("dir") != "" {
			dir = c.String("dir")
		}
		if c.String("address") != "" {
			address = c.String("address")
		}
		server := handlers.CompressHandler(http.FileServer(http.Dir(dir)))
		if c.Bool("log") {
			server = handlers.LoggingHandler(os.Stderr, server)
		}
		cert := c.String("cert")
		key := c.String("key")
		// if cert or key are set, start TLS
		if cert != "" || key != "" {
			// Both cert and key must be set
			if cert == "" || key == "" {
				log.Fatalln("Both a certificate and key must be provided for TLS")
			}
			log.Fatalln(http.ListenAndServeTLS(address, cert, key, server))
		} else {
			// No cert and no key, just serve unencrypted
			log.Fatalln(http.ListenAndServe(address, server))
		}
	}

	app.Run(os.Args)
}
<commit_msg>adding SPDX copyright<commit_after>// Copyright (c) 2014-2021 Frederick F. Kautz IV
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 main

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

	"github.com/urfave/cli"
	"github.com/gorilla/handlers"
)

func main() {
	app := cli.NewApp()
	app.Name = "serve"
	app.Usage = "Simple HTTP Server"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "dir, d",
			Value: ".",
			Usage: "Directory to serve",
		},
		cli.StringFlag{
			Name:  "address, a",
			Value: ":8080",
			Usage: "Address to listen on",
		},
		cli.BoolFlag{
			Name:  "log,l",
			Usage: "Log to stderr",
		},
		cli.StringFlag{
			Name:  "cert,c",
			Value: "",
			Usage: "Certificate for TLS",
		},
		cli.StringFlag{
			Name:  "key,k",
			Value: "",
			Usage: "Key for TLS",
		},
	}
	app.Action = func(c *cli.Context) {
		address := ":8080"
		dir := "."

		if c.String("dir") != "" {
			dir = c.String("dir")
		}
		if c.String("address") != "" {
			address = c.String("address")
		}
		server := handlers.CompressHandler(http.FileServer(http.Dir(dir)))
		if c.Bool("log") {
			server = handlers.LoggingHandler(os.Stderr, server)
		}
		cert := c.String("cert")
		key := c.String("key")
		// if cert or key are set, start TLS
		if cert != "" || key != "" {
			// Both cert and key must be set
			if cert == "" || key == "" {
				log.Fatalln("Both a certificate and key must be provided for TLS")
			}
			log.Fatalln(http.ListenAndServeTLS(address, cert, key, server))
		} else {
			// No cert and no key, just serve unencrypted
			log.Fatalln(http.ListenAndServe(address, server))
		}
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/vbatts/overlay/mount"
	"github.com/vbatts/overlay/state"
)

var (
	flSrc        = flag.String("src", "", "source directory to overlay")
	flTarget     = flag.String("target", "", "destination to overlay to (default is ${src}.overlay)")
	flUnmount    = flag.Bool("unmount", false, "unmount directory all provided args")
	flRemove     = flag.String("remove", "", "remove the provided UUID")
	flRoot       = flag.String("root", filepath.Join(os.Getenv("HOME"), ".local/share/overlay/"), "Directory to story state of previous overlay mounts")
	flListMounts = flag.Bool("list", false, "list previously recorded mounts")
	flDebug      = flag.Bool("debug", false, "enable debug output")
)

func main() {
	flag.Parse()
	if *flDebug {
		os.Setenv("DEBUG", "1")
	}

	if *flUnmount {
		for _, arg := range flag.Args() {
			if err := mount.UnmountPath(arg); err != nil {
				fmt.Fprintf(os.Stderr, "ERROR: unmounting %q: %s\n", arg, err)
				os.Exit(1)
			}
		}
		if *flRemove == "" {
			os.Exit(0)
		}
	}

	ctx, err := state.Initialize(*flRoot)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}

	if *flRemove != "" {
		mounts, err := ctx.Mounts()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
		for _, m := range mounts {
			if m.UUID == *flRemove {
				if err := os.RemoveAll(m.Root()); err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
					os.Exit(1)
				}
			}
		}
		os.Exit(0)
	}

	if *flListMounts {
		mounts, err := ctx.Mounts()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
		for _, m := range mounts {
			fmt.Printf("TARGET\t\tSOURCE\t\tUUID\n")
			fmt.Printf("%s\t\t%s\t\t%s\n", m.Target, m.Source, m.UUID)
		}
		os.Exit(0)
	}

	if *flSrc == "" {
		fmt.Fprintln(os.Stderr, "ERROR: no source directory provided")
		os.Exit(1)
	}

	// TODO check for supported underlying filesystems (ext4, xfs)

	m := ctx.NewMountPoint()
	m.Source, err = filepath.Abs(*flSrc)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}

	if *flTarget != "" {
		m.Target, err = filepath.Abs(*flTarget)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
	}

	// check if target directory already mounted
	infos, err := mount.Infos()
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: mountinfo: %s\n", err)
		os.Exit(1)
	}
	for i := range infos {
		if infos[i].MountPoint == m.Target {
			fmt.Fprintf(os.Stderr, "ERROR: %q is already mounted\n", m.Target)
			os.Exit(1)
		}
	}

	// TODO add cleanup mechanism if something later fails
	if err := m.Mkdir(0755); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
	fmt.Println(m.Target)

	if *flDebug {
		fmt.Println(m.Options())
	}

	if err := mount.Mount(m); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
	if err := ctx.SaveMount(m); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
}
<commit_msg>main: fix the list formatting<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/vbatts/overlay/mount"
	"github.com/vbatts/overlay/state"
)

var (
	flSrc        = flag.String("src", "", "source directory to overlay")
	flTarget     = flag.String("target", "", "destination to overlay to (default is ${src}.overlay)")
	flUnmount    = flag.Bool("unmount", false, "unmount directory all provided args")
	flRemove     = flag.String("remove", "", "remove the provided UUID")
	flRoot       = flag.String("root", filepath.Join(os.Getenv("HOME"), ".local/share/overlay/"), "Directory to story state of previous overlay mounts")
	flListMounts = flag.Bool("list", false, "list previously recorded mounts")
	flDebug      = flag.Bool("debug", false, "enable debug output")
)

func main() {
	flag.Parse()
	if *flDebug {
		os.Setenv("DEBUG", "1")
	}

	if *flUnmount {
		for _, arg := range flag.Args() {
			if err := mount.UnmountPath(arg); err != nil {
				fmt.Fprintf(os.Stderr, "ERROR: unmounting %q: %s\n", arg, err)
				os.Exit(1)
			}
		}
		if *flRemove == "" {
			os.Exit(0)
		}
	}

	ctx, err := state.Initialize(*flRoot)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}

	if *flRemove != "" {
		mounts, err := ctx.Mounts()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
		for _, m := range mounts {
			if m.UUID == *flRemove {
				if err := os.RemoveAll(m.Root()); err != nil {
					fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
					os.Exit(1)
				}
			}
		}
		os.Exit(0)
	}

	if *flListMounts {
		mounts, err := ctx.Mounts()
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
		fmt.Printf("TARGET\t\tSOURCE\t\tUUID\n")
		for _, m := range mounts {
			fmt.Printf("%s\t\t%s\t\t%s\n", m.Target, m.Source, m.UUID)
		}
		os.Exit(0)
	}

	if *flSrc == "" {
		fmt.Fprintln(os.Stderr, "ERROR: no source directory provided")
		os.Exit(1)
	}

	// TODO check for supported underlying filesystems (ext4, xfs)

	m := ctx.NewMountPoint()
	m.Source, err = filepath.Abs(*flSrc)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}

	if *flTarget != "" {
		m.Target, err = filepath.Abs(*flTarget)
		if err != nil {
			fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
			os.Exit(1)
		}
	}

	// check if target directory already mounted
	infos, err := mount.Infos()
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: mountinfo: %s\n", err)
		os.Exit(1)
	}
	for i := range infos {
		if infos[i].MountPoint == m.Target {
			fmt.Fprintf(os.Stderr, "ERROR: %q is already mounted\n", m.Target)
			os.Exit(1)
		}
	}

	// TODO add cleanup mechanism if something later fails
	if err := m.Mkdir(0755); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
	fmt.Println(m.Target)

	if *flDebug {
		fmt.Println(m.Options())
	}

	if err := mount.Mount(m); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
	if err := ctx.SaveMount(m); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"compress/zlib"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type proxyPattern struct {
	matches  []string
	proxyURL *url.URL
}

type config struct { // nolint
	ProxyPatterns    []proxyPattern
	proxyURL         *url.URL // PROXY_URL
	basicAuthUser    string   // BASIC_AUTH_USER
	basicAuthPass    string   // BASIC_AUTH_PASS
	port             string   // APP_PORT
	accessLog        bool     // ACCESS_LOG
	sslCert          string   // SSL_CERT_PATH
	sslKey           string   // SSL_KEY_PATH
	contentEncoding  bool     // CONTENT_ENCODING
	corsAllowOrigin  string   // CORS_ALLOW_ORIGIN
	corsAllowMethods string   // CORS_ALLOW_METHODS
	corsAllowHeaders string   // CORS_ALLOW_HEADERS
	corsMaxAge       int64    // CORS_MAX_AGE
	healthCheckPath  string   // HEALTHCHECK_PATH
	useForwardedHost bool     // USE_X_FORWARDED_HOST
}

var (
	version string
	date    string
	c       *config
)

func main() {
	c = configFromEnvironmentVariables()

	// Proxy!!
	http.Handle("/", wrapper(&httputil.ReverseProxy{
		Director: func(r *http.Request) {
			if c.useForwardedHost {
				r.Header.Set("X-Forwarded-Host", r.Host)
			}
			found := false
			for _, patterns := range c.ProxyPatterns {
				if match(patterns.matches[0], r.URL.Scheme, false) &&
					match(patterns.matches[1], r.Host, false) &&
					match(patterns.matches[3], r.URL.Path, true) {
					if c.useForwardedHost {
						r.Host = patterns.proxyURL.Host
						r.URL.Host = r.Host
					} else {
						r.URL.Host = patterns.proxyURL.Host
					}
					r.URL.Scheme = patterns.proxyURL.Scheme
					found = true
					break
				}
			}
			if !found {
				r.Host = c.proxyURL.Host
				r.URL.Host = r.Host
				r.URL.Scheme = c.proxyURL.Scheme
			}
		},
	}))

	if c.healthCheckPath != "" {
		http.HandleFunc(c.healthCheckPath, func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusOK)
		})
	}

	http.HandleFunc("/--version", func(w http.ResponseWriter, r *http.Request) {
		if len(version) > 0 && len(date) > 0 {
			fmt.Fprintf(w, "version: %s (built at %s)", version, date)
		} else {
			w.WriteHeader(http.StatusOK)
		}
	})

	// Listen & Serve
	log.Printf("[service] listening on port %s", c.port)
	if (len(c.sslCert) > 0) && (len(c.sslKey) > 0) {
		log.Fatal(http.ListenAndServeTLS(":"+c.port, c.sslCert, c.sslKey, nil))
	} else {
		log.Fatal(http.ListenAndServe(":"+c.port, nil))
	}
}

func match(pattern, target string, isPath bool) bool {
	if pattern == "" {
		return true
	}
	pattern = strings.Replace(pattern, "*", ".*", -1)
	if isPath && !strings.HasSuffix(pattern, "/") {
		pattern += "$"
	}
	match, _ := regexp.MatchString(pattern, target)
	return match
}

func configFromEnvironmentVariables() *config {
	candidateProxyURL := strings.Trim(os.Getenv("PROXY_URL"), "\"")
	candidateProxyPatterns := strings.Trim(os.Getenv("PROXY_PATTERNS"), "\"")
	if len(candidateProxyURL) == 0 && len(candidateProxyPatterns) == 0 {
		log.Fatal("Missing required environment variable: PROXY_URL or PROXY_PATTERNS")
	}
	var proxyURL *url.URL
	var err error
	if len(candidateProxyURL) > 0 {
		proxyURL, err = url.Parse(candidateProxyURL)
		if err != nil {
			log.Fatalf("Could not parse proxy URL: %s", candidateProxyURL)
		}
	}
	ProxyPatterns := []proxyPattern{}
	if len(candidateProxyPatterns) > 0 {
		regex := regexp.MustCompile(`(https?://)?([^:^/]*)(:\\d*)?(.*)?`)
		for _, pattern := range strings.Split(candidateProxyPatterns, ",") {
			splited := strings.Split(pattern, "=")
			if url, err := url.Parse(splited[1]); err == nil {
				pattern := proxyPattern{
					matches:  regex.FindStringSubmatch(splited[0])[1:],
					proxyURL: url,
				}
				ProxyPatterns = append(ProxyPatterns, pattern)
			}
		}
	}
	port := os.Getenv("APP_PORT")
	if len(port) == 0 {
		port = "80"
	}
	accessLog := false
	if b, err := strconv.ParseBool(os.Getenv("ACCESS_LOG")); err == nil {
		accessLog = b
	}
	contentEncoging := false
	if b, err := strconv.ParseBool(os.Getenv("CONTENT_ENCODING")); err == nil {
		contentEncoging = b
	}
	corsMaxAge := int64(600)
	if i, err := strconv.ParseInt(os.Getenv("CORS_MAX_AGE"), 10, 64); err == nil {
		corsMaxAge = i
	}
	useForwardedHost := true
	if b, err := strconv.ParseBool(os.Getenv("USE_X_FORWARDED_HOST")); err == nil {
		useForwardedHost = b
	}
	conf := &config{
		ProxyPatterns:    ProxyPatterns,
		proxyURL:         proxyURL,
		basicAuthUser:    os.Getenv("BASIC_AUTH_USER"),
		basicAuthPass:    os.Getenv("BASIC_AUTH_PASS"),
		port:             port,
		accessLog:        accessLog,
		sslCert:          os.Getenv("SSL_CERT_PATH"),
		sslKey:           os.Getenv("SSL_KEY_PATH"),
		contentEncoding:  contentEncoging,
		corsAllowOrigin:  os.Getenv("CORS_ALLOW_ORIGIN"),
		corsAllowMethods: os.Getenv("CORS_ALLOW_METHODS"),
		corsAllowHeaders: os.Getenv("CORS_ALLOW_HEADERS"),
		corsMaxAge:       corsMaxAge,
		healthCheckPath:  os.Getenv("HEALTHCHECK_PATH"),
		useForwardedHost: useForwardedHost,
	}
	// TLS pem files
	if (len(conf.sslCert) > 0) && (len(conf.sslKey) > 0) {
		log.Print("[config] TLS enabled.")
	}
	// Basic authentication
	if (len(conf.basicAuthUser) > 0) && (len(conf.basicAuthPass) > 0) {
		log.Printf("[config] Basic authentication: %s", conf.basicAuthUser)
	}
	// CORS
	if (len(conf.corsAllowOrigin) > 0) && (conf.corsMaxAge > 0) {
		log.Printf("[config] CORS enabled: %s", conf.corsAllowOrigin)
	}
	return conf
}

type custom struct {
	io.Writer
	http.ResponseWriter
	status int
}

func (r *custom) Write(b []byte) (int, error) {
	if r.Header().Get("Content-Type") == "" {
		r.Header().Set("Content-Type", http.DetectContentType(b))
	}
	return r.Writer.Write(b)
}

func (r *custom) WriteHeader(status int) {
	r.ResponseWriter.WriteHeader(status)
	r.status = status
}

func wrapper(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if (len(c.corsAllowOrigin) > 0) && (len(c.corsAllowMethods) > 0) && (len(c.corsAllowHeaders) > 0) && (c.corsMaxAge > 0) {
			w.Header().Set("Access-Control-Allow-Origin", c.corsAllowOrigin)
			w.Header().Set("Access-Control-Allow-Methods", c.corsAllowMethods)
			w.Header().Set("Access-Control-Allow-Headers", c.corsAllowHeaders)
			w.Header().Set("Access-Control-Max-Age", strconv.FormatInt(c.corsMaxAge, 10))
		}
		if (len(c.basicAuthUser) > 0) && (len(c.basicAuthPass) > 0) && !auth(r, c.basicAuthUser, c.basicAuthPass) {
			w.Header().Set("WWW-Authenticate", `Basic realm="REALM"`)
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
			return
		}
		proc := time.Now()
		addr := r.RemoteAddr
		if ip, found := header(r, "X-Forwarded-For"); found {
			addr = ip
		}
		ioWriter := w.(io.Writer)
		if encodings, found := header(r, "Accept-Encoding"); found && c.contentEncoding {
			for _, encoding := range splitCsvLine(encodings) {
				if encoding == "gzip" {
					w.Header().Set("Content-Encoding", "gzip")
					g := gzip.NewWriter(w)
					defer g.Close()
					ioWriter = g
					break
				}
				if encoding == "deflate" {
					w.Header().Set("Content-Encoding", "deflate")
					z := zlib.NewWriter(w)
					defer z.Close()
					ioWriter = z
					break
				}
			}
		}
		writer := &custom{Writer: ioWriter, ResponseWriter: w, status: http.StatusOK}
		h.ServeHTTP(writer, r)

		if c.accessLog {
			log.Printf("[%s] %.3f %d %s %s",
				addr, time.Since(proc).Seconds(),
				writer.status, r.Method, r.URL)
		}
	})
}

func header(r *http.Request, key string) (string, bool) {
	if r.Header == nil {
		return "", false
	}
	if candidate := r.Header[key]; len(candidate) > 0 {
		return candidate[0], true
	}
	return "", false
}

func splitCsvLine(data string) []string {
	splitted := strings.SplitN(data, ",", -1)
	parsed := make([]string, len(splitted))
	for i, val := range splitted {
		parsed[i] = strings.TrimSpace(val)
	}
	return parsed
}

func auth(r *http.Request, user, pass string) bool {
	if username, password, ok := r.BasicAuth(); ok {
		return username == user && password == pass
	}
	return false
}
<commit_msg>fix typo<commit_after>package main

import (
	"compress/gzip"
	"compress/zlib"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type proxyPattern struct {
	matches  []string
	proxyURL *url.URL
}

type config struct { // nolint
	ProxyPatterns    []proxyPattern
	proxyURL         *url.URL // PROXY_URL
	basicAuthUser    string   // BASIC_AUTH_USER
	basicAuthPass    string   // BASIC_AUTH_PASS
	port             string   // APP_PORT
	accessLog        bool     // ACCESS_LOG
	sslCert          string   // SSL_CERT_PATH
	sslKey           string   // SSL_KEY_PATH
	contentEncoding  bool     // CONTENT_ENCODING
	corsAllowOrigin  string   // CORS_ALLOW_ORIGIN
	corsAllowMethods string   // CORS_ALLOW_METHODS
	corsAllowHeaders string   // CORS_ALLOW_HEADERS
	corsMaxAge       int64    // CORS_MAX_AGE
	healthCheckPath  string   // HEALTHCHECK_PATH
	useForwardedHost bool     // USE_X_FORWARDED_HOST
}

var (
	version string
	date    string
	c       *config
)

func main() {
	c = configFromEnvironmentVariables()

	// Proxy!!
	http.Handle("/", wrapper(&httputil.ReverseProxy{
		Director: func(r *http.Request) {
			if c.useForwardedHost {
				r.Header.Set("X-Forwarded-Host", r.Host)
			}
			found := false
			for _, patterns := range c.ProxyPatterns {
				if match(patterns.matches[0], r.URL.Scheme, false) &&
					match(patterns.matches[1], r.Host, false) &&
					match(patterns.matches[3], r.URL.Path, true) {
					if c.useForwardedHost {
						r.Host = patterns.proxyURL.Host
						r.URL.Host = r.Host
					} else {
						r.URL.Host = patterns.proxyURL.Host
					}
					r.URL.Scheme = patterns.proxyURL.Scheme
					found = true
					break
				}
			}
			if !found {
				r.Host = c.proxyURL.Host
				r.URL.Host = r.Host
				r.URL.Scheme = c.proxyURL.Scheme
			}
		},
	}))

	if c.healthCheckPath != "" {
		http.HandleFunc(c.healthCheckPath, func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusOK)
		})
	}

	http.HandleFunc("/--version", func(w http.ResponseWriter, r *http.Request) {
		if len(version) > 0 && len(date) > 0 {
			fmt.Fprintf(w, "version: %s (built at %s)", version, date)
		} else {
			w.WriteHeader(http.StatusOK)
		}
	})

	// Listen & Serve
	log.Printf("[service] listening on port %s", c.port)
	if (len(c.sslCert) > 0) && (len(c.sslKey) > 0) {
		log.Fatal(http.ListenAndServeTLS(":"+c.port, c.sslCert, c.sslKey, nil))
	} else {
		log.Fatal(http.ListenAndServe(":"+c.port, nil))
	}
}

func match(pattern, target string, isPath bool) bool {
	if pattern == "" {
		return true
	}
	pattern = strings.Replace(pattern, "*", ".*", -1)
	if isPath && !strings.HasSuffix(pattern, "/") {
		pattern += "$"
	}
	match, _ := regexp.MatchString(pattern, target)
	return match
}

func configFromEnvironmentVariables() *config {
	candidateProxyURL := strings.Trim(os.Getenv("PROXY_URL"), "\"")
	candidateProxyPatterns := strings.Trim(os.Getenv("PROXY_PATTERNS"), "\"")
	if len(candidateProxyURL) == 0 && len(candidateProxyPatterns) == 0 {
		log.Fatal("Missing required environment variable: PROXY_URL or PROXY_PATTERNS")
	}
	var proxyURL *url.URL
	var err error
	if len(candidateProxyURL) > 0 {
		proxyURL, err = url.Parse(candidateProxyURL)
		if err != nil {
			log.Fatalf("Could not parse proxy URL: %s", candidateProxyURL)
		}
	}
	ProxyPatterns := []proxyPattern{}
	if len(candidateProxyPatterns) > 0 {
		regex := regexp.MustCompile(`(https?://)?([^:^/]*)(:\\d*)?(.*)?`)
		for _, pattern := range strings.Split(candidateProxyPatterns, ",") {
			splited := strings.Split(pattern, "=")
			if url, err := url.Parse(splited[1]); err == nil {
				pattern := proxyPattern{
					matches:  regex.FindStringSubmatch(splited[0])[1:],
					proxyURL: url,
				}
				ProxyPatterns = append(ProxyPatterns, pattern)
			}
		}
	}
	port := os.Getenv("APP_PORT")
	if len(port) == 0 {
		port = "80"
	}
	accessLog := false
	if b, err := strconv.ParseBool(os.Getenv("ACCESS_LOG")); err == nil {
		accessLog = b
	}
	contentEncoding := false
	if b, err := strconv.ParseBool(os.Getenv("CONTENT_ENCODING")); err == nil {
		contentEncoding = b
	}
	corsMaxAge := int64(600)
	if i, err := strconv.ParseInt(os.Getenv("CORS_MAX_AGE"), 10, 64); err == nil {
		corsMaxAge = i
	}
	useForwardedHost := true
	if b, err := strconv.ParseBool(os.Getenv("USE_X_FORWARDED_HOST")); err == nil {
		useForwardedHost = b
	}
	conf := &config{
		ProxyPatterns:    ProxyPatterns,
		proxyURL:         proxyURL,
		basicAuthUser:    os.Getenv("BASIC_AUTH_USER"),
		basicAuthPass:    os.Getenv("BASIC_AUTH_PASS"),
		port:             port,
		accessLog:        accessLog,
		sslCert:          os.Getenv("SSL_CERT_PATH"),
		sslKey:           os.Getenv("SSL_KEY_PATH"),
		contentEncoding:  contentEncoding,
		corsAllowOrigin:  os.Getenv("CORS_ALLOW_ORIGIN"),
		corsAllowMethods: os.Getenv("CORS_ALLOW_METHODS"),
		corsAllowHeaders: os.Getenv("CORS_ALLOW_HEADERS"),
		corsMaxAge:       corsMaxAge,
		healthCheckPath:  os.Getenv("HEALTHCHECK_PATH"),
		useForwardedHost: useForwardedHost,
	}
	// TLS pem files
	if (len(conf.sslCert) > 0) && (len(conf.sslKey) > 0) {
		log.Print("[config] TLS enabled.")
	}
	// Basic authentication
	if (len(conf.basicAuthUser) > 0) && (len(conf.basicAuthPass) > 0) {
		log.Printf("[config] Basic authentication: %s", conf.basicAuthUser)
	}
	// CORS
	if (len(conf.corsAllowOrigin) > 0) && (conf.corsMaxAge > 0) {
		log.Printf("[config] CORS enabled: %s", conf.corsAllowOrigin)
	}
	return conf
}

type custom struct {
	io.Writer
	http.ResponseWriter
	status int
}

func (r *custom) Write(b []byte) (int, error) {
	if r.Header().Get("Content-Type") == "" {
		r.Header().Set("Content-Type", http.DetectContentType(b))
	}
	return r.Writer.Write(b)
}

func (r *custom) WriteHeader(status int) {
	r.ResponseWriter.WriteHeader(status)
	r.status = status
}

func wrapper(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if (len(c.corsAllowOrigin) > 0) && (len(c.corsAllowMethods) > 0) && (len(c.corsAllowHeaders) > 0) && (c.corsMaxAge > 0) {
			w.Header().Set("Access-Control-Allow-Origin", c.corsAllowOrigin)
			w.Header().Set("Access-Control-Allow-Methods", c.corsAllowMethods)
			w.Header().Set("Access-Control-Allow-Headers", c.corsAllowHeaders)
			w.Header().Set("Access-Control-Max-Age", strconv.FormatInt(c.corsMaxAge, 10))
		}
		if (len(c.basicAuthUser) > 0) && (len(c.basicAuthPass) > 0) && !auth(r, c.basicAuthUser, c.basicAuthPass) {
			w.Header().Set("WWW-Authenticate", `Basic realm="REALM"`)
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
			return
		}
		proc := time.Now()
		addr := r.RemoteAddr
		if ip, found := header(r, "X-Forwarded-For"); found {
			addr = ip
		}
		ioWriter := w.(io.Writer)
		if encodings, found := header(r, "Accept-Encoding"); found && c.contentEncoding {
			for _, encoding := range splitCsvLine(encodings) {
				if encoding == "gzip" {
					w.Header().Set("Content-Encoding", "gzip")
					g := gzip.NewWriter(w)
					defer g.Close()
					ioWriter = g
					break
				}
				if encoding == "deflate" {
					w.Header().Set("Content-Encoding", "deflate")
					z := zlib.NewWriter(w)
					defer z.Close()
					ioWriter = z
					break
				}
			}
		}
		writer := &custom{Writer: ioWriter, ResponseWriter: w, status: http.StatusOK}
		h.ServeHTTP(writer, r)

		if c.accessLog {
			log.Printf("[%s] %.3f %d %s %s",
				addr, time.Since(proc).Seconds(),
				writer.status, r.Method, r.URL)
		}
	})
}

func header(r *http.Request, key string) (string, bool) {
	if r.Header == nil {
		return "", false
	}
	if candidate := r.Header[key]; len(candidate) > 0 {
		return candidate[0], true
	}
	return "", false
}

func splitCsvLine(data string) []string {
	splitted := strings.SplitN(data, ",", -1)
	parsed := make([]string, len(splitted))
	for i, val := range splitted {
		parsed[i] = strings.TrimSpace(val)
	}
	return parsed
}

func auth(r *http.Request, user, pass string) bool {
	if username, password, ok := r.BasicAuth(); ok {
		return username == user && password == pass
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
)

// Metric holds the details of a metric
type Metric struct {
	Name      string            `json:"name"`
	Timestamp int               `json:"timestamp"`
	Value     float64           `json:"value"`
	Tags      map[string]string `json:"tags"`
}

func main() {
	host := flag.String("host", "localhost:4242", "The host:port to connect to. Defaults to 'localhost:4242'")
	flag.Parse()

	dec := json.NewDecoder(os.Stdin)
	conn, err := net.Dial("tcp", *host)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	for {
		var m Metric
		if err := dec.Decode(&m); err == io.EOF {
			break
		} else if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		o := fmt.Sprintf("put %s %d %f", m.Name, m.Timestamp, m.Value)

		for name, value := range m.Tags {
			o += fmt.Sprintf(" %s=%s", name, value)
		}

		o += "\r"

		fmt.Fprint(conn, o)
	}
}
<commit_msg>Changes \r to \n<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
)

// Metric holds the details of a metric
type Metric struct {
	Name      string            `json:"name"`
	Timestamp int               `json:"timestamp"`
	Value     float64           `json:"value"`
	Tags      map[string]string `json:"tags"`
}

func main() {
	host := flag.String("host", "localhost:4242", "The host:port to connect to. Defaults to 'localhost:4242'")
	flag.Parse()

	dec := json.NewDecoder(os.Stdin)
	conn, err := net.Dial("tcp", *host)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	for {
		var m Metric
		if err := dec.Decode(&m); err == io.EOF {
			break
		} else if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		o := fmt.Sprintf("put %s %d %f", m.Name, m.Timestamp, m.Value)

		for name, value := range m.Tags {
			o += fmt.Sprintf(" %s=%s", name, value)
		}

		o += "\n"

		fmt.Fprint(conn, o)
	}
}
<|endoftext|>