<commit_before>package main

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"

	"github.com/GeertJohan/yubigo"
)

type authProxyHandler struct {
	acl              *ACLConfig
	cache            Cache
	authCookieName   string
	proxy            *httputil.ReverseProxy
	yubiAuth         *yubigo.YubiAuth
	cookieExpiration time.Duration
}

// Returns a boolean only (no error) to make validation of this return value easier.
func (a *authProxyHandler) validateCredentialsForEntry(entry UserEntry, username, password, yubiKey string) bool {

	// Validate username.

	if entry.Username != username {
		// This check is done in the caller, too. Keeping it here just
		// to be cautious.
		return false
	}

	// Validate password.

	if ok, err := entry.PasswordHash.Test(password); !ok {
		logger.Info(PasswordOrOTPFailed{username, err.Error()})
		return false
	}

	// Validate Yubikey.

	_, ok, err := a.yubiAuth.Verify(yubiKey)
	if err != nil {
		logger.Error(CouldNotValidateAgainstYubico{err.Error()})
	}

	logger.Info(AuthenticationSuccesful{username})

	return ok
}

func (a *authProxyHandler) validateCredentials(username string, basicAuthPassword string) (bool, error) {
	if len(username) == 0 {
		return false, errors.New("Username must not be empty.")
	}

	if len(basicAuthPassword) < 44 {
		return false, errors.New("Yubikey missing.")
	}
	passwordString := basicAuthPassword[0 : len(basicAuthPassword)-44]
	yubikeyString := basicAuthPassword[len(basicAuthPassword)-44:]

	foundAUser := false
	for _, entry := range a.acl.Entries {
		if entry.Username != username {
			continue
		}

		foundAUser = true

		if a.validateCredentialsForEntry(entry, username, passwordString, yubikeyString) {
			return true, nil
		}
	}

	if !foundAUser {
		logger.Info(CouldNotFindUsername{username})
	}

	return false, nil
}

func (a authProxyHandler) isAuthenticated(req *http.Request) bool {
	if cookie, err := req.Cookie(a.authCookieName); err != nil {
		return false
	}
	return a.cache.Contains(cookie.Value)
}

func generateRandomString(bytesSource int) (string, error) {
	slots := make([]byte, 32)
	if _, err := rand.Reader.Read(slots); err != nil {
		return "", err
	}
	return hex.EncodeToString(slots), nil

}

func (a authProxyHandler) stripAuthCookie(req *http.Request) {
	if cookieHeaders, ok := req.Header["Cookie"]; ok {
		for i, cookieHeader := range cookieHeaders {
			cookies := strings.Split(cookieHeader, "; ")
			newCookies := make([]string, 0)
			for _, cookie := range cookies {
				if !strings.HasPrefix(cookie, a.authCookieName+"=") {
					newCookies = append(newCookies, cookie)
				}
			}
			cookieHeaders[i] = strings.Join(newCookies, "; ")
		}
	}
}

func (a authProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	valid := false

	if a.isAuthenticated(req) {
		valid = true
	}

	if !valid {
		var username, password string
		var ok bool

		if username, password, ok = req.BasicAuth(); ok {
			var err error
			valid, err = a.validateCredentials(username, password)
			if err != nil {
				logger.Error(UnableToValidateCredentials{username, err.Error()})
			}
		}

		var randValue string
		if _randValue, err := generateRandomString(32); err != nil {
			logger.Error(UnableToGenerateRandomString{})
			resp.WriteHeader(http.StatusInternalServerError)
			return
		}
		randValue = _randValue

		cookie := http.Cookie{
			Name:     a.authCookieName,
			Value:    randValue,
			MaxAge:   int(a.cookieExpiration.Seconds()),
			HttpOnly: true,
		}
		if *serveCookieDomain != "" {
			cookie.Domain = *serveCookieDomain
		} else if host := req.Header.Get("Host"); host != "" {
			cookie.Domain = host
		}
		if *serveCookieSecure || !*insecure {
			cookie.Secure = true
		}

		http.SetCookie(resp, &cookie)
		a.cache.AddOrUpdate(randValue, func() {
			logger.Debug(SessionExpired{username})
		})
	}

	if valid {

		// Important we don't proxy our username and password upstream!
		delete(req.Header, "Authorization")

		// Don't proxy the auth cookie.
		a.stripAuthCookie(req)

		logger.Info(Proxying{req.RemoteAddr, req.URL.String()})

		a.proxy.ServeHTTP(resp, req)
	} else {
		logger.Debug(AskedUserToAuthenticate{req.RemoteAddr})

		// Ask for authentication
		resp.Header()["WWW-Authenticate"] = []string{"Basic realm=\"Please enter your username, followed by password+yubikey\""}
		resp.WriteHeader(http.StatusUnauthorized)
	}
}
<commit_msg>Revert "refactor(web): avoid unnecessary `else`s"<commit_after>package main

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"

	"github.com/GeertJohan/yubigo"
)

type authProxyHandler struct {
	acl              *ACLConfig
	cache            Cache
	authCookieName   string
	proxy            *httputil.ReverseProxy
	yubiAuth         *yubigo.YubiAuth
	cookieExpiration time.Duration
}

// Returns a boolean only (no error) to make validation of this return value easier.
func (a *authProxyHandler) validateCredentialsForEntry(entry UserEntry, username, password, yubiKey string) bool {

	// Validate username.

	if entry.Username != username {
		// This check is done in the caller, too. Keeping it here just
		// to be cautious.
		return false
	}

	// Validate password.

	if ok, err := entry.PasswordHash.Test(password); !ok {
		logger.Info(PasswordOrOTPFailed{username, err.Error()})
		return false
	}

	// Validate Yubikey.

	_, ok, err := a.yubiAuth.Verify(yubiKey)
	if err != nil {
		logger.Error(CouldNotValidateAgainstYubico{err.Error()})
	}

	logger.Info(AuthenticationSuccesful{username})

	return ok
}

func (a *authProxyHandler) validateCredentials(username string, basicAuthPassword string) (bool, error) {
	if len(username) == 0 {
		return false, errors.New("Username must not be empty.")
	}

	if len(basicAuthPassword) < 44 {
		return false, errors.New("Yubikey missing.")
	}
	passwordString := basicAuthPassword[0 : len(basicAuthPassword)-44]
	yubikeyString := basicAuthPassword[len(basicAuthPassword)-44:]

	foundAUser := false
	for _, entry := range a.acl.Entries {
		if entry.Username != username {
			continue
		}

		foundAUser = true

		if a.validateCredentialsForEntry(entry, username, passwordString, yubikeyString) {
			return true, nil
		}
	}

	if !foundAUser {
		logger.Info(CouldNotFindUsername{username})
	}

	return false, nil
}

func (a authProxyHandler) isAuthenticated(req *http.Request) bool {
	if cookie, err := req.Cookie(a.authCookieName); err != nil {
		return false
	} else {
		return a.cache.Contains(cookie.Value)
	}
}

func generateRandomString(bytesSource int) (string, error) {
	slots := make([]byte, 32)
	if _, err := rand.Reader.Read(slots); err != nil {
		return "", err
	} else {
		return hex.EncodeToString(slots), nil
	}

}

func (a authProxyHandler) stripAuthCookie(req *http.Request) {
	if cookieHeaders, ok := req.Header["Cookie"]; ok {
		for i, cookieHeader := range cookieHeaders {
			cookies := strings.Split(cookieHeader, "; ")
			newCookies := make([]string, 0)
			for _, cookie := range cookies {
				if !strings.HasPrefix(cookie, a.authCookieName+"=") {
					newCookies = append(newCookies, cookie)
				}
			}
			cookieHeaders[i] = strings.Join(newCookies, "; ")
		}
	}
}

func (a authProxyHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	valid := false

	if a.isAuthenticated(req) {
		valid = true
	}

	if !valid {
		var username, password string
		var ok bool

		if username, password, ok = req.BasicAuth(); ok {
			var err error
			valid, err = a.validateCredentials(username, password)
			if err != nil {
				logger.Error(UnableToValidateCredentials{username, err.Error()})
			}
		}

		var randValue string
		if _randValue, err := generateRandomString(32); err != nil {
			logger.Error(UnableToGenerateRandomString{})
			resp.WriteHeader(http.StatusInternalServerError)
			return
		} else {
			randValue = _randValue
		}

		cookie := http.Cookie{
			Name:     a.authCookieName,
			Value:    randValue,
			MaxAge:   int(a.cookieExpiration.Seconds()),
			HttpOnly: true,
		}
		if *serveCookieDomain != "" {
			cookie.Domain = *serveCookieDomain
		} else if host := req.Header.Get("Host"); host != "" {
			cookie.Domain = host
		}
		if *serveCookieSecure || !*insecure {
			cookie.Secure = true
		}

		http.SetCookie(resp, &cookie)
		a.cache.AddOrUpdate(randValue, func() {
			logger.Debug(SessionExpired{username})
		})
	}

	if valid {

		// Important we don't proxy our username and password upstream!
		delete(req.Header, "Authorization")

		// Don't proxy the auth cookie.
		a.stripAuthCookie(req)

		logger.Info(Proxying{req.RemoteAddr, req.URL.String()})

		a.proxy.ServeHTTP(resp, req)
	} else {
		logger.Debug(AskedUserToAuthenticate{req.RemoteAddr})

		// Ask for authentication
		resp.Header()["WWW-Authenticate"] = []string{"Basic realm=\"Please enter your username, followed by password+yubikey\""}
		resp.WriteHeader(http.StatusUnauthorized)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/go-martini/martini"
	"github.com/timothyye/vim-tips-web/routers"
	"net/http"
)

var (
	m = martini.Classic()
)

func main() {
	routers.Initialize(m)

	http.HandleFunc("/ws", routers.WSHandler)
	http.Handle("/", m)

	fmt.Println("Server started...")

	err := http.ListenAndServe("0.0.0.0:3000", nil)
	if err != nil {
		fmt.Println(err)
	}
}

func ShowMessage(mess string) {
	fmt.Println(mess)
}
<commit_msg>Update web.go<commit_after>package main

import (
	"fmt"
	"github.com/go-martini/martini"
	"github.com/timothyye/vim-tips-web/routers"
	"net/http"
)

var (
	m = martini.Classic()
)

func main() {
	routers.Initialize(m)

	http.HandleFunc("/ws", routers.WSHandler)
	http.Handle("/", m)

	fmt.Println("Server started...")

	err := http.ListenAndServe("127.0.0.1:3000", nil)
	if err != nil {
		fmt.Println(err)
	}
}

func ShowMessage(mess string) {
	fmt.Println(mess)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"time"

	"./workday"
)

func pathToYearMonth(p string) (int, time.Month, error) {
	r := regexp.MustCompile(`/(\d+)/(\d+)`)
	matches := r.FindStringSubmatch(p)
	if matches == nil {
		return 0, 0, errors.New("failed to parse url")
	}
	year, err := strconv.Atoi(matches[1])
	if err != nil {
		return 0, 0, err
	}
	month, err := strconv.Atoi(matches[2])
	if err != nil {
		return 0, 0, err
	}
	return year, time.Month(month), nil
}

func webHandler(w http.ResponseWriter, r *http.Request) {
	year, month, err := pathToYearMonth(r.URL.Path)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	days, err := workday.DaysForMonth(year, month)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for _, d := range days {
		fmt.Fprintln(w, d.String())
	}
}

func web() error {
	http.HandleFunc("/", webHandler)
	log.Println("Starting server on port 8080")
	return http.ListenAndServe(":8080", nil)
}
<commit_msg>redirect to current month if the url is invalid<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"time"

	"./workday"
)

func pathToYearMonth(p string) (int, time.Month, error) {
	r := regexp.MustCompile(`/(\d+)/(\d+)`)
	matches := r.FindStringSubmatch(p)
	if matches == nil {
		return 0, 0, errors.New("failed to parse url")
	}
	year, err := strconv.Atoi(matches[1])
	if err != nil {
		return 0, 0, err
	}
	month, err := strconv.Atoi(matches[2])
	if err != nil {
		return 0, 0, err
	}
	return year, time.Month(month), nil
}

func redirectToNow(w http.ResponseWriter, r *http.Request) {
	now := time.Now()
	nowPath := fmt.Sprintf("/%d/%d", now.Year(), now.Month())
	http.Redirect(w, r, nowPath, http.StatusSeeOther)
}

func webHandler(w http.ResponseWriter, r *http.Request) {
	year, month, err := pathToYearMonth(r.URL.Path)
	if err != nil {
		redirectToNow(w, r)
		return
	}
	days, err := workday.DaysForMonth(year, month)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for _, d := range days {
		fmt.Fprintln(w, d.String())
	}
}

func web() error {
	http.HandleFunc("/", webHandler)
	log.Println("Starting server on port 8080")
	return http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"html"
	"html/template"
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func taskList(w http.ResponseWriter, r *http.Request) {
	drawTemplate(w, "taskList", tmplData{
		"Title": "Tasks",
		"Tasks": GetTasks(),
		"Log":   logBuf.String(),
	})
}

func killTask(w http.ResponseWriter, r *http.Request, t *Task) {
	st := t.Status()
	in := st.Running
	if in == nil {
		http.Error(w, "task not running", 500)
		return
	}
	pid, _ := strconv.Atoi(r.FormValue("pid"))
	if in.Pid() != pid || pid == 0 {
		http.Error(w, "active task pid doesn't match pid parameter", 500)
		return
	}
	in.cmd.Process.Kill()
	drawTemplate(w, "killTask", tmplData{
		"Title": "Kill",
		"Task":  t,
		"PID":   pid,
	})
}

func taskView(w http.ResponseWriter, r *http.Request) {
	taskName := r.URL.Path[len("/task/"):]
	t, ok := GetTask(taskName)
	if !ok {
		http.NotFound(w, r)
		return
	}
	mode := r.FormValue("mode")
	switch mode {
	case "kill":
		killTask(w, r, t)
		return
	default:
		http.Error(w, "unknown mode", 400)
		return
	case "":
	}

	data := tmplData{
		"Title": t.Name + " status",
		"Task":  t,
	}

	st := t.Status()
	in := st.Running
	if in != nil {
		data["PID"] = in.Pid()
		data["Output"] = in.Output()
		data["Cmd"] = in.cmd
		data["StartTime"] = in.startTime
		data["StartAgo"] = time.Now().Sub(in.startTime)
	}

	// list failures in reverse-chronological order
	{
		f := st.Failures
		r := make([]*TaskInstance, len(f))
		for i := range f {
			r[len(r)-i-1] = f[i]
		}
		data["Failures"] = r
	}

	drawTemplate(w, "viewTask", data)
}

func runWebServer(ln net.Listener) {
	mux := http.NewServeMux()
	// TODO: wrap mux in auth handler, making it available only to
	// TCP connections from localhost and owned by the uid/gid of
	// the running process.
	mux.HandleFunc("/", taskList)
	mux.HandleFunc("/task/", taskView)
	s := &http.Server{
		Handler: mux,
	}
	err := s.Serve(ln)
	if err != nil {
		logger.Fatalf("webserver exiting: %v", err)
	}
}

type tmplData map[string]interface{}

func drawTemplate(w io.Writer, name string, data tmplData) {
	err := templates[name].ExecuteTemplate(w, "root", data)
	if err != nil {
		logger.Println(err)
	}
}

var templates = make(map[string]*template.Template)

func init() {
	for name, html := range templateHTML {
		t := template.New(name).Funcs(templateFuncs)
		template.Must(t.Parse(html))
		template.Must(t.Parse(rootHTML))
		templates[name] = t
	}
}

const rootHTML = `
{{define "root"}}

		<title>{{.Title}} - runsit</title>

{{.Title}}

		{{template "body" .}}

{{end}}
`

var templateHTML = map[string]string{
	"taskList": `
	{{define "body"}}

Running

		{{range .Tasks}}

{{.Name}}: {{maybePre .Status.Summary}}

		{{end}}

Log

{{.Log}}

	{{end}}
`,
	"killTask": `
	{{define "body"}}

Killed pid {{.PID}}.

Back to {{.Task.Name}} status.

	{{end}}
`,
	"viewTask": `
	{{define "body"}}

[Tasks]

{{maybePre .Task.Status.Summary}}

		{{with .Cmd}}
		{{/* TODO: embolden arg[0] */}}

command: {{range .Args}}{{maybeQuote .}} {{end}}

		{{end}}

		{{if .PID}}

Running Instance

Started {{.StartTime}}, {{.StartAgo}} ago.

PID={{.PID}} [kill]

		{{end}}

		{{with .Output}}{{template "output" .}}{{end}}

		{{with .Failures}}

Failures

		{{range .}}{{template "output" .Output}}{{end}}
		{{end}}

	{{end}}
	{{define "output"}}

		{{range .}}

{{.Data}}

		{{end}}

	{{end}}
`,
}

var templateFuncs = template.FuncMap{
	"maybeQuote": maybeQuote,
	"maybePre": maybePre,
}

func maybeQuote(s string) string {
	if strings.Contains(s, " ") || strings.Contains(s, `"`) {
		return fmt.Sprintf("%q", s)
	}
	return s
}

func maybePre(s string) interface{} {
	if strings.Contains(s, "\n") {
		return template.HTML("
" + html.EscapeString(s) + "
")
	}
	return s
}
<commit_msg>fix args display; now in LaunchRequest<commit_after>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"html"
	"html/template"
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func taskList(w http.ResponseWriter, r *http.Request) {
	drawTemplate(w, "taskList", tmplData{
		"Title": "Tasks",
		"Tasks": GetTasks(),
		"Log":   logBuf.String(),
	})
}

func killTask(w http.ResponseWriter, r *http.Request, t *Task) {
	st := t.Status()
	in := st.Running
	if in == nil {
		http.Error(w, "task not running", 500)
		return
	}
	pid, _ := strconv.Atoi(r.FormValue("pid"))
	if in.Pid() != pid || pid == 0 {
		http.Error(w, "active task pid doesn't match pid parameter", 500)
		return
	}
	in.cmd.Process.Kill()
	drawTemplate(w, "killTask", tmplData{
		"Title": "Kill",
		"Task":  t,
		"PID":   pid,
	})
}

func taskView(w http.ResponseWriter, r *http.Request) {
	taskName := r.URL.Path[len("/task/"):]
	t, ok := GetTask(taskName)
	if !ok {
		http.NotFound(w, r)
		return
	}
	mode := r.FormValue("mode")
	switch mode {
	case "kill":
		killTask(w, r, t)
		return
	default:
		http.Error(w, "unknown mode", 400)
		return
	case "":
	}

	data := tmplData{
		"Title": t.Name + " status",
		"Task":  t,
	}

	st := t.Status()
	in := st.Running
	if in != nil {
		data["PID"] = in.Pid()
		data["Output"] = in.Output()
		data["Cmd"] = in.lr
		data["StartTime"] = in.startTime
		data["StartAgo"] = time.Now().Sub(in.startTime)
	}

	// list failures in reverse-chronological order
	{
		f := st.Failures
		r := make([]*TaskInstance, len(f))
		for i := range f {
			r[len(r)-i-1] = f[i]
		}
		data["Failures"] = r
	}

	drawTemplate(w, "viewTask", data)
}

func runWebServer(ln net.Listener) {
	mux := http.NewServeMux()
	// TODO: wrap mux in auth handler, making it available only to
	// TCP connections from localhost and owned by the uid/gid of
	// the running process.
	mux.HandleFunc("/", taskList)
	mux.HandleFunc("/task/", taskView)
	s := &http.Server{
		Handler: mux,
	}
	err := s.Serve(ln)
	if err != nil {
		logger.Fatalf("webserver exiting: %v", err)
	}
}

type tmplData map[string]interface{}

func drawTemplate(w io.Writer, name string, data tmplData) {
	err := templates[name].ExecuteTemplate(w, "root", data)
	if err != nil {
		logger.Println(err)
	}
}

var templates = make(map[string]*template.Template)

func init() {
	for name, html := range templateHTML {
		t := template.New(name).Funcs(templateFuncs)
		template.Must(t.Parse(html))
		template.Must(t.Parse(rootHTML))
		templates[name] = t
	}
}

const rootHTML = `
{{define "root"}}

		<title>{{.Title}} - runsit</title>

{{.Title}}

		{{template "body" .}}

{{end}}
`

var templateHTML = map[string]string{
	"taskList": `
	{{define "body"}}

Running

		{{range .Tasks}}

{{.Name}}: {{maybePre .Status.Summary}}

		{{end}}

Log

{{.Log}}

	{{end}}
`,
	"killTask": `
	{{define "body"}}

Killed pid {{.PID}}.

Back to {{.Task.Name}} status.

	{{end}}
`,
	"viewTask": `
	{{define "body"}}

[Tasks]

{{maybePre .Task.Status.Summary}}

		{{with .Cmd}}
		{{/* TODO: embolden arg[0] */}}

command: {{range .Argv}}{{maybeQuote .}} {{end}}

		{{end}}

		{{if .PID}}

Running Instance

Started {{.StartTime}}, {{.StartAgo}} ago.

PID={{.PID}} [kill]

		{{end}}

		{{with .Output}}{{template "output" .}}{{end}}

		{{with .Failures}}

Failures

		{{range .}}{{template "output" .Output}}{{end}}
		{{end}}

	{{end}}
	{{define "output"}}

		{{range .}}

{{.Data}}

		{{end}}

	{{end}}
`,
}

var templateFuncs = template.FuncMap{
	"maybeQuote": maybeQuote,
	"maybePre": maybePre,
}

func maybeQuote(s string) string {
	if strings.Contains(s, " ") || strings.Contains(s, `"`) {
		return fmt.Sprintf("%q", s)
	}
	return s
}

func maybePre(s string) interface{} {
	if strings.Contains(s, "\n") {
		return template.HTML("
" + html.EscapeString(s) + "
")
	}
	return s
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
)

var dataUrlPattern *regexp.Regexp

func handleGet(res http.ResponseWriter, req *http.Request) {
	dataUrl := req.URL.Query().Get("url")
	match := dataUrlPattern.FindStringSubmatch(dataUrl)
	if len(match) == 0 {
		log.Println("match.error.input:", dataUrl)
		http.Error(res, "Parameter 'url' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}

	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]
	log.Println("request.type:", contentType, "request.base64:", isBase64)

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("base64.decode.error:", err, "dataUrl:", dataUrl)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprintln(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.read.error:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	dataUrl := "data:" + contentType + ";base64," + base64
	url := scheme + "://" + req.Host + req.URL.Path + "?url=" + url.QueryEscape(dataUrl)

	fmt.Fprint(res, url)
}

func main() {
	dataUrlPattern, _ = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")

	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

	log.Println("listening:true port:", os.Getenv("PORT"))
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>standardize logging<commit_after>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
)

var dataUrlPattern *regexp.Regexp

func handleGet(res http.ResponseWriter, req *http.Request) {
	dataUrl := req.URL.Query().Get("url")
	match := dataUrlPattern.FindStringSubmatch(dataUrl)
	if len(match) == 0 {
		log.Println("get.error.url:", dataUrl)
		http.Error(res, "Parameter 'url' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}

	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprintln(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.error.body:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	dataUrl := "data:" + contentType + ";base64," + base64
	url := scheme + "://" + req.Host + req.URL.Path + "?url=" + url.QueryEscape(dataUrl)

	fmt.Fprint(res, url)
}

func main() {
	dataUrlPattern, _ = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")

	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

	log.Println("listening:true port:", os.Getenv("PORT"))
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>// Alexandria
//
// Copyright (C) 2015-2016  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package alexandria

import (
	"fmt"
	"io/ioutil"
	"os"
)

func LogError(err interface{}) {
	fmt.Fprintln(os.Stderr, err)
}

// If an error occurred, log it.
func TryLogError(err interface{}) {
	if err != nil {
		LogError(err)
	}
}

// Load the content of a given scroll from disk.
func readScroll(id ID) (string, error) {
	result, err := ioutil.ReadFile(Config.KnowledgeDirectory + string(id) + ".tex")
	return string(result), err
}

// Load the content of a template file with the given name.
func readTemplate(filename string) (string, error) {
	result, err := ioutil.ReadFile(Config.TemplateDirectory + "tex/" + filename + ".tex")
	return string(result), err
}

// Write a TeX file with the given name and content to Alexandria's temp
// directory.
func writeTemp(id ID, data string) error {
	return ioutil.WriteFile(Config.TempDirectory+string(id)+".tex", []byte(data), 0644)
}

// Compute the combined size of all files in a given directory.
func getDirSize(dir string) (int, int64) {
	directory, err := os.Open(dir)
	TryLogError(err)
	defer directory.Close()
	fileInfo, err := directory.Readdir(0)
	if err != nil {
		panic(err)
	}
	result := int64(0)
	for _, file := range fileInfo {
		result += file.Size()
	}
	return len(fileInfo), result
}

// Get the time a given file was last modified as a Unix time.
func getModTime(file string) (int64, error) {
	info, err := os.Stat(file)
	if err != nil {
		return -1, err
	}
	return info.ModTime().Unix(), nil
}

// Cache the newest modification of any of the template files as a Unix time
// (i.e. seconds since 1970-01-01).
var templatesModTime int64 = -1

// All recognized template files
// TODO Generate the list⁈
var templateFiles []string = []string{
	"header.tex", "footer.tex",
	"algorithm_header.tex", "algorithm_footer.tex",
	"axiom_header.tex", "axiom_footer.tex",
	"corollary_header.tex", "corollary_footer.tex",
	"definition_header.tex", "definition_footer.tex",
	"example_header.tex", "example_footer.tex",
	"exercise_header.tex", "exercise_footer.tex",
	"lemma_header.tex", "lemma_footer.tex",
	"proof_header.tex", "proof_footer.tex",
	"proposition_header.tex", "proposition_footer.tex",
	"remark_header.tex", "remark_footer.tex",
	"theorem_header.tex", "theorem_footer.tex"}

// Check whether a given scroll has to be recompiled
func isUpToDate(id ID) bool {
	if templatesModTime == -1 {
		// Check template for modification times
		templatesModTime = 0

		for _, file := range templateFiles {
			foo, err := getModTime(Config.TemplateDirectory + file)
			if err != nil {
				break
			}
			if foo > templatesModTime {
				templatesModTime = foo
			}
		}
	}

	info, err := os.Stat(Config.CacheDirectory + string(id) + ".png")
	if err != nil {
		return false
	}
	imageTime := info.ModTime().Unix()

	if imageTime < templatesModTime {
		return false
	}

	info, err = os.Stat(Config.KnowledgeDirectory + string(id) + ".tex")
	if err != nil {
		return false // When in doubt, recompile
	}
	scrollTime := info.ModTime().Unix()

	return imageTime > scrollTime
}
<commit_msg>Address linter warnings in Util.go<commit_after>// Alexandria
//
// Copyright (C) 2015-2016  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package alexandria

import (
	"fmt"
	"io/ioutil"
	"os"
)

// LogError writes things to stderr.
func LogError(err interface{}) {
	fmt.Fprintln(os.Stderr, err)
}

// TryLogError checks whether an error occurred, and logs it if necessary.
func TryLogError(err interface{}) {
	if err != nil {
		LogError(err)
	}
}

// Load the content of a given scroll from disk.
func readScroll(id ID) (string, error) {
	result, err := ioutil.ReadFile(Config.KnowledgeDirectory + string(id) + ".tex")
	return string(result), err
}

// Load the content of a template file with the given name.
func readTemplate(filename string) (string, error) {
	result, err := ioutil.ReadFile(Config.TemplateDirectory + "tex/" + filename + ".tex")
	return string(result), err
}

// Write a TeX file with the given name and content to Alexandria's temp
// directory.
func writeTemp(id ID, data string) error {
	return ioutil.WriteFile(Config.TempDirectory+string(id)+".tex", []byte(data), 0644)
}

// Compute the combined size of all files in a given directory.
func getDirSize(dir string) (int, int64) {
	directory, err := os.Open(dir)
	TryLogError(err)
	defer directory.Close()
	fileInfo, err := directory.Readdir(0)
	if err != nil {
		panic(err)
	}
	result := int64(0)
	for _, file := range fileInfo {
		result += file.Size()
	}
	return len(fileInfo), result
}

// Get the time a given file was last modified as a Unix time.
func getModTime(file string) (int64, error) {
	info, err := os.Stat(file)
	if err != nil {
		return -1, err
	}
	return info.ModTime().Unix(), nil
}

// Cache the newest modification of any of the template files as a Unix time
// (i.e. seconds since 1970-01-01).
var templatesModTime int64 = -1

// All recognized template files
// TODO Generate the list⁈
var templateFiles = []string{
	"header.tex", "footer.tex",
	"algorithm_header.tex", "algorithm_footer.tex",
	"axiom_header.tex", "axiom_footer.tex",
	"corollary_header.tex", "corollary_footer.tex",
	"definition_header.tex", "definition_footer.tex",
	"example_header.tex", "example_footer.tex",
	"exercise_header.tex", "exercise_footer.tex",
	"lemma_header.tex", "lemma_footer.tex",
	"proof_header.tex", "proof_footer.tex",
	"proposition_header.tex", "proposition_footer.tex",
	"remark_header.tex", "remark_footer.tex",
	"theorem_header.tex", "theorem_footer.tex"}

// Check whether a given scroll has to be recompiled
func isUpToDate(id ID) bool {
	if templatesModTime == -1 {
		// Check template for modification times
		templatesModTime = 0

		for _, file := range templateFiles {
			foo, err := getModTime(Config.TemplateDirectory + file)
			if err != nil {
				break
			}
			if foo > templatesModTime {
				templatesModTime = foo
			}
		}
	}

	info, err := os.Stat(Config.CacheDirectory + string(id) + ".png")
	if err != nil {
		return false
	}
	imageTime := info.ModTime().Unix()

	if imageTime < templatesModTime {
		return false
	}

	info, err = os.Stat(Config.KnowledgeDirectory + string(id) + ".tex")
	if err != nil {
		return false // When in doubt, recompile
	}
	scrollTime := info.ModTime().Unix()

	return imageTime > scrollTime
}
<|endoftext|>


<commit_before>// +build ansi

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"time"

	termbox "github.com/nsf/termbox-go"
)

type termui struct {
	bStdin  *bufio.Reader
	bStdout *bufio.Writer
}

func WindowsPalette() {
	ColorBgLOS = uicolor(termbox.ColorWhite)
	ColorBgDark = uicolor(termbox.ColorBlack)
	ColorBg = uicolor(termbox.ColorBlack)
	ColorBgCloud = uicolor(termbox.ColorWhite)
	ColorFgLOS = uicolor(termbox.ColorBlack)
	ColorFgDark = uicolor(termbox.ColorWhite)
	ColorFg = uicolor(termbox.ColorWhite)
	ColorFgPlayer = uicolor(termbox.ColorBlue)
	ColorFgMonster = uicolor(termbox.ColorRed)
	ColorFgSleepingMonster = uicolor(termbox.ColorCyan)
	ColorFgWanderingMonster = uicolor(termbox.ColorMagenta)
	ColorFgConfusedMonster = uicolor(termbox.ColorGreen)
	ColorFgCollectable = uicolor(termbox.ColorYellow)
	ColorFgStairs = uicolor(termbox.ColorMagenta)
	ColorFgGold = uicolor(termbox.ColorYellow)
	ColorFgHPok = uicolor(termbox.ColorGreen)
	ColorFgHPwounded = uicolor(termbox.ColorYellow)
	ColorFgHPcritical = uicolor(termbox.ColorRed)
	ColorFgMPok = uicolor(termbox.ColorBlue)
	ColorFgMPpartial = uicolor(termbox.ColorMagenta)
	ColorFgMPcritical = uicolor(termbox.ColorRed)
	ColorFgStatusGood = uicolor(termbox.ColorBlue)
	ColorFgStatusBad = uicolor(termbox.ColorRed)
	ColorFgStatusOther = uicolor(termbox.ColorYellow)
	ColorFgTargetMode = uicolor(termbox.ColorCyan)
	ColorFgTemporalWall = uicolor(termbox.ColorCyan)
}

func (ui *termui) Init() error {
	ui.bStdin = bufio.NewReader(os.Stdin)
	ui.bStdout = bufio.NewWriter(os.Stdout)
	// TODO: stty
	return nil
}

func (ui *termui) Close() {
	// TODO: stty
}

func (ui *termui) PostInit() {
	//SolarizedPalette()
	FixColor()
}

func (ui *termui) MoveTo(x, y int) {
	fmt.Fprintf(ui.bStdout, "\x1b[%d;%dH", y, x)
}

func (ui *termui) Clear() {
	// TODO: avoid complete clear
	fmt.Fprintf(ui.bStdout, "\x1b[2J")
	ui.MoveTo(1, 1)
}

func (ui *termui) Flush() {
	ui.bStdout.Flush()
}

func (ui *termui) HideCursor() {
	fmt.Fprintf(ui.bStdout, "\x1b[?25l")
}

func (ui *termui) SetCursor(pos position) {
	fmt.Fprintf(ui.bStdout, "\x1b[?25h")
	ui.MoveTo(pos.X, pos.Y)
}

func (ui *termui) SetCell(x, y int, r rune, fg, bg uicolor) {
	//var fgAttr string
	//if fg <= 7 {
	//fgAttr = fmt.Sprintf("%d", fg)
	//} else {
	//fgAttr = fmt.Sprintf("1;%d", fg)
	//}
	//var bgAttr string
	//if bg <= 7 {
	//bgAttr = fmt.Sprintf("%d", 40+bg)
	//} else {
	//bgAttr = fmt.Sprintf("%d", 100+bg)
	//}

	ui.MoveTo(x, y)
	//fmt.Fprintf(ui.bStdout, "\x1b[%s;%sm", fgAttr, bgAttr)
	fmt.Fprintf(ui.bStdout, "\x1b[38;5;%dm", fg)
	fmt.Fprintf(ui.bStdout, "\x1b[48;5;%dm", bg)
	ui.bStdout.WriteRune(r)
	fmt.Fprintf(ui.bStdout, "\x1b[0m")
}

func (ui *termui) ReadChar() rune {
	cmd := exec.Command("stty", "raw", "-echo")
	cmd.Stdin = os.Stdin
	cmd.Run()
	r, _, _ := ui.bStdin.ReadRune()
	cmd = exec.Command("stty", "sane")
	cmd.Stdin = os.Stdin
	cmd.Run()
	return r
}

func (ui *termui) ExploreStep(g *game) bool {
	time.Sleep(10 * time.Millisecond)
	ui.DrawDungeonView(g, false)
	return false
}

func (ui *termui) WaitForContinue(g *game) {
loop:
	for {
		r := ui.ReadChar()
		switch r {
		case '\xb1', ' ':
			break loop
		}
	}
}

func (ui *termui) PromptConfirmation(g *game) bool {
	for {
		r := ui.ReadChar()
		switch r {
		case 'Y', 'y':
			return true
		default:
			return false
		}
	}
}

func (ui *termui) PressAnyKey() error {
	for {
		ui.ReadChar()
		return nil
	}
}

func (ui *termui) PlayerTurnEvent(g *game, ev event) (err error, again, quit bool) {
	again = true
	r := ui.ReadChar()
	err, again, quit = ui.HandleCharacter(g, ev, r)
	if err != nil {
		again = true
	}
	return err, again, quit
}

func (ui *termui) Scroll(n int) (m int, quit bool) {
	r := ui.ReadChar()
	switch r {
	case '\xb1', ' ':
		quit = true
	case 'u':
		n -= 12
	case 'd':
		n += 12
	case 'j':
		n++
	case 'k':
		n--
	}
	return n, quit
}

func (ui *termui) TargetModeEvent(g *game, targ Targetter, pos position, data *examineData) bool {
	r := ui.ReadChar()
	if r == '\xb1' {
		return true
	}
	return ui.CursorCharAction(g, targ, r, pos, data)
}

func (ui *termui) Select(g *game, ev event, l int) (index int, alternate bool, err error) {
	for {
		r := ui.ReadChar()
		switch {
		case r == '\xb1' || r == ' ':
			return -1, false, errors.New("Ok, then.")
		case 97 <= r && int(r) < 97+l:
			return int(r - 97), false, nil
		case r == '?':
			return -1, true, nil
		case r == ' ':
			return -1, false, errors.New("Ok, then.")
		}
	}
}
<commit_msg>finished simple ansi version with no dependencies<commit_after>// +build ansi

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"time"

	termbox "github.com/nsf/termbox-go"
)

type AnsiCell struct {
	fg uicolor
	bg uicolor
	r  rune
}

type termui struct {
	bStdin     *bufio.Reader
	bStdout    *bufio.Writer
	cells      []AnsiCell
	backBuffer []AnsiCell
	cursor     position
}

func WindowsPalette() {
	ColorBgLOS = uicolor(termbox.ColorWhite)
	ColorBgDark = uicolor(termbox.ColorBlack)
	ColorBg = uicolor(termbox.ColorBlack)
	ColorBgCloud = uicolor(termbox.ColorWhite)
	ColorFgLOS = uicolor(termbox.ColorBlack)
	ColorFgDark = uicolor(termbox.ColorWhite)
	ColorFg = uicolor(termbox.ColorWhite)
	ColorFgPlayer = uicolor(termbox.ColorBlue)
	ColorFgMonster = uicolor(termbox.ColorRed)
	ColorFgSleepingMonster = uicolor(termbox.ColorCyan)
	ColorFgWanderingMonster = uicolor(termbox.ColorMagenta)
	ColorFgConfusedMonster = uicolor(termbox.ColorGreen)
	ColorFgCollectable = uicolor(termbox.ColorYellow)
	ColorFgStairs = uicolor(termbox.ColorMagenta)
	ColorFgGold = uicolor(termbox.ColorYellow)
	ColorFgHPok = uicolor(termbox.ColorGreen)
	ColorFgHPwounded = uicolor(termbox.ColorYellow)
	ColorFgHPcritical = uicolor(termbox.ColorRed)
	ColorFgMPok = uicolor(termbox.ColorBlue)
	ColorFgMPpartial = uicolor(termbox.ColorMagenta)
	ColorFgMPcritical = uicolor(termbox.ColorRed)
	ColorFgStatusGood = uicolor(termbox.ColorBlue)
	ColorFgStatusBad = uicolor(termbox.ColorRed)
	ColorFgStatusOther = uicolor(termbox.ColorYellow)
	ColorFgTargetMode = uicolor(termbox.ColorCyan)
	ColorFgTemporalWall = uicolor(termbox.ColorCyan)
}

const (
	UIWidth  = 103
	UIHeigth = 27
)

func (ui *termui) GetIndex(x, y int) int {
	return y*UIWidth + x
}

func (ui *termui) GetPos(i int) (int, int) {
	return i - (i/UIWidth)*UIWidth, i / UIWidth
}

func (ui *termui) ResetCells() {
	for i := 0; i < len(ui.cells); i++ {
		ui.cells[i].r = ' '
		ui.cells[i].bg = ColorBg
	}
}

func (ui *termui) Init() error {
	ui.bStdin = bufio.NewReader(os.Stdin)
	ui.bStdout = bufio.NewWriter(os.Stdout)
	ui.cells = make([]AnsiCell, UIWidth*UIHeigth)
	ui.ResetCells()
	ui.backBuffer = make([]AnsiCell, UIWidth*UIHeigth)
	fmt.Fprint(ui.bStdout, "\x1b[2J")
	// TODO: stty
	return nil
}

func (ui *termui) Close() {
	fmt.Fprint(ui.bStdout, "\x1b[2J")
	fmt.Fprintf(ui.bStdout, "\x1b[?25h")
	ui.bStdout.Flush()
}

func (ui *termui) PostInit() {
	//SolarizedPalette()
	FixColor()
	ui.HideCursor()
}

func (ui *termui) MoveTo(x, y int) {
	fmt.Fprintf(ui.bStdout, "\x1b[%d;%dH", y+1, x+1)
}

func (ui *termui) Clear() {
}

func (ui *termui) Flush() {
	for i := 0; i < len(ui.cells); i++ {
		if ui.cells[i] == ui.backBuffer[i] {
			continue
		}
		cell := ui.cells[i]
		x, y := ui.GetPos(i)
		ui.MoveTo(x, y)
		//fmt.Fprintf(ui.bStdout, "\x1b[%s;%sm", fgAttr, bgAttr)
		fmt.Fprintf(ui.bStdout, "\x1b[38;5;%dm", cell.fg)
		fmt.Fprintf(ui.bStdout, "\x1b[48;5;%dm", cell.bg)
		ui.bStdout.WriteRune(cell.r)
		fmt.Fprintf(ui.bStdout, "\x1b[0m")
		ui.backBuffer[i] = cell
	}
	ui.ResetCells()
	ui.MoveTo(ui.cursor.X, ui.cursor.Y)
	if ui.cursor.X >= 0 && ui.cursor.Y >= 0 {
		fmt.Fprintf(ui.bStdout, "\x1b[?25h")
	} else {
		fmt.Fprintf(ui.bStdout, "\x1b[?25l")
	}
	ui.bStdout.Flush()
}

func (ui *termui) HideCursor() {
	ui.cursor = position{-1, -1}
}

func (ui *termui) SetCursor(pos position) {
	//fmt.Fprintf(ui.bStdout, "\x1b[?25h")
	ui.cursor = pos
}

func (ui *termui) SetCell(x, y int, r rune, fg, bg uicolor) {
	//var fgAttr string
	//if fg <= 7 {
	//fgAttr = fmt.Sprintf("%d", fg)
	//} else {
	//fgAttr = fmt.Sprintf("1;%d", fg)
	//}
	//var bgAttr string
	//if bg <= 7 {
	//bgAttr = fmt.Sprintf("%d", 40+bg)
	//} else {
	//bgAttr = fmt.Sprintf("%d", 100+bg)
	//}
	i := ui.GetIndex(x, y)
	if i >= len(ui.cells) {
		return
	}
	ui.cells[ui.GetIndex(x, y)] = AnsiCell{fg: fg, bg: bg, r: r}

}

func (ui *termui) ReadChar() rune {
	cmd := exec.Command("stty", "-g")
	cmd.Stdin = os.Stdin
	save, err := cmd.Output()
	if err != nil {
		save = []byte("sane")
	}
	cmd = exec.Command("stty", "raw", "-echo")
	cmd.Stdin = os.Stdin
	cmd.Run()
	r, _, _ := ui.bStdin.ReadRune()
	cmd = exec.Command("stty", string(save))
	cmd.Stdin = os.Stdin
	cmd.Run()
	return r
}

func (ui *termui) ExploreStep(g *game) bool {
	time.Sleep(10 * time.Millisecond)
	ui.DrawDungeonView(g, false)
	return false
}

func (ui *termui) WaitForContinue(g *game) {
loop:
	for {
		r := ui.ReadChar()
		switch r {
		case '\x1b', ' ':
			break loop
		}
	}
}

func (ui *termui) PromptConfirmation(g *game) bool {
	for {
		r := ui.ReadChar()
		switch r {
		case 'Y', 'y':
			return true
		default:
			return false
		}
	}
}

func (ui *termui) PressAnyKey() error {
	for {
		ui.ReadChar()
		return nil
	}
}

func (ui *termui) PlayerTurnEvent(g *game, ev event) (err error, again, quit bool) {
	again = true
	r := ui.ReadChar()
	err, again, quit = ui.HandleCharacter(g, ev, r)
	if err != nil {
		again = true
	}
	return err, again, quit
}

func (ui *termui) Scroll(n int) (m int, quit bool) {
	r := ui.ReadChar()
	switch r {
	case '\x1b', ' ':
		quit = true
	case 'u':
		n -= 12
	case 'd':
		n += 12
	case 'j':
		n++
	case 'k':
		n--
	}
	return n, quit
}

func (ui *termui) TargetModeEvent(g *game, targ Targetter, pos position, data *examineData) bool {
	r := ui.ReadChar()
	if r == '\x1b' || r == ' ' {
		return true
	}
	return ui.CursorCharAction(g, targ, r, pos, data)
}

func (ui *termui) Select(g *game, ev event, l int) (index int, alternate bool, err error) {
	for {
		r := ui.ReadChar()
		switch {
		case r == '\x1b' || r == ' ':
			return -1, false, errors.New("Ok, then.")
		case 97 <= r && int(r) < 97+l:
			return int(r - 97), false, nil
		case r == '?':
			return -1, true, nil
		case r == ' ':
			return -1, false, errors.New("Ok, then.")
		}
	}
}
<|endoftext|>


<commit_before>// Package zlmgo provides Go bindings to the Zen License Manager (ZLM).
package zlmgo

/*
#cgo CFLAGS: -I/usr/local/include
#cgo LDFLAGS: /usr/local/lib/libzlm.a

#include <zlm.h>

char zlmgo_errbuf_array[ZLM_ERRBUF];
char* zlmgo_errbuf = zlmgo_errbuf_array; // hack around cgo warning
*/
import "C"

import (
	"errors"
	"runtime"
)

type License struct {
	l *C.ZlmLicense
}

// LicenseNew returns a new license object (panics if not enough memory is available).
func LicenseNew() *License {
	license := &License{C.zlm_license_new(C.zlmgo_errbuf)}
	if license.l == nil {
		panic(C.GoString(C.zlmgo_errbuf))
	}
	runtime.SetFinalizer(license, (*License).free)
	return license
}

func (license *License) Get(product, version, argv0, path, licenseString string) error {
	var c_product, c_version, c_argv0, c_path, c_license_string *C.char
	// convert argument to C strings
	if product != "" {
		c_product = C.CString(product)
	}
	if version != "" {
		c_version = C.CString(version)
	}
	if argv0 != "" {
		c_argv0 = C.CString(argv0)
	}
	if path != "" {
		c_path = C.CString(path)
	}
	if licenseString != "" {
		c_license_string = C.CString(licenseString)
	}
	// call actual method
	if C.zlm_license_get(license.l, c_product, c_version, c_argv0, c_path, c_license_string, C.zlmgo_errbuf) != C.ZLM_OK {
		return errors.New(C.GoString(C.zlmgo_errbuf))
	}
	return nil
}

func (license *License) free() {
	C.zlm_license_free(license.l)
}
<commit_msg>bind more functions from the ZLM API<commit_after>// Package zlmgo provides Go bindings to the Zen License Manager (ZLM).
package zlmgo

/*
#cgo CFLAGS: -I/usr/local/include
#cgo LDFLAGS: /usr/local/lib/libzlm.a

#include <zlm.h>

char zlmgo_errbuf_array[ZLM_ERRBUF];
char* zlmgo_errbuf = zlmgo_errbuf_array; // hack around cgo warning
*/
import "C"

import (
	"errors"
	"runtime"
)

type License struct {
	l *C.ZlmLicense
}

// LicenseNew returns a new license object (panics if not enough memory is available).
func LicenseNew() *License {
	license := &License{C.zlm_license_new(C.zlmgo_errbuf)}
	if license.l == nil {
		panic(C.GoString(C.zlmgo_errbuf))
	}
	runtime.SetFinalizer(license, (*License).free)
	return license
}

func (license *License) Get(product, version, argv0, path, licenseString string) error {
	var c_product, c_version, c_argv0, c_path, c_license_string *C.char
	// convert argument to C strings
	if product != "" {
		c_product = C.CString(product)
	}
	if version != "" {
		c_version = C.CString(version)
	}
	if argv0 != "" {
		c_argv0 = C.CString(argv0)
	}
	if path != "" {
		c_path = C.CString(path)
	}
	if licenseString != "" {
		c_license_string = C.CString(licenseString)
	}
	// call actual method
	if C.zlm_license_get(license.l, c_product, c_version, c_argv0, c_path, c_license_string, C.zlmgo_errbuf) != C.ZLM_OK {
		return errors.New(C.GoString(C.zlmgo_errbuf))
	}
	return nil
}

func (license *License) free() {
	C.zlm_license_free(license.l)
}

func (license *License) Product() string {
	return C.GoString(C.zlm_license_product(license.l))
}

func (license *License) Expiry() string {
	return C.GoString(C.zlm_license_expiry(license.l))
}

func (license *License) ExpiryDays() int {
	return int(C.zlm_license_expiry_days(license.l))
}

func (license *License) Customer() string {
	return C.GoString(C.zlm_license_customer(license.l))
}

func (license *License) Userdata() string {
	return C.GoString(C.zlm_license_userdata(license.l))
}

func (license *License) Next() error {
	if C.zlm_license_next(license.l, C.zlmgo_errbuf) != C.ZLM_OK {
		return errors.New(C.GoString(C.zlmgo_errbuf))
	}
	return nil
}

func Version() string {
	return C.GoString(C.zlm_version())
}

func (license *License) CheckA() {
	C.zlm_license_check_a(license.l)
}

func (license *License) CheckB() {
	C.zlm_license_check_b(license.l)
}

func (license *License) CheckC() {
	C.zlm_license_check_c(license.l)
}

func (license *License) CheckD() {
	C.zlm_license_check_d(license.l)
}

func (license *License) CheckE() {
	C.zlm_license_check_e(license.l)
}

func (license *License) CheckF() {
	C.zlm_license_check_f(license.l)
}

func (license *License) CheckG() {
	C.zlm_license_check_g(license.l)
}

func (license *License) CheckH() {
	C.zlm_license_check_h(license.l)
}

func (license *License) CheckI() {
	C.zlm_license_check_i(license.l)
}

func (license *License) CheckJ() {
	C.zlm_license_check_j(license.l)
}

func (license *License) CheckK() {
	C.zlm_license_check_k(license.l)
}

func (license *License) CheckL() {
	C.zlm_license_check_l(license.l)
}

func (license *License) CheckM() {
	C.zlm_license_check_m(license.l)
}

func (license *License) CheckN() {
	C.zlm_license_check_n(license.l)
}

func (license *License) CheckO() {
	C.zlm_license_check_o(license.l)
}

func (license *License) CheckP() {
	C.zlm_license_check_p(license.l)
}

func (license *License) CheckQ() {
	C.zlm_license_check_q(license.l)
}

func (license *License) CheckR() {
	C.zlm_license_check_r(license.l)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"sort"
	"time"

	"github.com/bradfitz/http2"
	"github.com/myfreeweb/443d/demux"
	"github.com/myfreeweb/443d/util"
	"github.com/ryanuber/go-glob"
	"gopkg.in/yaml.v2"
)

type Config struct {
	Tls struct {
		Listen string
		Cert   string
		Key    string
		Ssh    string
		Hsts   struct {
			Seconds    int
			Subdomains bool
		}
		Hpkp struct {
			Seconds    int
			Subdomains bool
			BackupKeys []string `yaml:"backup_keys"`
		}
	}
	Http struct {
		Listen string
	}
	Hosts       []HttpBackend
	DefaultHost string
}

var confpath = flag.String("config", "/usr/local/etc/443d.yaml", "path to the configuration file")
var config Config
var tlsKeyPair tls.Certificate
var hstsHeader string
var hpkpHeader string

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	readConfig()
	processConfig()
	handler := httpHandler()
	go func() {
		addr := config.Http.Listen
		if addr == "" {
			log.Printf("No listen address for the HTTP server \n")
			return
		}
		srv := &http.Server{Addr: addr, Handler: handler}
		tcpl, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		serve("HTTP server", srv, tcpl)
	}()
	go func() {
		addr := config.Tls.Listen
		if addr == "" {
			log.Printf("No listen address for the TLS server \n")
			return
		}
		if config.Tls.Cert == "" && config.Tls.Key == "" {
			log.Printf("No keypair for the TLS server \n")
			return
		}
		secHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if config.Tls.Hsts.Seconds != 0 {
				w.Header().Add("Strict-Transport-Security", hstsHeader)
			}
			if config.Tls.Hpkp.Seconds != 0 {
				w.Header().Add("Public-Key-Pins", hpkpHeader)
			}
			handler.ServeHTTP(w, r)
		})
		srv := &http.Server{Addr: addr, Handler: secHandler}
		http2.ConfigureServer(srv, &http2.Server{})
		srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
		srv.TLSConfig.Certificates[0] = tlsKeyPair
		tcpl, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		sshh := demux.SshHandler(config.Tls.Ssh)
		dl := &demux.DemultiplexingListener{tcpl.(*net.TCPListener), sshh}
		tlsl := tls.NewListener(dl, srv.TLSConfig)
		serve("TLS server", srv, tlsl)
	}()
	for {
		time.Sleep(500 * time.Millisecond)
	}
}

func serve(name string, srv *http.Server, listener net.Listener) {
	for {
		log.Printf("Starting the "+name+" on tcp %v\n", srv.Addr)
		if err := srv.Serve(listener); err != nil {
			log.Printf(name+" error: %v :-(\n", err)
		}
		time.Sleep(200 * time.Millisecond)
		log.Printf("Restarting the " + name + "\n")
	}
}

func httpHandler() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Host == "" {
			r.Host = config.DefaultHost
		}
		for hostid := range config.Hosts {
			hostcnf := config.Hosts[hostid]
			for hostnid := range hostcnf.Hostnames {
				hostn := hostcnf.Hostnames[hostnid]
				if glob.Glob(hostn, r.Host) {
					hostcnf.Handler.ServeHTTP(w, r)
					return
				}
			}
		}
	})
}

func readConfig() {
	flag.Parse()
	f, err := os.Open(*confpath)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	defer f.Close()
	buf, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	if err := yaml.Unmarshal(buf, &config); err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	for ib := range config.Hosts {
		config.Hosts[ib].Initialize()
		var order []string
		for path := range config.Hosts[ib].Paths {
			order = append(order, path)
		}
		sort.Sort(util.ByLengthDesc(order))
		config.Hosts[ib].PathOrder = order
	}
}

func processConfig() {
	if config.DefaultHost == "" {
		config.DefaultHost = "localhost"
	}
	if config.Tls.Cert != "" && config.Tls.Key != "" {
		tlsKeyPair, err := tls.LoadX509KeyPair(config.Tls.Cert, config.Tls.Key)
		if err != nil {
			log.Fatalf("Error reading TLS key/cert: %v :-(", err)
		}
		tlsKeyPair.Leaf, err = x509.ParseCertificate(tlsKeyPair.Certificate[len(tlsKeyPair.Certificate)-1])
		if err != nil {
			log.Fatalf("Error parsing TLS cert: %v :-(", err)
		}
		if config.Tls.Hsts.Seconds != 0 {
			hstsHeader = fmt.Sprintf("max-age=%d", config.Tls.Hsts.Seconds)
			if config.Tls.Hsts.Subdomains {
				hstsHeader += "; includeSubdomains"
			}
		}
		if config.Tls.Hpkp.Seconds != 0 {
			if len(config.Tls.Hpkp.BackupKeys) < 1 {
				log.Printf("You should add a backup key to HPKP backup_keys!\n")
			}
			hash := sha256.Sum256(tlsKeyPair.Leaf.RawSubjectPublicKeyInfo)
			hpkpHeader = fmt.Sprintf("pin-sha256=\"%s\"", base64.StdEncoding.EncodeToString(hash[0:]))
			for k := range config.Tls.Hpkp.BackupKeys {
				hpkpHeader += fmt.Sprintf("; pin-sha256=\"%s\"", config.Tls.Hpkp.BackupKeys[k])
			}
			hpkpHeader += fmt.Sprintf("; max-age=%d", config.Tls.Hpkp.Seconds)
			if config.Tls.Hpkp.Subdomains {
				hpkpHeader += "; includeSubdomains"
			}
		}
	}
}
<commit_msg>remove unnecessary func<commit_after>package main

import (
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"sort"
	"time"

	"github.com/bradfitz/http2"
	"github.com/myfreeweb/443d/demux"
	"github.com/myfreeweb/443d/util"
	"github.com/ryanuber/go-glob"
	"gopkg.in/yaml.v2"
)

type Config struct {
	Tls struct {
		Listen string
		Cert   string
		Key    string
		Ssh    string
		Hsts   struct {
			Seconds    int
			Subdomains bool
		}
		Hpkp struct {
			Seconds    int
			Subdomains bool
			BackupKeys []string `yaml:"backup_keys"`
		}
	}
	Http struct {
		Listen string
	}
	Hosts       []HttpBackend
	DefaultHost string
}

var confpath = flag.String("config", "/usr/local/etc/443d.yaml", "path to the configuration file")
var config Config
var tlsKeyPair tls.Certificate
var hstsHeader string
var hpkpHeader string

var httpHandler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	if r.Host == "" {
		r.Host = config.DefaultHost
	}
	for hostid := range config.Hosts {
		hostcnf := config.Hosts[hostid]
		for hostnid := range hostcnf.Hostnames {
			hostn := hostcnf.Hostnames[hostnid]
			if glob.Glob(hostn, r.Host) {
				hostcnf.Handler.ServeHTTP(w, r)
				return
			}
		}
	}
})

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	readConfig()
	processConfig()
	go func() {
		addr := config.Http.Listen
		if addr == "" {
			log.Printf("No listen address for the HTTP server \n")
			return
		}
		srv := &http.Server{Addr: addr, Handler: httpHandler}
		tcpl, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		serve("HTTP server", srv, tcpl)
	}()
	go func() {
		addr := config.Tls.Listen
		if addr == "" {
			log.Printf("No listen address for the TLS server \n")
			return
		}
		if config.Tls.Cert == "" && config.Tls.Key == "" {
			log.Printf("No keypair for the TLS server \n")
			return
		}
		secHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if config.Tls.Hsts.Seconds != 0 {
				w.Header().Add("Strict-Transport-Security", hstsHeader)
			}
			if config.Tls.Hpkp.Seconds != 0 {
				w.Header().Add("Public-Key-Pins", hpkpHeader)
			}
			httpHandler.ServeHTTP(w, r)
		})
		srv := &http.Server{Addr: addr, Handler: secHandler}
		http2.ConfigureServer(srv, &http2.Server{})
		srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
		srv.TLSConfig.Certificates[0] = tlsKeyPair
		tcpl, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalf("%v :-(\n", err)
		}
		sshh := demux.SshHandler(config.Tls.Ssh)
		dl := &demux.DemultiplexingListener{tcpl.(*net.TCPListener), sshh}
		tlsl := tls.NewListener(dl, srv.TLSConfig)
		serve("TLS server", srv, tlsl)
	}()
	for {
		time.Sleep(500 * time.Millisecond)
	}
}

func serve(name string, srv *http.Server, listener net.Listener) {
	for {
		log.Printf("Starting the "+name+" on tcp %v\n", srv.Addr)
		if err := srv.Serve(listener); err != nil {
			log.Printf(name+" error: %v :-(\n", err)
		}
		time.Sleep(200 * time.Millisecond)
		log.Printf("Restarting the " + name + "\n")
	}
}

func readConfig() {
	flag.Parse()
	f, err := os.Open(*confpath)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	defer f.Close()
	buf, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	if err := yaml.Unmarshal(buf, &config); err != nil {
		log.Fatalf("%v :-(\n", err)
	}
	for ib := range config.Hosts {
		config.Hosts[ib].Initialize()
		var order []string
		for path := range config.Hosts[ib].Paths {
			order = append(order, path)
		}
		sort.Sort(util.ByLengthDesc(order))
		config.Hosts[ib].PathOrder = order
	}
}

func processConfig() {
	if config.DefaultHost == "" {
		config.DefaultHost = "localhost"
	}
	if config.Tls.Cert != "" && config.Tls.Key != "" {
		tlsKeyPair, err := tls.LoadX509KeyPair(config.Tls.Cert, config.Tls.Key)
		if err != nil {
			log.Fatalf("Error reading TLS key/cert: %v :-(", err)
		}
		tlsKeyPair.Leaf, err = x509.ParseCertificate(tlsKeyPair.Certificate[len(tlsKeyPair.Certificate)-1])
		if err != nil {
			log.Fatalf("Error parsing TLS cert: %v :-(", err)
		}
		if config.Tls.Hsts.Seconds != 0 {
			hstsHeader = fmt.Sprintf("max-age=%d", config.Tls.Hsts.Seconds)
			if config.Tls.Hsts.Subdomains {
				hstsHeader += "; includeSubdomains"
			}
		}
		if config.Tls.Hpkp.Seconds != 0 {
			if len(config.Tls.Hpkp.BackupKeys) < 1 {
				log.Printf("You should add a backup key to HPKP backup_keys!\n")
			}
			hash := sha256.Sum256(tlsKeyPair.Leaf.RawSubjectPublicKeyInfo)
			hpkpHeader = fmt.Sprintf("pin-sha256=\"%s\"", base64.StdEncoding.EncodeToString(hash[0:]))
			for k := range config.Tls.Hpkp.BackupKeys {
				hpkpHeader += fmt.Sprintf("; pin-sha256=\"%s\"", config.Tls.Hpkp.BackupKeys[k])
			}
			hpkpHeader += fmt.Sprintf("; max-age=%d", config.Tls.Hpkp.Seconds)
			if config.Tls.Hpkp.Subdomains {
				hpkpHeader += "; includeSubdomains"
			}
		}
	}
}
<|endoftext|>


<commit_before>// bake - release management tool
package main

import (
	"bufio"
	"code.google.com/p/google-api-go-client/drive/v2"
	"fmt"
	"github.com/prasmussen/gdrive/gdrive"
	"github.com/singhsaysdotcom/cobra"
	"github.com/singhsaysdotcom/shlog"
	"os"
	"os/exec"
	"path"
)

var (
	// Flags
	versionFile       string
	enable_uploads    bool
	enable_git_push   bool
	enable_git_tag    bool
	enable_git_commit bool
	enable_git_tasks  bool

	logger          = shlog.NewLogger()
	is_versioned    bool
	current_version *Version

	logFile    *os.File
	errLogFile *os.File
	goog       *gdrive.Drive
)

func Build(args []string) bool {
	logger.Message("building %s ...", PkgName(""))
	_, err := exec.LookPath("go")
	if err != nil {
		logger.Err()
		return false
	}
	c := exec.Command("go", "build", "-o", PkgName(""))
	if len(args) > 0 {
		c.Args = append(c.Args, args...)
	}
	if !CaptureLogs("build", c) {
		logger.Err()
		return false
	} else {
		logger.Ok()
		return true
	}
}

// git commits version file
func CommitVersion() bool {
	var ok bool
	logger.Message("git commit new version ...")
	ok = CaptureLogs("git add", exec.Command("git", "add", versionFile))
	if !ok {
		logger.Err()
		return false
	}
	ok = CaptureLogs("commitversion", exec.Command("git", "commit", versionFile, "-m", "Built new version "+current_version.String()))
	if ok {
		logger.Ok()
	} else {
		logger.Err()
	}
	return ok
}

// adds a git tag
func TagVersion() bool {
	logger.Message("adding git tag ...")
	ok := CaptureLogs("git tag", exec.Command("git", "tag", "v"+current_version.String()))
	if ok {
		logger.Ok()
	} else {
		logger.Err()
	}
	return ok
}

// git push to remote
func Push() bool {
	logger.Message("git push to remote ...")
	changes, err := exec.Command("git", "status", "-s").Output()
	if err != nil {
		logger.Status(shlog.Orange, "skipped - unknown status")
		return false
	}
	if len(changes) > 0 {
		logger.Status(shlog.Orange, "skipped - uncommited changes")
		return false
	}
	remotes, err := exec.Command("git", "remote").Output()
	if err != nil || len(remotes) == 0 {
		logger.Status(shlog.Orange, "skipped - no remotes")
		return false
	}
	err = exec.Command("git", "push").Run()
	if err != nil {
		logger.Err()
		return false
	}
	logger.Ok()
	return true
}

// Uploads the binary to google drive
func Upload() bool {
	var (
		err error
	)
	logger.Message("uploading new binary ...")
	goog, err = gdrive.New("", false, false)
	if err != nil {
		logger.Status(shlog.Orange, "not configured")
		return false
	}
	// TODO: check it file already exists and remove it
	// TODO: add support for uploads to folders
	filename := PkgName("")
	f, err := os.Open(filename)
	defer f.Close()
	if err != nil {
		logger.Err()
		return false
	}
	fileRef := &drive.File{Title: path.Base(filename), MimeType: "application/octet-stream"}
	reader := bufio.NewReader(f)
	_, err = goog.Files.Insert(fileRef).Media(reader).Do()
	if err != nil {
		logger.Err()
		return false
	}
	logger.Ok()
	return true
}

func BuildCommon(save_version bool, upload bool, args []string) {
	var ok bool
	if !Build(args) {
		return
	}
	if save_version {
		if ok, _ = SaveVersion(&versionFile); !ok {
			return
		}
	}
	if IsGitRepo() && enable_git_tasks {
		// Skip all git changes if no new version
		if !save_version {
			logger.Message("git commit new version ...")
			logger.Status(shlog.Orange, "skipped - no new version")
			logger.Message("adding git tag ...")
			logger.Status(shlog.Orange, "skipped - no new version")
			logger.Message("git push to remote ...")
			logger.Status(shlog.Orange, "skipped - no new version")
		} else {
			if enable_git_commit && !CommitVersion() {
				return
			}
			if enable_git_tag && !TagVersion() {
				return
			}
			if enable_git_push && !Push() {
				return
			}
		}
	}
	if enable_uploads && upload {
		Upload()
	}
	logger.Done()
}

// Build a new major version
func BuildMajor(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new major version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncMajor()
	}
	BuildCommon(true, true, args)
}

// Build a new minor version
func BuildMinor(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new minor version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncMinor()
	}
	BuildCommon(true, true, args)
}

// Build at the next build number
func BuildNext(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new build version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncBuild()
	}
	BuildCommon(true, true, args)
}

// Rebuild at current version
func Rebuild(cmd *cobra.Command, args []string) {
	BuildCommon(false, false, args)
}

// Rebuilds at the current version and reuploads to drive
func Reupload(cmd *cobra.Command, args []string) {
	BuildCommon(false, true, args)
	Upload()
}

func main() {
	rootCmd := &cobra.Command{
		Use:   "bake",
		Short: "minimal build and release tool",
	}
	rootCmd.PersistentFlags().StringVarP(&versionFile, "version_file", "f", "VERSION", "name of the version file")
	rootCmd.PersistentFlags().BoolVar(&enable_uploads, "enable_uploads", true, "enable uploads to Google Drive")
	rootCmd.PersistentFlags().BoolVar(&enable_git_tasks, "enable_git_tasks", true, "enable git related tasks")
	rootCmd.PersistentFlags().BoolVar(&enable_git_commit, "enable_git_commit", true, "enable git commits for version changes")
	rootCmd.PersistentFlags().BoolVar(&enable_git_tag, "enable_git_tag", true, "enable git tagging for version changes.")
	rootCmd.PersistentFlags().BoolVar(&enable_git_push, "enable_git_push", true, "enable git push to remotes")

	is_versioned, current_version, _ = GetVersion(&versionFile)

	// Log files
	err := os.Mkdir(".log", 0755)
	if err != nil && !os.IsExist(err) {
		fmt.Printf("Error creating logs directory\n")
		os.Exit(1)
	}
	logFile, err := os.Create(".log/bake.log")
	defer logFile.Close()
	if err != nil {
		fmt.Printf("Error creating log file\n")
		os.Exit(1)
	}
	errLogFile, err = os.Create(".log/bake.err.log")
	defer errLogFile.Close()
	if err != nil {
		fmt.Printf("Error creating log file\n")
		os.Exit(1)
	}

	majorCmd := &cobra.Command{
		Use:   "major",
		Short: "build a new major version",
		Run:   BuildMajor,
	}

	minorCmd := &cobra.Command{
		Use:   "minor",
		Short: "build a new minor version",
		Run:   BuildMinor,
	}

	nextCmd := &cobra.Command{
		Use:   "next",
		Short: "build at the next build number",
		Run:   BuildNext,
	}

	rebuildCmd := &cobra.Command{
		Use:   "rebuild",
		Short: "rebuilds at the current version",
		Run:   Rebuild,
	}

	reuploadCmd := &cobra.Command{
		Use:   "reupload",
		Short: "rebuilds at the current version and reuploads to drive",
		Run:   Rebuild,
	}

	rootCmd.AddCommand(majorCmd, minorCmd, nextCmd, rebuildCmd, reuploadCmd)
	rootCmd.Execute()
}
<commit_msg>fix typo in upload task<commit_after>// bake - release management tool
package main

import (
	"bufio"
	"code.google.com/p/google-api-go-client/drive/v2"
	"fmt"
	"github.com/prasmussen/gdrive/gdrive"
	"github.com/singhsaysdotcom/cobra"
	"github.com/singhsaysdotcom/shlog"
	"os"
	"os/exec"
	"path"
)

var (
	// Flags
	versionFile       string
	enable_uploads    bool
	enable_git_push   bool
	enable_git_tag    bool
	enable_git_commit bool
	enable_git_tasks  bool

	logger          = shlog.NewLogger()
	is_versioned    bool
	current_version *Version

	logFile    *os.File
	errLogFile *os.File
	goog       *gdrive.Drive
)

func Build(args []string) bool {
	logger.Message("building %s ...", PkgName(""))
	_, err := exec.LookPath("go")
	if err != nil {
		logger.Err()
		return false
	}
	c := exec.Command("go", "build", "-o", PkgName(""))
	if len(args) > 0 {
		c.Args = append(c.Args, args...)
	}
	if !CaptureLogs("build", c) {
		logger.Err()
		return false
	} else {
		logger.Ok()
		return true
	}
}

// git commits version file
func CommitVersion() bool {
	var ok bool
	logger.Message("git commit new version ...")
	ok = CaptureLogs("git add", exec.Command("git", "add", versionFile))
	if !ok {
		logger.Err()
		return false
	}
	ok = CaptureLogs("commitversion", exec.Command("git", "commit", versionFile, "-m", "Built new version "+current_version.String()))
	if ok {
		logger.Ok()
	} else {
		logger.Err()
	}
	return ok
}

// adds a git tag
func TagVersion() bool {
	logger.Message("adding git tag ...")
	ok := CaptureLogs("git tag", exec.Command("git", "tag", "v"+current_version.String()))
	if ok {
		logger.Ok()
	} else {
		logger.Err()
	}
	return ok
}

// git push to remote
func Push() bool {
	logger.Message("git push to remote ...")
	changes, err := exec.Command("git", "status", "-s").Output()
	if err != nil {
		logger.Status(shlog.Orange, "skipped - unknown status")
		return false
	}
	if len(changes) > 0 {
		logger.Status(shlog.Orange, "skipped - uncommited changes")
		return false
	}
	remotes, err := exec.Command("git", "remote").Output()
	if err != nil || len(remotes) == 0 {
		logger.Status(shlog.Orange, "skipped - no remotes")
		return false
	}
	err = exec.Command("git", "push").Run()
	if err != nil {
		logger.Err()
		return false
	}
	logger.Ok()
	return true
}

// Uploads the binary to google drive
func Upload() bool {
	var (
		err error
	)
	logger.Message("uploading new binary ...")
	goog, err = gdrive.New("", false, false)
	if err != nil {
		logger.Status(shlog.Orange, "not configured")
		return false
	}
	// TODO: check it file already exists and remove it
	// TODO: add support for uploads to folders
	filename := PkgName("")
	f, err := os.Open(filename)
	defer f.Close()
	if err != nil {
		logger.Err()
		return false
	}
	fileRef := &drive.File{Title: path.Base(filename), MimeType: "application/octet-stream"}
	reader := bufio.NewReader(f)
	_, err = goog.Files.Insert(fileRef).Media(reader).Do()
	if err != nil {
		logger.Err()
		return false
	}
	logger.Ok()
	return true
}

func BuildCommon(save_version bool, upload bool, args []string) {
	var ok bool
	if !Build(args) {
		return
	}
	if save_version {
		if ok, _ = SaveVersion(&versionFile); !ok {
			return
		}
	}
	if IsGitRepo() && enable_git_tasks {
		// Skip all git changes if no new version
		if !save_version {
			logger.Message("git commit new version ...")
			logger.Status(shlog.Orange, "skipped - no new version")
			logger.Message("adding git tag ...")
			logger.Status(shlog.Orange, "skipped - no new version")
			logger.Message("git push to remote ...")
			logger.Status(shlog.Orange, "skipped - no new version")
		} else {
			if enable_git_commit && !CommitVersion() {
				return
			}
			if enable_git_tag && !TagVersion() {
				return
			}
			if enable_git_push && !Push() {
				return
			}
		}
	}
	if enable_uploads && upload {
		Upload()
	}
	logger.Done()
}

// Build a new major version
func BuildMajor(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new major version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncMajor()
	}
	BuildCommon(true, true, args)
}

// Build a new minor version
func BuildMinor(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new minor version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncMinor()
	}
	BuildCommon(true, true, args)
}

// Build at the next build number
func BuildNext(cmd *cobra.Command, args []string) {
	if !is_versioned {
		current_version = NewVersion()
		logger.Message("new build version")
		logger.Status(shlog.Green, current_version.String())
	} else {
		current_version.IncBuild()
	}
	BuildCommon(true, true, args)
}

// Rebuild at current version
func Rebuild(cmd *cobra.Command, args []string) {
	BuildCommon(false, false, args)
}

// Rebuilds at the current version and reuploads to drive
func Reupload(cmd *cobra.Command, args []string) {
	BuildCommon(false, true, args)
}

func main() {
	rootCmd := &cobra.Command{
		Use:   "bake",
		Short: "minimal build and release tool",
	}
	rootCmd.PersistentFlags().StringVarP(&versionFile, "version_file", "f", "VERSION", "name of the version file")
	rootCmd.PersistentFlags().BoolVar(&enable_uploads, "enable_uploads", true, "enable uploads to Google Drive")
	rootCmd.PersistentFlags().BoolVar(&enable_git_tasks, "enable_git_tasks", true, "enable git related tasks")
	rootCmd.PersistentFlags().BoolVar(&enable_git_commit, "enable_git_commit", true, "enable git commits for version changes")
	rootCmd.PersistentFlags().BoolVar(&enable_git_tag, "enable_git_tag", true, "enable git tagging for version changes.")
	rootCmd.PersistentFlags().BoolVar(&enable_git_push, "enable_git_push", true, "enable git push to remotes")

	is_versioned, current_version, _ = GetVersion(&versionFile)

	// Log files
	err := os.Mkdir(".log", 0755)
	if err != nil && !os.IsExist(err) {
		fmt.Printf("Error creating logs directory\n")
		os.Exit(1)
	}
	logFile, err := os.Create(".log/bake.log")
	defer logFile.Close()
	if err != nil {
		fmt.Printf("Error creating log file\n")
		os.Exit(1)
	}
	errLogFile, err = os.Create(".log/bake.err.log")
	defer errLogFile.Close()
	if err != nil {
		fmt.Printf("Error creating log file\n")
		os.Exit(1)
	}

	majorCmd := &cobra.Command{
		Use:   "major",
		Short: "build a new major version",
		Run:   BuildMajor,
	}

	minorCmd := &cobra.Command{
		Use:   "minor",
		Short: "build a new minor version",
		Run:   BuildMinor,
	}

	nextCmd := &cobra.Command{
		Use:   "next",
		Short: "build at the next build number",
		Run:   BuildNext,
	}

	rebuildCmd := &cobra.Command{
		Use:   "rebuild",
		Short: "rebuilds at the current version",
		Run:   Rebuild,
	}

	reuploadCmd := &cobra.Command{
		Use:   "reupload",
		Short: "rebuilds at the current version and reuploads to drive",
		Run:   Reupload,
	}

	rootCmd.AddCommand(majorCmd, minorCmd, nextCmd, rebuildCmd, reuploadCmd)
	rootCmd.Execute()
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"net/url"
	"launchpad.net/xmlpath"
	"time"
	"fmt"
	"log"
)

var BingImageOfTheDayUrl = ""

func BingImageOfTheDayPoller () {
	bingImageApiUrl := "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US"
	duration, _ := time.ParseDuration("1h")
	for {
		resp, _ := http.Get(bingImageApiUrl)
		path    := xmlpath.MustCompile("/images/image/url")
		root, _ := xmlpath.Parse(resp.Body)
		if text, ok := path.String(root); ok {
			BingImageOfTheDayUrl = fmt.Sprintf("http://www.bing.com%s", text)
			log.Printf("Setting BingImageOfTheDay: %s\n", BingImageOfTheDayUrl)
		}

		time.Sleep(duration)
	}
}

func GetBingImageOfTheDayUrl() string {
	// fallback
	if BingImageOfTheDayUrl == "" {
		imageUrl, _ := url.Parse(fmt.Sprintf("http://%s:%d/%s",
			OverwatchConfiguration.ServerName,
			OverwatchConfiguration.BindPort,
			"assets/img/bg1.jpg"))
		BingImageOfTheDayUrl = imageUrl.String()
	}
	return BingImageOfTheDayUrl
}
<commit_msg>switch to https<commit_after>package main

import (
	"net/http"
	"net/url"
	"launchpad.net/xmlpath"
	"time"
	"fmt"
	"log"
)

var BingImageOfTheDayUrl = ""

func BingImageOfTheDayPoller () {
	bingImageApiUrl := "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US"
	duration, _ := time.ParseDuration("1h")
	for {
		resp, _ := http.Get(bingImageApiUrl)
		path    := xmlpath.MustCompile("/images/image/url")
		root, _ := xmlpath.Parse(resp.Body)
		if text, ok := path.String(root); ok {
			BingImageOfTheDayUrl = fmt.Sprintf("https://www.bing.com%s", text)
			log.Printf("Setting BingImageOfTheDay: %s\n", BingImageOfTheDayUrl)
		}

		time.Sleep(duration)
	}
}

func GetBingImageOfTheDayUrl() string {
	// fallback
	if BingImageOfTheDayUrl == "" {
		imageUrl, _ := url.Parse(fmt.Sprintf("https://%s:%d/%s",
			OverwatchConfiguration.ServerName,
			OverwatchConfiguration.BindPort,
			"assets/img/bg1.jpg"))
		BingImageOfTheDayUrl = imageUrl.String()
	}
	return BingImageOfTheDayUrl
}
<|endoftext|>


<commit_before>package HologramGo

import (
	"fmt"
	"os"
)

type Plan map[string]interface{}

// Plans is just a list of Plan(s).
type Plans []Plan

// EFFECTS: Returns device data plans.
func GetDeviceDataPlans() Plan {

	req := createGetRequest("/plans/")

	resp, err := sendRequest(req)
	if err != nil {
		fmt.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}

	var payload = Placeholder{}
	err = resp.Parse(&payload)
	// error handling
	if err != nil {
		fmt.Printf("Problem parsing response: %v\n", err)
		os.Exit(1)
	}

	return payload["data"].(map[string]interface{})
}

// REQUIRES: A plan id.
// EFFECTS: Returns a given device data plan
func GetDeviceDataPlan(planid string) Plan {

	req := createGetRequest("/plans/" + string(planid))

	resp, err := sendRequest(req)
	if err != nil {
		fmt.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}

	var payload = Placeholder{}
	err = resp.Parse(&payload)
	// error handling
	if err != nil {
		fmt.Printf("Problem parsing response: %v\n", err)
		os.Exit(1)
	}

	return payload["data"].(map[string]interface{})
}

// EFFECTS: Returns the data plan id.
func (plan Plan) GetDataPlanId(map[string]interface{}) float64 {
	return plan["id"].(float64)
}

// EFFECTS: Returns the data plan partner id.
func (plan Plan) GetDataPlanPartnerId(map[string]interface{}) float64 {
	return plan["partnerid"].(float64)
}

// EFFECTS: Returns the data plan name.
func (plan Plan) GetDataPlanName(map[string]interface{}) string {
	return plan["name"].(string)
}

// EFFECTS: Returns the data plan description.
func (plan Plan) GetDataPlanDescription(map[string]interface{}) string {
	return plan["description"].(string)
}

// EFFECTS: Returns the data size.
func (plan Plan) GetDataPlanSize(map[string]interface{}) float64 {
	return plan["size"].(float64)
}

// EFFECTS: Returns true if it is recurring.
func (plan Plan) IsDataPlanRecurring(map[string]interface{}) bool {
	return plan["recurring"].(bool)
}

// EFFECTS: Returns true if the data plan is enabled.
func (plan Plan) IsDataPlanEnabled(map[string]interface{}) bool {
	return plan["enabled"].(bool)
}

// EFFECTS: Returns the billing period.
func (plan Plan) GetDataPlanBillingPeriod(map[string]interface{}) float64 {
	return plan["billingperiod"].(float64)
}

// EFFECTS: Returns the number of trial days left.
func (plan Plan) GetDataPlanTrialDays(map[string]interface{}) float64 {
	return plan["traildays"].(float64)
}

// EFFECTS: Returns the data plan template id.
func (plan Plan) GetDataPlanTemplateId(map[string]interface{}) float64 {
	return plan["templateid"].(float64)
}

// EFFECTS: Returns the carrier id of the data plan.
func (plan Plan) GetDataPlanCarrierId(map[string]interface{}) float64 {
	return plan["carrierid"].(float64)
}

// EFFECTS: Returns the groupid of the data plan.
func (plan Plan) GetDataPlanGroupId(map[string]interface{}) float64 {
	return plan["groupid"].(float64)
}
<commit_msg>updated plan to handle array interface response<commit_after>package HologramGo

import (
	"fmt"
	"os"
	"strconv"
)

type Plan map[string]interface{}

// Plans is just a list of Plan(s).
type Plans []interface{}

// TODO: Add Plans data type for this call here.
// EFFECTS: Returns device data plans.
func GetDeviceDataPlans() Plans {

	req := createGetRequest("/plans/")

	resp, err := sendRequest(req)
	if err != nil {
		fmt.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}

	var payload = Placeholder{}
	err = resp.Parse(&payload)
	// error handling
	if err != nil {
		fmt.Printf("Problem parsing response: %v\n", err)
		os.Exit(1)
	}

	return payload["data"].([]interface{})
}

// REQUIRES: A plan id.
// EFFECTS: Returns a given device data plan
func GetDeviceDataPlan(planid int) Plan {

	req := createGetRequest("/plans/" + strconv.Itoa(planid))

	resp, err := sendRequest(req)
	if err != nil {
		fmt.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}

	var payload = Placeholder{}
	err = resp.Parse(&payload)
	// error handling
	if err != nil {
		fmt.Printf("Problem parsing response: %v\n", err)
		os.Exit(1)
	}

	plans := payload["data"].([]interface{})

	return (Plan)(plans[0].(map[string]interface{}))
}

// EFFECTS: Returns the data plan id.
func (plan Plan) GetDataPlanId() float64 {
	return plan["id"].(float64)
}

// EFFECTS: Returns the data plan partner id.
func (plan Plan) GetDataPlanPartnerId() float64 {
	return plan["partnerid"].(float64)
}

// EFFECTS: Returns the data plan name.
func (plan Plan) GetDataPlanName() string {
	return plan["name"].(string)
}

// EFFECTS: Returns the data plan description.
func (plan Plan) GetDataPlanDescription() string {
	return plan["description"].(string)
}

// EFFECTS: Returns the data size.
func (plan Plan) GetDataPlanSize() float64 {
	return plan["data"].(float64)
}

// EFFECTS: Returns true if it is recurring.
func (plan Plan) IsDataPlanRecurring() bool {
	return plan["recurring"].(bool)
}

// EFFECTS: Returns true if the data plan is enabled.
func (plan Plan) IsDataPlanEnabled() bool {
	return plan["enabled"].(bool)
}

// EFFECTS: Returns the billing period.
func (plan Plan) GetDataPlanBillingPeriod() float64 {
	return plan["billingperiod"].(float64)
}

// EFFECTS: Returns the number of trial days left.
func (plan Plan) GetDataPlanTrialDays() float64 {
	return plan["traildays"].(float64)
}

// EFFECTS: Returns the data plan template id.
func (plan Plan) GetDataPlanTemplateId() float64 {
	return plan["templateid"].(float64)
}

// EFFECTS: Returns the carrier id of the data plan.
func (plan Plan) GetDataPlanCarrierId() float64 {
	return plan["carrierid"].(float64)
}

// EFFECTS: Returns the groupid of the data plan.
func (plan Plan) GetDataPlanGroupId() float64 {
	return plan["groupid"].(float64)
}
<|endoftext|>