<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/samuel/go-gettext/gettext"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

func IsParamSet(r *http.Request, param string) bool {
	return len(r.URL.Query().Get(param)) > 0
}

func Lang(r *http.Request) string {
	lang := r.URL.Query().Get("lang")
	if len(lang) == 0 {
		lang = "en_US"
	}
	return lang
}

func GetQS(q url.Values, param string, deflt int) (num int, str string) {
	str = q.Get(param)
	num, err := strconv.Atoi(str)
	if err != nil {
		num = deflt
		str = ""
	} else {
		str = fmt.Sprintf("&%s=%s", param, str)
	}
	return
}

func GetHost(r *http.Request) (host string, err error) {
	// get remote ip
	host = r.Header.Get("X-Forwarded-For")
	if len(host) > 0 {
		parts := strings.Split(host, ",")
		// apache will append the remote address
		host = strings.TrimSpace(parts[len(parts)-1])
	} else {
		host, _, err = net.SplitHostPort(r.RemoteAddr)
	}
	return
}

var TBBUserAgents = regexp.MustCompile(`^Mozilla/5\.0 \(Windows NT 6\.1; rv:[\d]+\.0\) Gecko/20100101 Firefox/[\d]+\.0$`)

func LikelyTBB(ua string) bool {
	return TBBUserAgents.MatchString(ua)
}

var HaveManual = map[string]bool{
	"ar":    true,
	"cs":    true,
	"de":    true,
	"el":    true,
	"en":    true,
	"es":    true,
	"fa":    true,
	"fr":    true,
	"hu":    true,
	"it":    true,
	"ja":    true,
	"lv":    true,
	"nb":    true,
	"nl":    true,
	"pl":    true,
	"pt_BR": true,
	"ru":    true,
	"sv":    true,
	"tr":    true,
	"zh_CN": true,
}

func FuncMap(domain *gettext.Domain) template.FuncMap {
	return template.FuncMap{
		"UnEscaped": func(x string) interface{} {
			return template.HTML(x)
		},
		"UnEscapedURL": func(x string) interface{} {
			return template.URL(x)
		},
		"GetText": func(lang string, text string) string {
			return domain.GetText(lang, text)
		},
		"Equal": func(one string, two string) bool {
			return one == two
		},
		"Not": func(b bool) bool {
			return !b
		},
		"And": func(a bool, b bool) bool {
			return a && b
		},
		"UserManual": func(lang string) string {
			if _, ok := HaveManual[lang]; !ok {
				lang = "en"
			}
			return lang
		},
	}
}

var Layout *template.Template

func CompileTemplate(base string, domain *gettext.Domain, templateName string) *template.Template {
	if Layout == nil {
		Layout = template.New("")
		Layout = Layout.Funcs(FuncMap(domain))
		Layout = template.Must(Layout.ParseFiles(
			path.Join(base, "public/base.html"),
			path.Join(base, "public/torbutton.html"),
		))
	}
	l, err := Layout.Clone()
	if err != nil {
		log.Fatal(err)
	}
	return template.Must(l.ParseFiles(path.Join(base, "public/", templateName)))
}

type locale struct {
	Code string
	Name string
}

func GetLocaleList(base string) map[string]string {
	// populated from https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
	// and https://sites.google.com/site/opti365/translate_codes
	// and https://en.wikipedia.org/w/api.php?action=sitematrix&format=json
	haveTranslatedNames := map[string]string{
		"af":    "Afrikaans",
		"ar":    "العربية",
		"bs":    "Bosanski jezik",
		"ca":    "Català",
		"cs":    "Čeština",
		"cy":    "Cymraeg",
		"da":    "Dansk",
		"de":    "Deutsch",
		"el":    "ελληνικά",
		"eo":    "Esperanto",
		"es":    "Español",
		"es_AR": "Español (Argentina)",
		"et":    "Eesti",
		"eu":    "Euskara",
		"fa":    "فارسی",
		"fi":    "Suomi",
		"fr":    "Français",
		"fr_CA": "Français (Canadien)",
		"gl":    "Galego",
		"he":    "עברית",
		"hi":    "हिन्दी",
		"hr":    "Hrvatski jezik",
		"hr_HR": "Hrvatski jezik (Croatia)",
		"hu":    "Magyar",
		"id":    "Bahasa Indonesia",
		"it":    "Italiano",
		"ja":    "日本語",
		"km":    "មែរ",
		"kn":    "ಕನ್ನಡ",
		"ko":    "한국어",
		"ko_KR": "한국어 (South Korea)",
		"lv":    "Latviešu valoda",
		"mk":    "македонски јазик",
		"ms_MY": "Bahasa Melayu",
		"my":    "ဗမာစာ",
		"nb":    "Norsk bokmål",
		"nl":    "Nederlands",
		"nl_BE": "Vlaams",
		"pa":    "ਪੰਜਾਬੀ",
		"pl":    "Język polski",
		"pl_PL": "Język polski (Poland)",
		"pt":    "Português",
		"pt_BR": "Português do Brasil",
		"ru":    "русский язык",
		"si_LK": "සිංහල",
		"sk":    "Slovenčina",
		"sl":    "Slovenski jezik",
		"sl_SI": "Slovenski jezik (Slovenia)",
		"sr":    "српски језик",
		"sv":    "Svenska",
		"te_IN": "తెలుగు",
		"th":    "ไทย",
		"tr":    "Türkçe",
		"uk":    "українська мова",
		"zh_CN": "中文简体",
		"zh_TW": "中文繁體",
	}

	// for all folders in locale which match a locale from https://www.transifex.com/api/2/languages/
	// use the language name unless we have an override
	webLocales, err := FetchTranslationLocales(base)
	if err != nil {
		log.Printf("Failed to get up to date language list, using fallback.")
		return haveTranslatedNames
	}

	return GetInstalledLocales(base, webLocales, haveTranslatedNames)
}

func FetchTranslationLocales(base string) (map[string]locale, error) {
	file, err := os.Open(path.Join(base, "data/langs"))
	if err != nil {
		return nil, err
	}
	defer file.Close()

	webLocales := make(map[string]locale)
	// Parse the api response into a list of possible locales
	dec := json.NewDecoder(file)
	for {
		var webList []locale
		if err = dec.Decode(&webList); err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		// The api returns an array, so we need to map it
		for _, l := range webList {
			webLocales[l.Code] = l
		}
	}

	return webLocales, nil
}

// Get a list of all languages installed in our locale folder with translations if available
func GetInstalledLocales(base string, webLocales map[string]locale, nameTranslations map[string]string) map[string]string {
	localFiles, err := ioutil.ReadDir(path.Join(base, "locale"))

	if err != nil {
		log.Print("No locales found in 'locale'. Try running 'make i18n'.")
		log.Fatal(err)
	}

	locales := make(map[string]string, len(localFiles))
	locales["en_US"] = "English"

	for _, f := range localFiles {
		// TODO: Ensure a language has 100% of the template file
		// Currently this is what should be on the torcheck_completed
		// branch on the translations git should be, so we don't really
		// have to check it in theory...
		code := f.Name()

		// Only accept folders which have corresponding locale
		if !f.IsDir() || webLocales[code] == (locale{}) {
			continue
		}

		// If we have a translated name for a given locale, use it
		if transName := nameTranslations[code]; transName != "" {
			locales[code] = transName
		} else {
			log.Print("No translated name for code: " + code)
			locales[code] = webLocales[code].Name
		}
	}

	return locales
}
<commit_msg>Add translated names<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/samuel/go-gettext/gettext"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

func IsParamSet(r *http.Request, param string) bool {
	return len(r.URL.Query().Get(param)) > 0
}

func Lang(r *http.Request) string {
	lang := r.URL.Query().Get("lang")
	if len(lang) == 0 {
		lang = "en_US"
	}
	return lang
}

func GetQS(q url.Values, param string, deflt int) (num int, str string) {
	str = q.Get(param)
	num, err := strconv.Atoi(str)
	if err != nil {
		num = deflt
		str = ""
	} else {
		str = fmt.Sprintf("&%s=%s", param, str)
	}
	return
}

func GetHost(r *http.Request) (host string, err error) {
	// get remote ip
	host = r.Header.Get("X-Forwarded-For")
	if len(host) > 0 {
		parts := strings.Split(host, ",")
		// apache will append the remote address
		host = strings.TrimSpace(parts[len(parts)-1])
	} else {
		host, _, err = net.SplitHostPort(r.RemoteAddr)
	}
	return
}

var TBBUserAgents = regexp.MustCompile(`^Mozilla/5\.0 \(Windows NT 6\.1; rv:[\d]+\.0\) Gecko/20100101 Firefox/[\d]+\.0$`)

func LikelyTBB(ua string) bool {
	return TBBUserAgents.MatchString(ua)
}

var HaveManual = map[string]bool{
	"ar":    true,
	"cs":    true,
	"de":    true,
	"el":    true,
	"en":    true,
	"es":    true,
	"fa":    true,
	"fr":    true,
	"hu":    true,
	"it":    true,
	"ja":    true,
	"lv":    true,
	"nb":    true,
	"nl":    true,
	"pl":    true,
	"pt_BR": true,
	"ru":    true,
	"sv":    true,
	"tr":    true,
	"zh_CN": true,
}

func FuncMap(domain *gettext.Domain) template.FuncMap {
	return template.FuncMap{
		"UnEscaped": func(x string) interface{} {
			return template.HTML(x)
		},
		"UnEscapedURL": func(x string) interface{} {
			return template.URL(x)
		},
		"GetText": func(lang string, text string) string {
			return domain.GetText(lang, text)
		},
		"Equal": func(one string, two string) bool {
			return one == two
		},
		"Not": func(b bool) bool {
			return !b
		},
		"And": func(a bool, b bool) bool {
			return a && b
		},
		"UserManual": func(lang string) string {
			if _, ok := HaveManual[lang]; !ok {
				lang = "en"
			}
			return lang
		},
	}
}

var Layout *template.Template

func CompileTemplate(base string, domain *gettext.Domain, templateName string) *template.Template {
	if Layout == nil {
		Layout = template.New("")
		Layout = Layout.Funcs(FuncMap(domain))
		Layout = template.Must(Layout.ParseFiles(
			path.Join(base, "public/base.html"),
			path.Join(base, "public/torbutton.html"),
		))
	}
	l, err := Layout.Clone()
	if err != nil {
		log.Fatal(err)
	}
	return template.Must(l.ParseFiles(path.Join(base, "public/", templateName)))
}

type locale struct {
	Code string
	Name string
}

func GetLocaleList(base string) map[string]string {
	// populated from https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
	// and https://sites.google.com/site/opti365/translate_codes
	// and https://en.wikipedia.org/w/api.php?action=sitematrix&format=json
	haveTranslatedNames := map[string]string{
		"af":          "Afrikaans",
		"ar":          "العربية",
		"bg":          "български",
		"bs":          "Bosanski jezik",
		"ca":          "Català",
		"cs":          "Čeština",
		"cy":          "Cymraeg",
		"da":          "Dansk",
		"de":          "Deutsch",
		"el":          "ελληνικά",
		"en_GB":       "English (United Kingdom)",
		"eo":          "Esperanto",
		"es":          "Español",
		"es_AR":       "Español (Argentina)",
		"es_MX":       "Español (Mexico)",
		"et":          "Eesti",
		"eu":          "Euskara",
		"fa":          "فارسی",
		"fi":          "Suomi",
		"fr":          "Français",
		"fr_CA":       "Français (Canadien)",
		"gl":          "Galego",
		"he":          "עברית",
		"hi":          "हिन्दी",
		"hr":          "Hrvatski jezik",
		"hr_HR":       "Hrvatski jezik (Croatia)",
		"hu":          "Magyar",
		"id":          "Bahasa Indonesia",
		"it":          "Italiano",
		"ja":          "日本語",
		"km":          "មែរ",
		"kn":          "ಕನ್ನಡ",
		"ko":          "한국어",
		"ko_KR":       "한국어 (South Korea)",
		"lv":          "Latviešu valoda",
		"mk":          "македонски јазик",
		"ms_MY":       "Bahasa Melayu",
		"my":          "ဗမာစာ",
		"nb":          "Norsk bokmål",
		"nl":          "Nederlands",
		"nl_BE":       "Vlaams",
		"pa":          "ਪੰਜਾਬੀ",
		"pl":          "Język polski",
		"pl_PL":       "Język polski (Poland)",
		"pt":          "Português",
		"pt_BR":       "Português do Brasil",
		"ro":          "română",
		"ru":          "русский язык",
		"ru@petr1708": "Russian Petrine orthography",
		"si_LK":       "සිංහල",
		"sk":          "Slovenčina",
		"sk_SK":       "Slovenčina (Slovakia)",
		"sl":          "Slovenski jezik",
		"sl_SI":       "Slovenski jezik (Slovenia)",
		"sr":          "српски језик",
		"sv":          "Svenska",
		"te_IN":       "తెలుగు",
		"th":          "ไทย",
		"tr":          "Türkçe",
		"uk":          "українська мова",
		"zh_CN":       "中文简体",
		"zh_TW":       "中文繁體",
	}

	// for all folders in locale which match a locale from https://www.transifex.com/api/2/languages/
	// use the language name unless we have an override
	webLocales, err := FetchTranslationLocales(base)
	if err != nil {
		log.Printf("Failed to get up to date language list, using fallback.")
		return haveTranslatedNames
	}

	return GetInstalledLocales(base, webLocales, haveTranslatedNames)
}

func FetchTranslationLocales(base string) (map[string]locale, error) {
	file, err := os.Open(path.Join(base, "data/langs"))
	if err != nil {
		return nil, err
	}
	defer file.Close()

	webLocales := make(map[string]locale)
	// Parse the api response into a list of possible locales
	dec := json.NewDecoder(file)
	for {
		var webList []locale
		if err = dec.Decode(&webList); err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		// The api returns an array, so we need to map it
		for _, l := range webList {
			webLocales[l.Code] = l
		}
	}

	return webLocales, nil
}

// Get a list of all languages installed in our locale folder with translations if available
func GetInstalledLocales(base string, webLocales map[string]locale, nameTranslations map[string]string) map[string]string {
	localFiles, err := ioutil.ReadDir(path.Join(base, "locale"))

	if err != nil {
		log.Print("No locales found in 'locale'. Try running 'make i18n'.")
		log.Fatal(err)
	}

	locales := make(map[string]string, len(localFiles))
	locales["en_US"] = "English"

	for _, f := range localFiles {
		// TODO: Ensure a language has 100% of the template file
		// Currently this is what should be on the torcheck_completed
		// branch on the translations git should be, so we don't really
		// have to check it in theory...
		code := f.Name()

		// Only accept folders which have corresponding locale
		if !f.IsDir() || webLocales[code] == (locale{}) {
			continue
		}

		// If we have a translated name for a given locale, use it
		if transName := nameTranslations[code]; transName != "" {
			locales[code] = transName
		} else {
			log.Print("No translated name for code: " + code)
			locales[code] = webLocales[code].Name
		}
	}

	return locales
}
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/pprof"

	"github.com/gorilla/mux"
)

// JSON response convenience function
func jsonResponse(w http.ResponseWriter, data interface{}, err error) {
	w.Header().Add("Content-Type", "application/json")

	// Error Response - Return early
	if err != nil {
		jErr, _ := json.Marshal(map[string]interface{}{
			"Error": err.Error(),
		})
		w.WriteHeader(500)
		w.Write(jErr)
	}

	// Try to handle data
	jRes, mErr := json.Marshal(data)
	if mErr != nil {
		jErr, _ := json.Marshal(map[string]interface{}{
			"Data Error": err.Error(),
		})
		w.WriteHeader(500)
		w.Write(jErr)
	}
	w.Write(jRes)
}

// Nests map (for adding envelope)
func envelope(d interface{}, envelope string) map[string]interface{} {
	return map[string]interface{}{
		envelope: d,
	}
}

// Unpacks map (opposite process of envelope)
func unvelope(d []byte, envelope string) ([]byte, error) {
	var raw map[string]interface{}

	// Need to use a custom JSON decoder in order to handle large ID
	dec := json.NewDecoder(bytes.NewReader(d))
	dec.UseNumber()
	err := dec.Decode(&raw)
	if err != nil {
		return nil, err
	}

	return json.Marshal(raw[envelope])
}

func enableProfiling(r *mux.Router) {
	r.HandleFunc("/debug/pprof", pprof.Index)
	r.HandleFunc("/debug/pprof/profile", pprof.Profile)
	r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	r.Handle("/debug/block", pprof.Handler("block"))
	r.Handle("/debug/goroutine", pprof.Handler("goroutine"))
	r.Handle("/debug/heap", pprof.Handler("heap"))
	r.Handle("/debug/threadcreate", pprof.Handler("threadcreate"))
}
<commit_msg>support http status code in jsonResponse function<commit_after>package utils

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/pprof"

	"github.com/gorilla/mux"
)

// JSON response convenience function
func jsonResponse(w http.ResponseWriter, status int, data interface{}, err error) {
	w.Header().Add("Content-Type", "application/json")

	// Error Response - Return early
	if err != nil {
		jErr, _ := json.Marshal(map[string]interface{}{
			"Error": err.Error(),
		})
		w.WriteHeader(500)
		w.Write(jErr)
	}

	// Try to handle data
	jRes, mErr := json.Marshal(data)
	if mErr != nil {
		jErr, _ := json.Marshal(map[string]interface{}{
			"Data Error": err.Error(),
		})
		w.WriteHeader(500)
		w.Write(jErr)
	}
	w.WriteHeader(status)
	w.Write(jRes)
}

// Nests map (for adding envelope)
func envelope(d interface{}, envelope string) map[string]interface{} {
	return map[string]interface{}{
		envelope: d,
	}
}

// Unpacks map (opposite process of envelope)
func unvelope(d []byte, envelope string) ([]byte, error) {
	var raw map[string]interface{}

	// Need to use a custom JSON decoder in order to handle large ID
	dec := json.NewDecoder(bytes.NewReader(d))
	dec.UseNumber()
	err := dec.Decode(&raw)
	if err != nil {
		return nil, err
	}

	return json.Marshal(raw[envelope])
}

func enableProfiling(r *mux.Router) {
	r.HandleFunc("/debug/pprof", pprof.Index)
	r.HandleFunc("/debug/pprof/profile", pprof.Profile)
	r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	r.Handle("/debug/block", pprof.Handler("block"))
	r.Handle("/debug/goroutine", pprof.Handler("goroutine"))
	r.Handle("/debug/heap", pprof.Handler("heap"))
	r.Handle("/debug/threadcreate", pprof.Handler("threadcreate"))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// trace writes the command in the programs stdout for debug purposes.
// the command is wrapped in xml tags for easy parsing.
func trace(cmd *exec.Cmd) {
	fmt.Printf("<command>%s</command>\n", strings.Join(cmd.Args, " "))
}

// helper function returns true if directory dir is empty.
func isDirEmpty(dir string) bool {
	f, err := os.Open(dir)
	if err != nil {
		return true
	}
	defer f.Close()

	_, err = f.Readdir(1)
	return err == io.EOF
}

// helper function returns true if the commit is a pull_request.
func isPullRequest(event string) bool {
	return event == "pull_request"
}

// helper function returns true if the commit is a tag.
func isTag(event, ref string) bool {
	return event == "tag" ||
		strings.HasPrefix(ref, "refs/tags/")
}

// helper function to write a netrc file.
func writeNetrc(machine, login, password string) error {
	if machine == "" {
		return nil
	}
	out := fmt.Sprintf(
		netrcFile,
		machine,
		login,
		password,
	)
	home := "/root"
	u, err := user.Current()
	if err == nil {
		home = u.HomeDir
	}
	path := filepath.Join(home, ".netrc")
	return ioutil.WriteFile(path, []byte(out), 0600)
}

const netrcFile = `
machine %s
login %s
password %s
`
<commit_msg>updated trace function format<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// trace writes the command in the programs stdout for debug purposes.
// the command is wrapped in xml tags for easy parsing.
func trace(cmd *exec.Cmd) {
	fmt.Printf("+ %s\n", strings.Join(cmd.Args, " "))
}

// helper function returns true if directory dir is empty.
func isDirEmpty(dir string) bool {
	f, err := os.Open(dir)
	if err != nil {
		return true
	}
	defer f.Close()

	_, err = f.Readdir(1)
	return err == io.EOF
}

// helper function returns true if the commit is a pull_request.
func isPullRequest(event string) bool {
	return event == "pull_request"
}

// helper function returns true if the commit is a tag.
func isTag(event, ref string) bool {
	return event == "tag" ||
		strings.HasPrefix(ref, "refs/tags/")
}

// helper function to write a netrc file.
func writeNetrc(machine, login, password string) error {
	if machine == "" {
		return nil
	}
	out := fmt.Sprintf(
		netrcFile,
		machine,
		login,
		password,
	)

	home := "/root"
	u, err := user.Current()
	if err == nil {
		home = u.HomeDir
	}
	path := filepath.Join(home, ".netrc")
	return ioutil.WriteFile(path, []byte(out), 0600)
}

const netrcFile = `
machine %s
login %s
password %s
`
<|endoftext|>


<commit_before>package relay

import (
	"io"
	"net/http"
	"strings"
)

//IsWebSocketRequest returns true if a http.Request object is based on
//websocket standards
func IsWebSocketRequest(r *http.Request) bool {
	var _ interface{}
	_, hasUpgrade := r.Header["Upgrade"]
	_, hasSec := r.Header["Sec-Websocket-Version"]
	_, hasExt := r.Header["Sec-Websocket-Extensions"]
	_, hasKey := r.Header["Sec-Websocket-Key"]
	return hasUpgrade && hasSec && hasExt && hasKey
}

func setUpHeadings(r *HTTPRequest) {
	agent, ok := r.Req.Header["User-Agent"]

	if ok {
		ag := strings.Join(agent, ";")
		msie := strings.Index(ag, ";MSIE")
		trident := strings.Index(ag, "Trident/")

		if msie != -1 || trident != -1 {
			// r.Res.Header().Set("X-XSS-Protection", "0")
		}
	}

	origin, ok := r.Req.Header["Origin"]

	if ok {
		r.Res.Header().Set("Access-Control-Allow-Credentials", "true")
		r.Res.Header().Set("Access-Control-Allow-Origin", strings.Join(origin, ";"))
	} else {
		r.Res.Header().Set("Access-Control-Allow-Origin", "*")
	}
}
func loadData(r *HTTPRequest) (*Message, error) {
	msg := Message{}
	msg.Method = r.Req.Method

	content, ok := r.Req.Header["Content-Type"]

	if ok {
		muxcontent := strings.Join(content, ";")

		if strings.Index(muxcontent, "application/x-www-form-urlencode") != -1 {
			if err := r.Req.ParseForm(); err != nil {
				return nil, err
			}

			msg.MessageType = "form"
			msg.Method = r.Req.Method
			msg.Form = r.Req.Form
			msg.PostForm = r.Req.PostForm

			return &msg, nil
		}

		if strings.Index(muxcontent, "multipart/form-data") != -1 {
			if err := r.Req.ParseMultipartForm(32 << 20); err != nil {
				return nil, err
			}

			msg.MessageType = "multipart"
			msg.Multipart = r.Req.MultipartForm
			return &msg, nil
		}
	}

	if r.Req.Body == nil {
		return nil, nil
	}

	data := make([]byte, r.Req.ContentLength)
	_, err := r.Req.Body.Read(data)

	if err != nil && err != io.EOF {
		return nil, err
	}

	msg.MessageType = "body"
	msg.Payload = data

	return &msg, nil
}
<commit_msg>fixing reggy calls<commit_after>package relay

import (
	"io"
	"net/http"
	"strings"
)

//IsWebSocketRequest returns true if a http.Request object is based on
//websocket standards
func IsWebSocketRequest(r *http.Request) bool {
	var _ interface{}
	_, hasUpgrade := r.Header["Upgrade"]
	_, hasSec := r.Header["Sec-Websocket-Version"]
	_, hasExt := r.Header["Sec-Websocket-Extensions"]
	_, hasKey := r.Header["Sec-Websocket-Key"]
	return hasUpgrade && hasSec && hasExt && hasKey
}

func setUpHeadings(r *HTTPRequest) {
	agent, ok := r.Req.Header["User-Agent"]

	if ok {
		ag := strings.Join(agent, ";")
		msie := strings.Index(ag, ";MSIE")
		trident := strings.Index(ag, "Trident/")

		if msie != -1 || trident != -1 {
			// r.Res.Header().Set("X-XSS-Protection", "0")
		}
	}

	origin, ok := r.Req.Header["Origin"]

	if ok {
		r.Res.Header().Set("Access-Control-Allow-Credentials", "true")
		r.Res.Header().Set("Access-Control-Allow-Origin", strings.Join(origin, ";"))
	} else {
		r.Res.Header().Set("Access-Control-Allow-Origin", "*")
	}
}

func loadData(r *HTTPRequest) (*Message, error) {
	msg := Message{}
	msg.Method = r.Req.Method

	content, ok := r.Req.Header["Content-Type"]

	if ok {
		muxcontent := strings.Join(content, ";")

		if strings.Index(muxcontent, "application/x-www-form-urlencode") != -1 {
			if err := r.Req.ParseForm(); err != nil {
				return nil, err
			}

			msg.MessageType = "form"
			msg.Method = r.Req.Method
			msg.Form = r.Req.Form
			msg.PostForm = r.Req.PostForm

			return &msg, nil
		}

		if strings.Index(muxcontent, "multipart/form-data") != -1 {
			if err := r.Req.ParseMultipartForm(32 << 20); err != nil {
				return nil, err
			}

			msg.MessageType = "multipart"
			msg.Multipart = r.Req.MultipartForm
			return &msg, nil
		}
	}

	if r.Req.Body == nil {
		return nil, nil
	}

	data := make([]byte, r.Req.ContentLength)
	_, err := r.Req.Body.Read(data)

	if err != nil && err != io.EOF {
		return nil, err
	}

	msg.MessageType = "body"
	msg.Payload = data

	return &msg, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"strings"
)

func createKey(path string) string {
	var buffer bytes.Buffer
	buffer.WriteString(*uploadpath)
	if *uploadpath == "/" {
		if startWith(path, "/") {
			return path
		}
		buffer.WriteString(path)
		return buffer.String()
	} else {
		if !endWith(*uploadpath, "/") && !startWith(path, "/") {
			buffer.WriteString("/")
		}
		if endWith(*uploadpath, "/") && startWith(path, "/") {
			buffer.WriteString(string(path[1:]))
		} else {
			buffer.WriteString(path)
		}
		return buffer.String()
	}
}

func startWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[0:len(substring)])
	return str == substring
}

func endWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[len(original)-len(substring):])
	return str == substring
}

func getFileName(filepath string) string {
	if *rename != "" {
		return *rename
	}
	index := strings.LastIndex(filepath, "/")
	if index == -1 {
		return filepath
	}
	return filepath[index+1:]
}

func getFolderName(filepath string) string {
	if endWith(filepath, "/") {
		pos := strings.LastIndex(string(filepath[:len(filepath)-1]), "/")
		return string(filepath[pos+1 : len(filepath)-1])
	} else {
		pos := strings.LastIndex(filepath, "/")
		return string(filepath[pos+1:])
	}
}

func getPathInsideFolder(path, folder string) string {
	pos := strings.Index(path, folder)
	var result string
	if pos != -1 {
		result = string(path[pos-1:])
	}
	return result
}
<commit_msg>Fix golint issues<commit_after>package main

import (
	"bytes"
	"strings"
)

func createKey(path string) string {
	var buffer bytes.Buffer
	buffer.WriteString(*uploadpath)
	if *uploadpath == "/" {
		if startWith(path, "/") {
			return path
		}
		buffer.WriteString(path)
	} else {
		if !endWith(*uploadpath, "/") && !startWith(path, "/") {
			buffer.WriteString("/")
		}
		if endWith(*uploadpath, "/") && startWith(path, "/") {
			buffer.WriteString(string(path[1:]))
		} else {
			buffer.WriteString(path)
		}
	}
	return buffer.String()
}

func startWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[0:len(substring)])
	return str == substring
}

func endWith(original, substring string) bool {
	if len(substring) > len(original) {
		return false
	}
	str := string(original[len(original)-len(substring):])
	return str == substring
}

func getFileName(filepath string) string {
	if *rename != "" {
		return *rename
	}
	index := strings.LastIndex(filepath, "/")
	if index == -1 {
		return filepath
	}
	return filepath[index+1:]
}

func getFolderName(filepath string) string {
	var result string
	if endWith(filepath, "/") {
		pos := strings.LastIndex(string(filepath[:len(filepath)-1]), "/")
		result = filepath[pos+1 : len(filepath)-1]
	} else {
		pos := strings.LastIndex(filepath, "/")
		result = filepath[pos+1:]
	}
	return result
}

func getPathInsideFolder(path, folder string) string {
	pos := strings.Index(path, folder)
	var result string
	if pos != -1 {
		result = string(path[pos-1:])
	}
	return result
}
<|endoftext|>


<commit_before>package main

import (
    "bytes"
    "fmt"
    "ini"
    "io"
    "io/ioutil"
    "os"
    "path"
    "template"
)

var toolext = map[string]string{"386": "8", "amd64": "6", "arm": "5"}

func writeTemplate(tmplString string, data interface{}, filename string) os.Error {
    var err os.Error
    tmpl := template.New(nil)
    tmpl.SetDelims("{{", "}}")

    if err = tmpl.Parse(tmplString); err != nil {
        return err
    }

    var buf bytes.Buffer

    tmpl.Execute(data, &buf)

    if err := ioutil.WriteFile(filename, buf.Bytes(), 0644); err != nil {
        return err
    }

    return nil
}

func printHelp() { println("Commands: create, serve") }

func exists(path string) bool {
    _, err := os.Lstat(path)
    return err == nil
}

func create(name string) {
    cwd := os.Getenv("PWD")
    projectDir := path.Join(cwd, name)

    if exists(projectDir) {
        println("Project directory already exists")
        os.Exit(0)
    }

    println("Creating directory ", projectDir)
    if err := os.Mkdir(projectDir, 0744); err != nil {
        println(err.String())
        os.Exit(0)
    }

    appfile := path.Join(projectDir, name+".go")
    println("Creating application file", appfile)
    writeTemplate(apptmpl, map[string]string{"app": name}, appfile)

    inifile := path.Join(projectDir, "default.ini")
    println("Creating config file", inifile)
    writeTemplate(initmpl, map[string]string{"app": name}, inifile)

}

func getOutput(command string, args []string) (string, os.Error) {
    r, w, err := os.Pipe()
    if err != nil {
        return "", err
    }
    args2 := make([]string, len(args)+1)
    args2[0] = command
    copy(args2[1:], args)
    pid, err := os.ForkExec(command, args2, os.Environ(), "", []*os.File{nil, w, w})

    if err != nil {
        return "", err
    }

    w.Close()

    var b bytes.Buffer
    io.Copy(&b, r)
    output := b.String()
    os.Wait(pid, 0)

    return output, nil
}

func serve(inifile string) {
    cwd := os.Getenv("PWD")
    inifile = path.Join(cwd, inifile)
    datadir := path.Join(cwd, "data/")

    if !exists(datadir) {
        if err := os.Mkdir(datadir, 0744); err != nil {
            println(err.String())
            return
        }
    }

    config, err := ini.ParseFile(inifile)

    if err != nil {
        println("Error parsing config", err.String())
        return
    }

    app := config["main"]["application"]

    println("Serving application", app)

    address := fmt.Sprintf("%s:%s", config["main"]["bind_address"], config["main"]["port"])
    gobin := os.Getenv("GOBIN")
    goarch := os.Getenv("GOARCH")
    ext := toolext[goarch]
    compiler := path.Join(gobin, ext+"g")
    linker := path.Join(gobin, ext+"l")

    appSrc := path.Join(cwd, app+".go")
    appObj := path.Join(datadir, app+"."+ext)

    output, err := getOutput(compiler, []string{"-o", appObj, appSrc})

    if err != nil {
        println("Error executing compiler", err.String())
        return
    }

    if output != "" {
        println("Error compiling web application")
        println(output)
        return
    }

    //generate runner.go

    runnerSrc := path.Join(datadir, "runner.go")
    runnerObj := path.Join(datadir, "runner."+ext)

    writeTemplate(runnertmpl, map[string]string{"app": app, "address": address}, runnerSrc)

    output, err = getOutput(compiler, []string{"-o", runnerObj, "-I", datadir, runnerSrc})

    if err != nil {
        println("Error Compiling", runnerSrc, err.String())
        return
    }

    if output != "" {
        println("Error compiling runner application")
        println(output)
        return
    }

    //link the web program

    obj := path.Join(cwd, app)
    output, err = getOutput(linker, []string{"-o", obj, runnerObj, appObj})

    if err != nil {
        println("Error Linking", err.String())
        return
    }

    if output != "" {
        println("Error linking")
        println(output)
        return
    }

    pid, err := os.ForkExec(obj, []string{}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})

    if err == nil {
        println("Serving on address", address)
    }

    waitchan := make(chan int, 0)

    go waitProcess(waitchan, pid)

    select {
    case _ = <-waitchan:
        println("Server process terminated")
    }
}

func waitProcess(waitchan chan int, pid int) {
    os.Wait(pid, 0)
    waitchan <- 0
}

func clean(inifile string) {
    cwd := os.Getenv("PWD")
    inifile = path.Join(cwd, inifile)
    datadir := path.Join(cwd, "data/")

    config, err := ini.ParseFile(inifile)

    if err != nil {
        println("Error parsing config file", err.String())
        return
    }

    app := config["main"]["application"]

    if len(app) == 0 {
        println("Invalid application name")
        return
    }

    obj := path.Join(cwd, app)

    if exists(obj) {
        println("Removing", obj)
        pid, _ := os.ForkExec("/bin/rm", []string{"/bin/rm", obj}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})
        os.Wait(pid, 0)
    }

    if exists(datadir) {
        println("Removing", datadir)
        pid, _ := os.ForkExec("/bin/rm", []string{"/bin/rm", "-rf", datadir}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})
        os.Wait(pid, 0)
    }
}

func main() {
    if len(os.Args) <= 1 {
        printHelp()
        os.Exit(0)
    }
    inifile := "default.ini"
    command := os.Args[1]

    switch command {
    case "create":
        create(os.Args[2])

    case "serve":
        if len(os.Args) == 3 {
            inifile = os.Args[2]
        }
        serve(inifile)

    case "clean":
        if len(os.Args) == 3 {
            inifile = os.Args[2]
        }
        clean(inifile)

    case "help":
        printHelp()

    default:
        printHelp()
    }
}

var apptmpl = `package {{app}}

import (
  //"web";
)

var Routes = map[string] interface {} {
  "/(.*)" : hello,
}

func hello (val string) string {
 return "hello "+val;
}
`

var initmpl = `[main]
application = {{app}}
bind_address = 0.0.0.0
port = 9999
`
var runnertmpl = `package main

import (
        "{{app}}";
        "web";
)

func main() {
        web.Run({{app}}.Routes, "{{address}}");
}

`
<commit_msg>Update 'webgo create' to create files consistent with the new parser<commit_after>package main

import (
    "bytes"
    "fmt"
    "ini"
    "io"
    "io/ioutil"
    "os"
    "path"
    "template"
)

var toolext = map[string]string{"386": "8", "amd64": "6", "arm": "5"}

func writeTemplate(tmplString string, data interface{}, filename string) os.Error {
    var err os.Error
    tmpl := template.New(nil)
    tmpl.SetDelims("{{", "}}")

    if err = tmpl.Parse(tmplString); err != nil {
        return err
    }

    var buf bytes.Buffer

    tmpl.Execute(data, &buf)

    if err := ioutil.WriteFile(filename, buf.Bytes(), 0644); err != nil {
        return err
    }

    return nil
}

func printHelp() { println("Commands: create, serve") }

func exists(path string) bool {
    _, err := os.Lstat(path)
    return err == nil
}

func create(name string) {
    cwd := os.Getenv("PWD")
    projectDir := path.Join(cwd, name)

    if exists(projectDir) {
        println("Project directory already exists")
        os.Exit(0)
    }

    println("Creating directory ", projectDir)
    if err := os.Mkdir(projectDir, 0744); err != nil {
        println(err.String())
        os.Exit(0)
    }

    appfile := path.Join(projectDir, name+".go")
    println("Creating application file", appfile)
    writeTemplate(apptmpl, map[string]string{"app": name}, appfile)

    inifile := path.Join(projectDir, "default.ini")
    println("Creating config file", inifile)
    writeTemplate(initmpl, map[string]string{"app": name}, inifile)

}

func getOutput(command string, args []string) (string, os.Error) {
    r, w, err := os.Pipe()
    if err != nil {
        return "", err
    }
    args2 := make([]string, len(args)+1)
    args2[0] = command
    copy(args2[1:], args)
    pid, err := os.ForkExec(command, args2, os.Environ(), "", []*os.File{nil, w, w})

    if err != nil {
        return "", err
    }

    w.Close()

    var b bytes.Buffer
    io.Copy(&b, r)
    output := b.String()
    os.Wait(pid, 0)

    return output, nil
}

func serve(inifile string) {
    cwd := os.Getenv("PWD")
    inifile = path.Join(cwd, inifile)
    datadir := path.Join(cwd, "data/")

    if !exists(datadir) {
        if err := os.Mkdir(datadir, 0744); err != nil {
            println(err.String())
            return
        }
    }

    config, err := ini.ParseFile(inifile)

    if err != nil {
        println("Error parsing config", err.String())
        return
    }

    app := config["main"]["application"]

    println("Serving application", app)

    address := fmt.Sprintf("%s:%s", config["main"]["bind_address"], config["main"]["port"])
    gobin := os.Getenv("GOBIN")
    goarch := os.Getenv("GOARCH")
    ext := toolext[goarch]
    compiler := path.Join(gobin, ext+"g")
    linker := path.Join(gobin, ext+"l")

    appSrc := path.Join(cwd, app+".go")
    appObj := path.Join(datadir, app+"."+ext)

    output, err := getOutput(compiler, []string{"-o", appObj, appSrc})

    if err != nil {
        println("Error executing compiler", err.String())
        return
    }

    if output != "" {
        println("Error compiling web application")
        println(output)
        return
    }

    //generate runner.go

    runnerSrc := path.Join(datadir, "runner.go")
    runnerObj := path.Join(datadir, "runner."+ext)

    writeTemplate(runnertmpl, map[string]string{"app": app, "address": address}, runnerSrc)

    output, err = getOutput(compiler, []string{"-o", runnerObj, "-I", datadir, runnerSrc})

    if err != nil {
        println("Error Compiling", runnerSrc, err.String())
        return
    }

    if output != "" {
        println("Error compiling runner application")
        println(output)
        return
    }

    //link the web program

    obj := path.Join(cwd, app)
    output, err = getOutput(linker, []string{"-o", obj, runnerObj, appObj})

    if err != nil {
        println("Error Linking", err.String())
        return
    }

    if output != "" {
        println("Error linking")
        println(output)
        return
    }

    pid, err := os.ForkExec(obj, []string{}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})

    if err == nil {
        println("Serving on address", address)
    }

    waitchan := make(chan int, 0)

    go waitProcess(waitchan, pid)

    select {
    case _ = <-waitchan:
        println("Server process terminated")
    }
}

func waitProcess(waitchan chan int, pid int) {
    os.Wait(pid, 0)
    waitchan <- 0
}

func clean(inifile string) {
    cwd := os.Getenv("PWD")
    inifile = path.Join(cwd, inifile)
    datadir := path.Join(cwd, "data/")

    config, err := ini.ParseFile(inifile)

    if err != nil {
        println("Error parsing config file", err.String())
        return
    }

    app := config["main"]["application"]

    if len(app) == 0 {
        println("Invalid application name")
        return
    }

    obj := path.Join(cwd, app)

    if exists(obj) {
        println("Removing", obj)
        pid, _ := os.ForkExec("/bin/rm", []string{"/bin/rm", obj}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})
        os.Wait(pid, 0)
    }

    if exists(datadir) {
        println("Removing", datadir)
        pid, _ := os.ForkExec("/bin/rm", []string{"/bin/rm", "-rf", datadir}, os.Environ(), "", []*os.File{nil, os.Stdout, os.Stdout})
        os.Wait(pid, 0)
    }
}

func main() {
    if len(os.Args) <= 1 {
        printHelp()
        os.Exit(0)
    }
    inifile := "default.ini"
    command := os.Args[1]

    switch command {
    case "create":
        create(os.Args[2])

    case "serve":
        if len(os.Args) == 3 {
            inifile = os.Args[2]
        }
        serve(inifile)

    case "clean":
        if len(os.Args) == 3 {
            inifile = os.Args[2]
        }
        clean(inifile)

    case "help":
        printHelp()

    default:
        printHelp()
    }
}

var apptmpl = `package {{app}}

import (
    "fmt"
)

var Routes = map[string]interface{}{
    "/(.*)": hello,
}

func hello(val string) string {
    return fmt.Sprintf("hello %s", val)
}
`

var initmpl = `[main]
application = {{app}}
bind_address = 0.0.0.0
port = 9999
`

var runnertmpl = `package main

import (
    "{{app}}"
    "web"
)

func main() { web.Run({{app}}.Routes, "{{address}}") }
`
<|endoftext|>


<commit_before>package xj2go

import (
	"encoding/xml"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

// XJ define xj2go struct
type XJ struct {
	d *xml.Decoder
}

type leafNode struct {
	path  string
	value interface{}
}

type strctNode struct {
	Name string
	Type string
	Tag  string
}

var (
	re    *regexp.Regexp
	strct map[string][]strctNode
	exist map[string]bool
)

// New return a xj2go instance
func New(filename string) *XJ {
	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
		return nil
	}

	return &XJ{
		d: xml.NewDecoder(file),
	}
}

// XMLToStruct convert xml to go struct and write this struct to a go file
func (xj *XJ) XMLToStruct(filename, pkg string) {
	m, _ := xj.xmlToMap("", nil)
	l := &[]leafNode{}
	xj.leafNodes("", "", m, l, false)
	// for _, v := range *l {
	// 	fmt.Println(v.path)
	// }
	paths := xj.leafPaths(*l)
	// TODO: not work well
	strct := xj.pathsToNodes(paths)

	if ok, _ := pathExists(filename); ok {
		if err := os.Remove(filename); err != nil {
			log.Fatal(err)
		}
	}

	file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// s := "package " + pkg + "\n\n"
	file.WriteString("package " + pkg + "\n\n")
	for root, snodes := range strct {
		// s += "type " + strings.Title(root) + " struct {\n"
		file.WriteString("type " + strings.Title(root) + " struct {\n")
		for i := 0; i < len(snodes); i++ {
			typ := snodes[i].Type
			if typ != "string" {
				typ = strings.Title(snodes[i].Type)
			}

			// s += "\t" + strings.Title(snodes[i].Name) + "\t" + typ + "\t" + snodes[i].Tag + "\n"
			file.WriteString("\t" + strings.Title(snodes[i].Name) + "\t" + typ + "\t" + snodes[i].Tag + "\n")
		}
		// s += "}\n"
		file.WriteString("}\n")
	}
	file.WriteString("\n")
	cmd := exec.Command("go", "fmt", filename)
	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
	// log.Println(s)
}
<commit_msg>add mkdir logic for generating<commit_after>package xj2go

import (
	"encoding/xml"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

// XJ define xj2go struct
type XJ struct {
	d *xml.Decoder
}

type leafNode struct {
	path  string
	value interface{}
}

type strctNode struct {
	Name string
	Type string
	Tag  string
}

var (
	re    *regexp.Regexp
	strct map[string][]strctNode
	exist map[string]bool
)

// New return a xj2go instance
func New(filename string) *XJ {
	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
		return nil
	}

	return &XJ{
		d: xml.NewDecoder(file),
	}
}

// XMLToStruct convert xml to go struct and write this struct to a go file
func (xj *XJ) XMLToStruct(filename, pkg string) {
	m, _ := xj.xmlToMap("", nil)
	l := &[]leafNode{}
	xj.leafNodes("", "", m, l, false)
	// for _, v := range *l {
	// 	fmt.Println(v.path)
	// }
	paths := xj.leafPaths(*l)
	// TODO: not work well
	strct := xj.pathsToNodes(paths)

	if ok, _ := pathExists(pkg); !ok {
		os.Mkdir(pkg, 0755)
	}

	if ok, _ := pathExists(filename); ok {
		if err := os.Remove(filename); err != nil {
			log.Fatal(err)
		}
	}

	file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// s := "package " + pkg + "\n\n"
	file.WriteString("package " + pkg + "\n\n")
	for root, snodes := range strct {
		// s += "type " + strings.Title(root) + " struct {\n"
		file.WriteString("type " + strings.Title(root) + " struct {\n")
		for i := 0; i < len(snodes); i++ {
			typ := snodes[i].Type
			if typ != "string" {
				typ = strings.Title(snodes[i].Type)
			}

			// s += "\t" + strings.Title(snodes[i].Name) + "\t" + typ + "\t" + snodes[i].Tag + "\n"
			file.WriteString("\t" + strings.Title(snodes[i].Name) + "\t" + typ + "\t" + snodes[i].Tag + "\n")
		}
		// s += "}\n"
		file.WriteString("}\n")
	}
	file.WriteString("\n")
	cmd := exec.Command("go", "fmt", filename)
	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
	// log.Println(s)
}
<|endoftext|>


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

package xurls

import "regexp"

//go:generate go run generate/tldsgen/main.go
//go:generate go run generate/regexgen/main.go

const (
	letter    = `\p{L}`
	number    = `\p{N}`
	iriChar   = letter + number
	pathChar  = iriChar + `/\-+_@|&=#~*%.,:;'?!` + `\p{Sc}\p{Sk}\p{So}`
	endChar   = iriChar + `/\-+_@&~*%` + `\p{Sc}`
	octet     = `(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
	ipv4Addr  = `\b` + octet + `\.` + octet + `\.` + octet + `\.` + octet + `\b`
	ipv6Addr  = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr    = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri       = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
	domain    = `(` + iri + `\.)+`
	hostName  = `(` + domain + gtld + `|` + ipAddr + `)`
	wellParen = `\([` + pathChar + `]*(\([` + pathChar + `]*\)[` + pathChar + `]*)*\)`
	pathCont  = `([` + pathChar + `]*(` + wellParen + `|[` + endChar + `])+)+`
	path      = `(/|/` + pathCont + `?|\b|$)`
	port      = `(:[0-9]*)?`
	webURL    = hostName + port + path
	email     = `[a-zA-Z0-9._%\-+]+@` + hostName

	comScheme = `[a-zA-Z][a-zA-Z.\-+]*://`
	scheme    = `(` + comScheme + `|` + otherScheme + `)`
	strict    = `\b` + scheme + pathCont
	relaxed   = strict + `|` + webURL + `|` + email
)

var (
	// Relaxed matches all the urls it can find
	Relaxed = regexp.MustCompile(relaxed)
	// Strict only matches urls with a scheme to avoid false positives
	Strict = regexp.MustCompile(strict)
)

func init() {
	Relaxed.Longest()
	Strict.Longest()
}

// StrictMatching produces a regexp that matches urls like Strict but matching
// a specified scheme regular expression
func StrictMatching(schemeExp string) (*regexp.Regexp, error) {
	strictMatching := `\b(` + schemeExp + `)` + pathCont
	re, err := regexp.Compile(strictMatching)
	if err != nil {
		return nil, err
	}
	re.Longest()
	return re, nil
}
<commit_msg>Remove @ as a valid end character<commit_after>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import "regexp"

//go:generate go run generate/tldsgen/main.go
//go:generate go run generate/regexgen/main.go

const (
	letter    = `\p{L}`
	number    = `\p{N}`
	iriChar   = letter + number
	pathChar  = iriChar + `/\-+_@|&=#~*%.,:;'?!` + `\p{Sc}\p{Sk}\p{So}`
	endChar   = iriChar + `/\-+_&~*%` + `\p{Sc}`
	octet     = `(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
	ipv4Addr  = `\b` + octet + `\.` + octet + `\.` + octet + `\.` + octet + `\b`
	ipv6Addr  = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr    = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri       = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
	domain    = `(` + iri + `\.)+`
	hostName  = `(` + domain + gtld + `|` + ipAddr + `)`
	wellParen = `\([` + pathChar + `]*(\([` + pathChar + `]*\)[` + pathChar + `]*)*\)`
	pathCont  = `([` + pathChar + `]*(` + wellParen + `|[` + endChar + `])+)+`
	path      = `(/|/` + pathCont + `?|\b|$)`
	port      = `(:[0-9]*)?`
	webURL    = hostName + port + path
	email     = `[a-zA-Z0-9._%\-+]+@` + hostName

	comScheme = `[a-zA-Z][a-zA-Z.\-+]*://`
	scheme    = `(` + comScheme + `|` + otherScheme + `)`
	strict    = `\b` + scheme + pathCont
	relaxed   = strict + `|` + webURL + `|` + email
)

var (
	// Relaxed matches all the urls it can find
	Relaxed = regexp.MustCompile(relaxed)
	// Strict only matches urls with a scheme to avoid false positives
	Strict = regexp.MustCompile(strict)
)

func init() {
	Relaxed.Longest()
	Strict.Longest()
}

// StrictMatching produces a regexp that matches urls like Strict but matching
// a specified scheme regular expression
func StrictMatching(schemeExp string) (*regexp.Regexp, error) {
	strictMatching := `\b(` + schemeExp + `)` + pathCont
	re, err := regexp.Compile(strictMatching)
	if err != nil {
		return nil, err
	}
	re.Longest()
	return re, nil
}
<|endoftext|>


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

// Package xurls extracts urls from plain text using regular expressions.
package xurls // import "mvdan.cc/xurls"

import "regexp"

//go:generate go run generate/tldsgen/main.go
//go:generate go run generate/schemesgen/main.go
//go:generate go run generate/regexgen/main.go

const (
	letter    = `\p{L}`
	mark      = `\p{M}`
	number    = `\p{N}`
	iriChar   = letter + mark + number
	currency  = `\p{Sc}`
	otherSymb = `\p{So}`
	endChar   = iriChar + `/\-+_&~*%=#` + currency + otherSymb
	otherPunc = `\p{Po}`
	midChar   = endChar + `|` + otherPunc
	wellParen = `\([` + midChar + `]*(\([` + midChar + `]*\)[` + midChar + `]*)*\)`
	wellBrack = `\[[` + midChar + `]*(\[[` + midChar + `]*\][` + midChar + `]*)*\]`
	wellBrace = `\{[` + midChar + `]*(\{[` + midChar + `]*\}[` + midChar + `]*)*\}`
	wellAll   = wellParen + `|` + wellBrack + `|` + wellBrace
	pathCont  = `([` + midChar + `]*(` + wellAll + `|[` + endChar + `])+)+`
	comScheme = `[a-zA-Z][a-zA-Z.\-+]*://`
	scheme    = `(` + comScheme + `|` + otherScheme + `)`
	stdScheme = `(` + stdSchemes + `|` + otherScheme + `)`

	iri      = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
	domain   = `(` + iri + `\.)+`
	octet    = `(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
	ipv4Addr = `\b` + octet + `\.` + octet + `\.` + octet + `\.` + octet + `\b`
	ipv6Addr = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr   = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	site     = domain + gtld
	hostName = `(` + site + `|` + ipAddr + `)`
	port     = `(:[0-9]*)?`
	path     = `(/|/` + pathCont + `?|\b|$)`
	webURL   = hostName + port + path

	strict  = `(\b` + scheme + pathCont + `)`
	relaxed = `(` + strict + `|` + webURL + `)`

	knownSchemesStrict  = `(` + stdScheme + pathCont + `)`
	knownSchemesRelaxed = `(` + knownSchemesStrict + `|` + webURL + `)`
)

var (
	// Relaxed matches all the urls it can find.
	Relaxed = regexp.MustCompile(relaxed)
	// Strict only matches urls with a scheme to avoid false positives.
	Strict = regexp.MustCompile(strict)
	// Known Schemes Relaxed matches all the urls it can find with known schemes
	KnownSchemesRelaxed = regexp.MustCompile(knownSchemesRelaxed)
	// Known Schemes Strict only matches urls with a known scheme to avoid false positives.
	KnownSchemesStrict = regexp.MustCompile(knownSchemesStrict)
)

func init() {
	Relaxed.Longest()
	Strict.Longest()
	KnownSchemesRelaxed.Longest()
	KnownSchemesStrict.Longest()
}

// StrictMatchingScheme produces a regexp that matches urls like Strict but
// whose scheme matches the given regular expression.
func StrictMatchingScheme(exp string) (*regexp.Regexp, error) {
	strictMatching := `(\b(?i)(` + exp + `)(?-i)` + pathCont + `)`
	re, err := regexp.Compile(strictMatching)
	if err != nil {
		return nil, err
	}
	re.Longest()
	return re, nil
}
<commit_msg>Hide known schemes regexes<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

// Package xurls extracts urls from plain text using regular expressions.
package xurls // import "mvdan.cc/xurls"

import "regexp"

//go:generate go run generate/tldsgen/main.go
//go:generate go run generate/schemesgen/main.go
//go:generate go run generate/regexgen/main.go

const (
	letter    = `\p{L}`
	mark      = `\p{M}`
	number    = `\p{N}`
	iriChar   = letter + mark + number
	currency  = `\p{Sc}`
	otherSymb = `\p{So}`
	endChar   = iriChar + `/\-+_&~*%=#` + currency + otherSymb
	otherPunc = `\p{Po}`
	midChar   = endChar + `|` + otherPunc
	wellParen = `\([` + midChar + `]*(\([` + midChar + `]*\)[` + midChar + `]*)*\)`
	wellBrack = `\[[` + midChar + `]*(\[[` + midChar + `]*\][` + midChar + `]*)*\]`
	wellBrace = `\{[` + midChar + `]*(\{[` + midChar + `]*\}[` + midChar + `]*)*\}`
	wellAll   = wellParen + `|` + wellBrack + `|` + wellBrace
	pathCont  = `([` + midChar + `]*(` + wellAll + `|[` + endChar + `])+)+`
	comScheme = `[a-zA-Z][a-zA-Z.\-+]*://`
	scheme    = `(` + comScheme + `|` + otherScheme + `)`
	stdScheme = `(` + stdSchemes + `|` + otherScheme + `)`

	iri      = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
	domain   = `(` + iri + `\.)+`
	octet    = `(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
	ipv4Addr = `\b` + octet + `\.` + octet + `\.` + octet + `\.` + octet + `\b`
	ipv6Addr = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr   = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	site     = domain + gtld
	hostName = `(` + site + `|` + ipAddr + `)`
	port     = `(:[0-9]*)?`
	path     = `(/|/` + pathCont + `?|\b|$)`
	webURL   = hostName + port + path

	strict  = `(\b` + scheme + pathCont + `)`
	relaxed = `(` + strict + `|` + webURL + `)`

	knownSchemesStrict  = `(` + stdScheme + pathCont + `)`
	knownSchemesRelaxed = `(` + knownSchemesStrict + `|` + webURL + `)`
)

var (
	// Relaxed matches all the urls it can find.
	Relaxed = regexp.MustCompile(relaxed)
	// Strict only matches urls with a scheme to avoid false positives.
	Strict = regexp.MustCompile(strict)
)

func init() {
	Relaxed.Longest()
	Strict.Longest()
}

// StrictMatchingScheme produces a regexp that matches urls like Strict but
// whose scheme matches the given regular expression.
func StrictMatchingScheme(exp string) (*regexp.Regexp, error) {
	strictMatching := `(\b(?i)(` + exp + `)(?-i)` + pathCont + `)`
	re, err := regexp.Compile(strictMatching)
	if err != nil {
		return nil, err
	}
	re.Longest()
	return re, nil
}
<|endoftext|>


<commit_before>package main

import (
	"camlistore.org/pkg/errorutil"
	"encoding/json"
	"fmt"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"runtime"
	"runtime/debug"
	"sort"
	"strconv"
	"strings"
	"time"
)

func zonesReader(dirName string, zones Zones) {
	for {
		zonesReadDir(dirName, zones)
		time.Sleep(5 * time.Second)
	}
}

func addHandler(zones Zones, name string, config *Zone) {
	zones[name] = config
	dns.HandleFunc(name, setupServerFunc(config))
}

func zonesReadDir(dirName string, zones Zones) error {
	dir, err := ioutil.ReadDir(dirName)
	if err != nil {
		log.Println("Could not read", dirName, ":", err)
		return err
	}

	seenZones := map[string]bool{}

	var parse_err error

	for _, file := range dir {
		fileName := file.Name()
		if !strings.HasSuffix(strings.ToLower(fileName), ".json") {
			continue
		}

		zoneName := zoneNameFromFile(fileName)

		seenZones[zoneName] = true

		if zone, ok := zones[zoneName]; !ok || file.ModTime().After(zone.LastRead) {
			if ok {
				log.Printf("Reloading %s\n", fileName)
			} else {
				logPrintf("Reading new file %s\n", fileName)
			}

			//log.Println("FILE:", i, file, zoneName)
			config, err := readZoneFile(zoneName, path.Join(dirName, fileName))
			if config == nil || err != nil {
				config.LastRead = file.ModTime()
				log.Println(err)
				parse_err = err
				continue
			}
			config.LastRead = file.ModTime()

			addHandler(zones, zoneName, config)
			runtime.GC()
		}
	}

	for zoneName, zone := range zones {
		if zoneName == "pgeodns" {
			continue
		}
		if ok, _ := seenZones[zoneName]; ok {
			continue
		}
		log.Println("Removing zone", zone.Origin)
		dns.HandleRemove(zoneName)
		delete(zones, zoneName)
	}

	return parse_err
}

func setupPgeodnsZone(zones Zones) {
	zoneName := "pgeodns"
	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)
	label := new(Label)
	label.Records = make(map[uint16]Records)
	label.Weight = make(map[uint16]int)
	Zone.Labels[""] = label
	setupSOA(Zone)
	addHandler(zones, zoneName, Zone)
}

func readZoneFile(zoneName, fileName string) (*Zone, error) {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("reading %s failed: %s", zoneName, err)
			debug.PrintStack()
		}
	}()

	fh, err := os.Open(fileName)
	if err != nil {
		log.Println("Could not read ", fileName, ": ", err)
		panic(err)
	}

	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)
	Zone.Options.Ttl = 120
	Zone.Options.MaxHosts = 2
	Zone.Options.Contact = "support.bitnames.com"

	if err == nil {
		var objmap map[string]interface{}
		decoder := json.NewDecoder(fh)
		if err = decoder.Decode(&objmap); err != nil {
			extra := ""
			if serr, ok := err.(*json.SyntaxError); ok {
				if _, serr := fh.Seek(0, os.SEEK_SET); serr != nil {
					log.Fatalf("seek error: %v", serr)
				}
				line, col, highlight := errorutil.HighlightBytePosition(fh, serr.Offset)
				extra = fmt.Sprintf(":\nError at line %d, column %d (file offset %d):\n%s",
					line, col, serr.Offset, highlight)
			}
			return nil, fmt.Errorf("error parsing JSON object in config file %s%s\n%v",
				fh.Name(), extra, err)
		}

		if err != nil {
			panic(err)
		}
		//log.Println(objmap)

		var data map[string]interface{}

		for k, v := range objmap {
			//log.Printf("k: %s v: %#v, T: %T\n", k, v, v)

			switch k {
			case "ttl", "serial", "max_hosts", "contact":
				switch option := k; option {
				case "ttl":
					Zone.Options.Ttl = valueToInt(v)
				case "serial":
					Zone.Options.Serial = valueToInt(v)
				case "contact":
					Zone.Options.Contact = v.(string)
				case "max_hosts":
					Zone.Options.MaxHosts = valueToInt(v)
				}
				continue

			case "data":
				data = v.(map[string]interface{})
			}
		}

		setupZoneData(data, Zone)

	}

	//log.Printf("ZO T: %T %s\n", Zones["0.us"], Zones["0.us"])

	//log.Println("IP", string(Zone.Regions["0.us"].IPv4[0].ip))

	return Zone, nil
}

func setupZoneData(data map[string]interface{}, Zone *Zone) {

	recordTypes := map[string]uint16{
		"a":     dns.TypeA,
		"aaaa":  dns.TypeAAAA,
		"ns":    dns.TypeNS,
		"cname": dns.TypeCNAME,
		"mx":    dns.TypeMX,
		"alias": dns.TypeMF,
	}

	for dk, dv_inter := range data {

		dv := dv_inter.(map[string]interface{})

		//log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv)

		label := Zone.AddLabel(dk)

		if ttl, ok := dv["ttl"]; ok {
			label.Ttl = valueToInt(ttl)
		}

		if maxHosts, ok := dv["max_hosts"]; ok {
			label.MaxHosts = valueToInt(maxHosts)
		}

		for rType, dnsType := range recordTypes {

			rdata := dv[rType]

			if rdata == nil {
				//log.Printf("No %s records for label %s\n", rType, dk)
				continue
			}

			//log.Printf("rdata %s TYPE-R %T\n", rdata, rdata)

			records := make(map[string][]interface{})

			switch rdata.(type) {
			case map[string]interface{}:
				// Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>]
				tmp := make([]interface{}, 0)
				for rdata_k, rdata_v := range rdata.(map[string]interface{}) {
					if rdata_v == nil {
						rdata_v = ""
					}
					tmp = append(tmp, []string{rdata_k, rdata_v.(string)})
				}
				records[rType] = tmp
			case string:
				// CNAME and alias
				tmp := make([]interface{}, 1)
				tmp[0] = rdata.(string)
				records[rType] = tmp
			default:
				records[rType] = rdata.([]interface{})
			}

			//log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records)

			label.Records[dnsType] = make(Records, len(records[rType]))

			for i := 0; i < len(records[rType]); i++ {

				//log.Printf("RT %T %#v\n", records[rType][i], records[rType][i])

				record := new(Record)

				var h dns.RR_Header
				// log.Println("TTL OPTIONS", Zone.Options.Ttl)
				h.Ttl = uint32(label.Ttl)
				h.Class = dns.ClassINET
				h.Rrtype = dnsType
				h.Name = label.Label + "." + Zone.Origin + "."

				switch dnsType {
				case dns.TypeA, dns.TypeAAAA:
					rec := records[rType][i].([]interface{})
					ip := rec[0].(string)
					var err error

					if len(rec) > 1 {
						switch rec[1].(type) {
						case string:
							record.Weight, err = strconv.Atoi(rec[1].(string))
							if err != nil {
								panic("Error converting weight to integer")
							}
						case float64:
							record.Weight = int(rec[1].(float64))
						}
					}
					switch dnsType {
					case dns.TypeA:
						if x := net.ParseIP(ip); x != nil {
							record.RR = &dns.A{Hdr: h, A: x}
							break
						}
						panic("Bad A record")
					case dns.TypeAAAA:
						if x := net.ParseIP(ip); x != nil {
							record.RR = &dns.AAAA{Hdr: h, AAAA: x}
							break
						}
						panic("Bad AAAA record")
					}

				case dns.TypeMX:
					rec := records[rType][i].(map[string]interface{})
					pref := uint16(0)
					mx := rec["mx"].(string)
					if !strings.HasSuffix(mx, ".") {
						mx = mx + "."
					}
					if rec["weight"] != nil {
						record.Weight = valueToInt(rec["weight"])
					}
					if rec["preference"] != nil {
						pref = uint16(valueToInt(rec["preference"]))
					}
					record.RR = &dns.MX{
						Hdr:        h,
						Mx:         mx,
						Preference: pref}

				case dns.TypeCNAME:
					rec := records[rType][i]
					target := rec.(string)
					if !dns.IsFqdn(target) {
						target = target + "." + Zone.Origin
					}
					record.RR = &dns.CNAME{Hdr: h, Target: dns.Fqdn(target)}

				case dns.TypeMF:
					rec := records[rType][i]
					// MF records (how we store aliases) are not FQDNs
					record.RR = &dns.MF{Hdr: h, Mf: rec.(string)}

				case dns.TypeNS:
					rec := records[rType][i]
					if h.Ttl < 86400 {
						h.Ttl = 86400
					}

					var ns string

					switch rec.(type) {
					case string:
						ns = rec.(string)
					case []string:
						recl := rec.([]string)
						ns = recl[0]
						if len(recl[1]) > 0 {
							log.Println("NS records with names syntax not supported")
						}
					default:
						log.Printf("Data: %T %#v\n", rec, rec)
						panic("Unrecognized NS format/syntax")
					}

					rr := &dns.NS{Hdr: h, Ns: dns.Fqdn(ns)}

					record.RR = rr

				default:
					log.Println("type:", rType)
					panic("Don't know how to handle this type")
				}

				if record.RR == nil {
					panic("record.RR is nil")
				}

				label.Weight[dnsType] += record.Weight
				label.Records[dnsType][i] = *record
			}
			if label.Weight[dnsType] > 0 {
				sort.Sort(RecordsByWeight{label.Records[dnsType]})
			}
		}
	}

	setupSOA(Zone)

	//log.Println(Zones[k])
}

func setupSOA(Zone *Zone) {
	label := Zone.Labels[""]

	primaryNs := "ns"

	// log.Println("LABEL", label)

	if label == nil {
		log.Println(Zone.Origin, "doesn't have any 'root' records,",
			"you should probably add some NS records")
		label = Zone.AddLabel("")
	}

	if record, ok := label.Records[dns.TypeNS]; ok {
		primaryNs = record[0].RR.(*dns.NS).Ns
	}

	s := Zone.Origin + ". 3600 IN SOA " +
		primaryNs + " " + Zone.Options.Contact + " " +
		strconv.Itoa(Zone.Options.Serial) +
		" 5400 5400 2419200 " +
		strconv.Itoa(Zone.Options.Ttl)

	// log.Println("SOA: ", s)

	rr, err := dns.NewRR(s)

	if err != nil {
		log.Println("SOA Error", err)
		panic("Could not setup SOA")
	}

	record := Record{RR: rr}

	label.Records[dns.TypeSOA] = make([]Record, 1)
	label.Records[dns.TypeSOA][0] = record

}

func valueToInt(v interface{}) (rv int) {
	switch v.(type) {
	case string:
		i, err := strconv.Atoi(v.(string))
		if err != nil {
			panic("Error converting weight to integer")
		}
		rv = i
	case float64:
		rv = int(v.(float64))
	default:
		log.Println("Can't convert", v, "to integer")
		panic("Can't convert value")
	}
	return rv
}

func zoneNameFromFile(fileName string) string {
	return fileName[0:strings.LastIndex(fileName, ".")]
}
<commit_msg>Improve error handling for bad zone data<commit_after>package main

import (
	"camlistore.org/pkg/errorutil"
	"encoding/json"
	"fmt"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"runtime"
	"runtime/debug"
	"sort"
	"strconv"
	"strings"
	"time"
)

func zonesReader(dirName string, zones Zones) {
	for {
		zonesReadDir(dirName, zones)
		time.Sleep(5 * time.Second)
	}
}

func addHandler(zones Zones, name string, config *Zone) {
	zones[name] = config
	dns.HandleFunc(name, setupServerFunc(config))
}

func zonesReadDir(dirName string, zones Zones) error {
	dir, err := ioutil.ReadDir(dirName)
	if err != nil {
		log.Println("Could not read", dirName, ":", err)
		return err
	}

	seenZones := map[string]bool{}

	var parse_err error

	for _, file := range dir {
		fileName := file.Name()
		if !strings.HasSuffix(strings.ToLower(fileName), ".json") {
			continue
		}

		zoneName := zoneNameFromFile(fileName)

		seenZones[zoneName] = true

		if zone, ok := zones[zoneName]; !ok || file.ModTime().After(zone.LastRead) {
			if ok {
				log.Printf("Reloading %s\n", fileName)
			} else {
				logPrintf("Reading new file %s\n", fileName)
			}

			//log.Println("FILE:", i, file, zoneName)
			config, err := readZoneFile(zoneName, path.Join(dirName, fileName))
			if config == nil || err != nil {
				log.Println("Caught an error")
				config.LastRead = file.ModTime()
				zones[zoneName] = config
				log.Println(err)
				parse_err = err
				continue
			}
			config.LastRead = file.ModTime()

			addHandler(zones, zoneName, config)
			runtime.GC()
		}
	}

	for zoneName, zone := range zones {
		if zoneName == "pgeodns" {
			continue
		}
		if ok, _ := seenZones[zoneName]; ok {
			continue
		}
		log.Println("Removing zone", zone.Origin)
		dns.HandleRemove(zoneName)
		delete(zones, zoneName)
	}

	return parse_err
}

func setupPgeodnsZone(zones Zones) {
	zoneName := "pgeodns"
	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)
	label := new(Label)
	label.Records = make(map[uint16]Records)
	label.Weight = make(map[uint16]int)
	Zone.Labels[""] = label
	setupSOA(Zone)
	addHandler(zones, zoneName, Zone)
}

func readZoneFile(zoneName, fileName string) (zone *Zone, zerr error) {
	defer func() {
		if r := recover(); r != nil {
			log.Printf("reading %s failed: %s", zoneName, r)
			debug.PrintStack()
			zerr = fmt.Errorf("reading %s failed: %s", zoneName, r)
		}
	}()

	fh, err := os.Open(fileName)
	if err != nil {
		log.Println("Could not read ", fileName, ": ", err)
		panic(err)
	}

	zone = new(Zone)
	zone.Labels = make(labels)
	zone.Origin = zoneName
	zone.LenLabels = dns.LenLabels(zone.Origin)
	zone.Options.Ttl = 120
	zone.Options.MaxHosts = 2
	zone.Options.Contact = "support.bitnames.com"

	if err == nil {
		var objmap map[string]interface{}
		decoder := json.NewDecoder(fh)
		if err = decoder.Decode(&objmap); err != nil {
			extra := ""
			if serr, ok := err.(*json.SyntaxError); ok {
				if _, serr := fh.Seek(0, os.SEEK_SET); serr != nil {
					log.Fatalf("seek error: %v", serr)
				}
				line, col, highlight := errorutil.HighlightBytePosition(fh, serr.Offset)
				extra = fmt.Sprintf(":\nError at line %d, column %d (file offset %d):\n%s",
					line, col, serr.Offset, highlight)
			}
			return nil, fmt.Errorf("error parsing JSON object in config file %s%s\n%v",
				fh.Name(), extra, err)
		}

		if err != nil {
			panic(err)
		}
		//log.Println(objmap)

		var data map[string]interface{}

		for k, v := range objmap {
			//log.Printf("k: %s v: %#v, T: %T\n", k, v, v)

			switch k {
			case "ttl", "serial", "max_hosts", "contact":
				switch option := k; option {
				case "ttl":
					zone.Options.Ttl = valueToInt(v)
				case "serial":
					zone.Options.Serial = valueToInt(v)
				case "contact":
					zone.Options.Contact = v.(string)
				case "max_hosts":
					zone.Options.MaxHosts = valueToInt(v)
				}
				continue

			case "data":
				data = v.(map[string]interface{})
			}
		}

		setupZoneData(data, zone)

	}

	//log.Printf("ZO T: %T %s\n", Zones["0.us"], Zones["0.us"])

	//log.Println("IP", string(Zone.Regions["0.us"].IPv4[0].ip))

	return zone, nil
}

func setupZoneData(data map[string]interface{}, Zone *Zone) {

	recordTypes := map[string]uint16{
		"a":     dns.TypeA,
		"aaaa":  dns.TypeAAAA,
		"ns":    dns.TypeNS,
		"cname": dns.TypeCNAME,
		"mx":    dns.TypeMX,
		"alias": dns.TypeMF,
	}

	for dk, dv_inter := range data {

		dv := dv_inter.(map[string]interface{})

		//log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv)

		label := Zone.AddLabel(dk)

		if ttl, ok := dv["ttl"]; ok {
			label.Ttl = valueToInt(ttl)
		}

		if maxHosts, ok := dv["max_hosts"]; ok {
			label.MaxHosts = valueToInt(maxHosts)
		}

		for rType, dnsType := range recordTypes {

			rdata := dv[rType]

			if rdata == nil {
				//log.Printf("No %s records for label %s\n", rType, dk)
				continue
			}

			//log.Printf("rdata %s TYPE-R %T\n", rdata, rdata)

			records := make(map[string][]interface{})

			switch rdata.(type) {
			case map[string]interface{}:
				// Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>]
				tmp := make([]interface{}, 0)
				for rdata_k, rdata_v := range rdata.(map[string]interface{}) {
					if rdata_v == nil {
						rdata_v = ""
					}
					tmp = append(tmp, []string{rdata_k, rdata_v.(string)})
				}
				records[rType] = tmp
			case string:
				// CNAME and alias
				tmp := make([]interface{}, 1)
				tmp[0] = rdata.(string)
				records[rType] = tmp
			default:
				records[rType] = rdata.([]interface{})
			}

			//log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records)

			label.Records[dnsType] = make(Records, len(records[rType]))

			for i := 0; i < len(records[rType]); i++ {

				//log.Printf("RT %T %#v\n", records[rType][i], records[rType][i])

				record := new(Record)

				var h dns.RR_Header
				// log.Println("TTL OPTIONS", Zone.Options.Ttl)
				h.Ttl = uint32(label.Ttl)
				h.Class = dns.ClassINET
				h.Rrtype = dnsType
				h.Name = label.Label + "." + Zone.Origin + "."

				switch dnsType {
				case dns.TypeA, dns.TypeAAAA:
					rec := records[rType][i].([]interface{})
					ip := rec[0].(string)
					var err error

					if len(rec) > 1 {
						switch rec[1].(type) {
						case string:
							record.Weight, err = strconv.Atoi(rec[1].(string))
							if err != nil {
								panic("Error converting weight to integer")
							}
						case float64:
							record.Weight = int(rec[1].(float64))
						}
					}
					switch dnsType {
					case dns.TypeA:
						if x := net.ParseIP(ip); x != nil {
							record.RR = &dns.A{Hdr: h, A: x}
							break
						}
						panic(fmt.Errorf("Bad A record %s for %s", ip, dk))
					case dns.TypeAAAA:
						if x := net.ParseIP(ip); x != nil {
							record.RR = &dns.AAAA{Hdr: h, AAAA: x}
							break
						}
						panic(fmt.Errorf("Bad AAAA record %s for %s", ip, dk))
					}

				case dns.TypeMX:
					rec := records[rType][i].(map[string]interface{})
					pref := uint16(0)
					mx := rec["mx"].(string)
					if !strings.HasSuffix(mx, ".") {
						mx = mx + "."
					}
					if rec["weight"] != nil {
						record.Weight = valueToInt(rec["weight"])
					}
					if rec["preference"] != nil {
						pref = uint16(valueToInt(rec["preference"]))
					}
					record.RR = &dns.MX{
						Hdr:        h,
						Mx:         mx,
						Preference: pref}

				case dns.TypeCNAME:
					rec := records[rType][i]
					target := rec.(string)
					if !dns.IsFqdn(target) {
						target = target + "." + Zone.Origin
					}
					record.RR = &dns.CNAME{Hdr: h, Target: dns.Fqdn(target)}

				case dns.TypeMF:
					rec := records[rType][i]
					// MF records (how we store aliases) are not FQDNs
					record.RR = &dns.MF{Hdr: h, Mf: rec.(string)}

				case dns.TypeNS:
					rec := records[rType][i]
					if h.Ttl < 86400 {
						h.Ttl = 86400
					}

					var ns string

					switch rec.(type) {
					case string:
						ns = rec.(string)
					case []string:
						recl := rec.([]string)
						ns = recl[0]
						if len(recl[1]) > 0 {
							log.Println("NS records with names syntax not supported")
						}
					default:
						log.Printf("Data: %T %#v\n", rec, rec)
						panic("Unrecognized NS format/syntax")
					}

					rr := &dns.NS{Hdr: h, Ns: dns.Fqdn(ns)}

					record.RR = rr

				default:
					log.Println("type:", rType)
					panic("Don't know how to handle this type")
				}

				if record.RR == nil {
					panic("record.RR is nil")
				}

				label.Weight[dnsType] += record.Weight
				label.Records[dnsType][i] = *record
			}
			if label.Weight[dnsType] > 0 {
				sort.Sort(RecordsByWeight{label.Records[dnsType]})
			}
		}
	}

	setupSOA(Zone)

	//log.Println(Zones[k])
}

func setupSOA(Zone *Zone) {
	label := Zone.Labels[""]

	primaryNs := "ns"

	// log.Println("LABEL", label)

	if label == nil {
		log.Println(Zone.Origin, "doesn't have any 'root' records,",
			"you should probably add some NS records")
		label = Zone.AddLabel("")
	}

	if record, ok := label.Records[dns.TypeNS]; ok {
		primaryNs = record[0].RR.(*dns.NS).Ns
	}

	s := Zone.Origin + ". 3600 IN SOA " +
		primaryNs + " " + Zone.Options.Contact + " " +
		strconv.Itoa(Zone.Options.Serial) +
		" 5400 5400 2419200 " +
		strconv.Itoa(Zone.Options.Ttl)

	// log.Println("SOA: ", s)

	rr, err := dns.NewRR(s)

	if err != nil {
		log.Println("SOA Error", err)
		panic("Could not setup SOA")
	}

	record := Record{RR: rr}

	label.Records[dns.TypeSOA] = make([]Record, 1)
	label.Records[dns.TypeSOA][0] = record

}

func valueToInt(v interface{}) (rv int) {
	switch v.(type) {
	case string:
		i, err := strconv.Atoi(v.(string))
		if err != nil {
			panic("Error converting weight to integer")
		}
		rv = i
	case float64:
		rv = int(v.(float64))
	default:
		log.Println("Can't convert", v, "to integer")
		panic("Can't convert value")
	}
	return rv
}

func zoneNameFromFile(fileName string) string {
	return fileName[0:strings.LastIndex(fileName, ".")]
}
<|endoftext|>


<commit_before>package assert

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
)

// httpCode is a helper that returns HTTP code of the response. It returns -1 and
// an error if building a new request fails.
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
	w := httptest.NewRecorder()
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return -1, err
	}
	req.URL.RawQuery = values.Encode()
	handler(w, req)
	return w.Code, nil
}

// HTTPSuccess asserts that a specified handler returns a success status code.
//
//  assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
	if !isSuccessCode {
		Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isSuccessCode
}

// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
//  assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
	if !isRedirectCode {
		Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isRedirectCode
}

// HTTPError asserts that a specified handler returns an error status code.
//
//  assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isErrorCode := code >= http.StatusBadRequest
	if !isErrorCode {
		Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isErrorCode
}

// HTTPBody is a helper that returns HTTP body of the response. It returns
// empty string if building a new request fails.
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
	w := httptest.NewRecorder()
	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
	if err != nil {
		return ""
	}
	handler(w, req)
	return w.Body.String()
}

// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
//
//  assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	body := HTTPBody(handler, method, url, values)

	contains := strings.Contains(body, fmt.Sprint(str))
	if !contains {
		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
	}

	return contains
}

// HTTPBodyNotContains asserts that a specified handler returns a
// body that does not contain a string.
//
//  assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	body := HTTPBody(handler, method, url, values)

	contains := strings.Contains(body, fmt.Sprint(str))
	if contains {
		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
	}

	return !contains
}
<commit_msg>http_assertions: fix docs (missing methods)<commit_after>package assert

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
)

// httpCode is a helper that returns HTTP code of the response. It returns -1 and
// an error if building a new request fails.
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
	w := httptest.NewRecorder()
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return -1, err
	}
	req.URL.RawQuery = values.Encode()
	handler(w, req)
	return w.Code, nil
}

// HTTPSuccess asserts that a specified handler returns a success status code.
//
//  assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
	if !isSuccessCode {
		Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isSuccessCode
}

// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
//  assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
	if !isRedirectCode {
		Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isRedirectCode
}

// HTTPError asserts that a specified handler returns an error status code.
//
//  assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	code, err := httpCode(handler, method, url, values)
	if err != nil {
		Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
		return false
	}

	isErrorCode := code >= http.StatusBadRequest
	if !isErrorCode {
		Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
	}

	return isErrorCode
}

// HTTPBody is a helper that returns HTTP body of the response. It returns
// empty string if building a new request fails.
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
	w := httptest.NewRecorder()
	req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
	if err != nil {
		return ""
	}
	handler(w, req)
	return w.Body.String()
}

// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
//
//  assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	body := HTTPBody(handler, method, url, values)

	contains := strings.Contains(body, fmt.Sprint(str))
	if !contains {
		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
	}

	return contains
}

// HTTPBodyNotContains asserts that a specified handler returns a
// body that does not contain a string.
//
//  assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
	if h, ok := t.(tHelper); ok {
		h.Helper()
	}
	body := HTTPBody(handler, method, url, values)

	contains := strings.Contains(body, fmt.Sprint(str))
	if contains {
		Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
	}

	return !contains
}
<|endoftext|>


<commit_before>package assets

const styles = `
html, body {
    margin: 0;
    padding: 0;
}

body {
    font: 100%/1.3 Verdana, sans-serif;
    overflow-y: scroll;
}

.container {
    max-width: 40rem;
    margin: 1rem;
}

aside {
    max-width: 40rem;
    margin: 1rem 1.5rem;
}

.container:before, .container:after {
    clear: both;
    content: " ";
    display: table;
}

a {
    color: hsl(220, 51%, 44%);
}

a:hover {
    color: hsl(208, 56%, 38%);
}

header {
    margin: 0 1rem;
    font-size: 1rem;
    border-bottom: 1px solid #ddd;
}

header h1, header > a {
    margin: 0;
    padding: 1.3rem;
    height: 1.3rem;
    line-height: 1.3rem;
    display: inline-block;
}

header h1 {
    font-size: 1.5rem;
    padding-left: 0;
    margin-left: .5rem;
    font-weight: bold;
    align-self: flex-start;
}

header h1 a {
    color: #000;
    text-decoration: none;
}

.repos {
    width: auto;
    list-style: none;
    padding: 0;
    margin: 0;
}

.repos .repo {
    border-bottom: 1px dotted #ddd;
    width: auto;
}

.repos .repo:last-child {
    border-bottom: none;
}

.repo {
    margin: 1.3rem 0;
    padding: 0 .5rem;
    position: relative;
}

.repo h1 {
    font-size: 1.2rem;
}

.repo h1 a {
    text-decoration: none;
}

.repo .buttons {
    float: right;
    position: relative;
    top: -2.3rem;
    opacity: 0;
    background: white;
}

.repo:hover .buttons {
    opacity: 1;
}

.repo.private a {
    color: hsl(20, 51%, 44%);
}

.clone {
    margin: 1.3rem 0;
    background: #efefef;
    padding: 1rem;
}

.filter {
    padding: 1rem 0px;
    background: #fefefe;
    border-bottom: 1px solid #eee;
}

.filter input[type=search] {
    display: block;
    border: none;
    width: 100%;
    padding: 0 0.5rem;
    font: 1rem Verdana, Geneva, sans-serif;
    margin: 0;
    background: none repeat scroll 0% 0% transparent;
}

hr {
    margin: 1.3rem auto;
    border: none;
    height: 0;
    max-width: 10rem;
    width: 66%;
    border-bottom: 1px solid #ccc;
}

figure {
    border: 1px solid #bbb;
    margin: 1rem .5rem;
    padding: 0;
}

figure figcaption {
    border-bottom: 1px solid #ddd;
    padding: 0.65rem 0.65rem;
    margin: 0 0.65rem;
}

figure figcaption h3 {
    margin: 0;
    font-size: .75rem;
    letter-spacing: .01rem;
    font-variant: small-caps;
}

figure article {
    padding: 0.65rem 1.3rem;
}

figure article pre.full {
    padding: 0;
    background: transparent;
}

form {
    margin: 1.3rem 0.5rem;
}

input[type=text] {
    display: block;
    border: none;
    border-bottom: 1px dotted #aaa;
    margin: 0.3rem 0 1.3rem;
    width: 100%;
}

textarea {
    display: block;
    border: 1px dotted #aaa;
    margin: 0.3rem 0 1.3rem;
    width: 100%;
    max-width: 100%;
    min-width: 100%;
}

input[type=submit] {
    margin: 1rem 0;
}

label {
    color: #aaa;
    font-style: italic;
    margin: 0.3rem 0;
}

figure {
    background: white;
    color: black;
}

article {
    font: 13px/1.3 Menlo, monospace;
}

article h1:first-child {
    margin-top: 1rem;
}

article h1 {
    font-size: 16px;
    margin: 2rem 0 1rem;
}

article h2 {
    font-size: 14px;
    margin: 1.5rem 0 0.5rem;
}

article h3 {
    font-size: 13px;
    font-weight: normal;
    text-decoration: underline;
    margin: 1.5rem 0 0.5rem;
}

article ul {
    padding-left: 1.3em;
}

article p {
    margin: 1.3em 0;
}

article code {
    font-family: Menlo, monospace;
    color: rgb(90, 10, 20);
}

article pre > code {
    padding: 0;
    background: none;
    color: rgb(90, 10, 20);
}

article pre {
    padding: .7em 1.3em;
    font-family: Menlo, monospace;
    white-space: pre-wrap;
    color: rgb(90, 10, 20);
}

article pre.content {
    color: black;
    padding: 0;
}

article blockquote {
    margin-left: 0;
    padding-left: 1.3em;
    border-left: 1px dotted #aaa;
    color: #666;
}

article hr {
    border: none;
    height: 1px;
    width: 7rem;
    margin: 2.5rem 0 0.5rem;
    background: #aaa;
}

article table {
    border-spacing: collapse;
    border-collapse: collapse;
}

article th, article td {
    padding: 0.3rem 0.5rem;
    margin: 0;
}

article th {
    font-weight: bold;
    text-align: left;
    border-bottom: 1px solid #eee;
}

.files {
    list-style: none;
    padding: 0;
    margin: 0;
}

.files li {
    margin: 0 .65rem;
    padding: .65rem;
    border-bottom: 1px dotted #ddd;
    font-size: .75rem;
}

.files li:last-child {
    border-bottom: none;
}

.files .fa {
    margin-right: .3rem;
    height: 14px;
    width: 14px;
}
`
<commit_msg>Remove smallcaps in figure heading<commit_after>package assets

const styles = `
html, body {
    margin: 0;
    padding: 0;
}

body {
    font: 100%/1.3 Verdana, sans-serif;
    overflow-y: scroll;
}

.container {
    max-width: 40rem;
    margin: 1rem;
}

aside {
    max-width: 40rem;
    margin: 1rem 1.5rem;
}

.container:before, .container:after {
    clear: both;
    content: " ";
    display: table;
}

a {
    color: hsl(220, 51%, 44%);
}

a:hover {
    color: hsl(208, 56%, 38%);
}

header {
    margin: 0 1rem;
    font-size: 1rem;
    border-bottom: 1px solid #ddd;
}

header h1, header > a {
    margin: 0;
    padding: 1.3rem;
    height: 1.3rem;
    line-height: 1.3rem;
    display: inline-block;
}

header h1 {
    font-size: 1.5rem;
    padding-left: 0;
    margin-left: .5rem;
    font-weight: bold;
    align-self: flex-start;
}

header h1 a {
    color: #000;
    text-decoration: none;
}

.repos {
    width: auto;
    list-style: none;
    padding: 0;
    margin: 0;
}

.repos .repo {
    border-bottom: 1px dotted #ddd;
    width: auto;
}

.repos .repo:last-child {
    border-bottom: none;
}

.repo {
    margin: 1.3rem 0;
    padding: 0 .5rem;
    position: relative;
}

.repo h1 {
    font-size: 1.2rem;
}

.repo h1 a {
    text-decoration: none;
}

.repo .buttons {
    float: right;
    position: relative;
    top: -2.3rem;
    opacity: 0;
    background: white;
}

.repo:hover .buttons {
    opacity: 1;
}

.repo.private a {
    color: hsl(20, 51%, 44%);
}

.clone {
    margin: 1.3rem 0;
    background: #efefef;
    padding: 1rem;
}

.filter {
    padding: 1rem 0px;
    background: #fefefe;
    border-bottom: 1px solid #eee;
}

.filter input[type=search] {
    display: block;
    border: none;
    width: 100%;
    padding: 0 0.5rem;
    font: 1rem Verdana, Geneva, sans-serif;
    margin: 0;
    background: none repeat scroll 0% 0% transparent;
}

hr {
    margin: 1.3rem auto;
    border: none;
    height: 0;
    max-width: 10rem;
    width: 66%;
    border-bottom: 1px solid #ccc;
}

figure {
    border: 1px solid #bbb;
    margin: 1rem .5rem;
    padding: 0;
}

figure figcaption {
    border-bottom: 1px solid #ddd;
    padding: 0.65rem 0.65rem;
    margin: 0 0.65rem;
}

figure figcaption h3 {
    margin: 0;
    font-size: .75rem;
    letter-spacing: .01rem;
}

figure article {
    padding: 0.65rem 1.3rem;
}

figure article pre.full {
    padding: 0;
    background: transparent;
}

form {
    margin: 1.3rem 0.5rem;
}

input[type=text] {
    display: block;
    border: none;
    border-bottom: 1px dotted #aaa;
    margin: 0.3rem 0 1.3rem;
    width: 100%;
}

textarea {
    display: block;
    border: 1px dotted #aaa;
    margin: 0.3rem 0 1.3rem;
    width: 100%;
    max-width: 100%;
    min-width: 100%;
}

input[type=submit] {
    margin: 1rem 0;
}

label {
    color: #aaa;
    font-style: italic;
    margin: 0.3rem 0;
}

figure {
    background: white;
    color: black;
}

article {
    font: 13px/1.3 Menlo, monospace;
}

article h1:first-child {
    margin-top: 1rem;
}

article h1 {
    font-size: 16px;
    margin: 2rem 0 1rem;
}

article h2 {
    font-size: 14px;
    margin: 1.5rem 0 0.5rem;
}

article h3 {
    font-size: 13px;
    font-weight: normal;
    text-decoration: underline;
    margin: 1.5rem 0 0.5rem;
}

article ul {
    padding-left: 1.3em;
}

article p {
    margin: 1.3em 0;
}

article code {
    font-family: Menlo, monospace;
    color: rgb(90, 10, 20);
}

article pre > code {
    padding: 0;
    background: none;
    color: rgb(90, 10, 20);
}

article pre {
    padding: .7em 1.3em;
    font-family: Menlo, monospace;
    white-space: pre-wrap;
    color: rgb(90, 10, 20);
}

article pre.content {
    color: black;
    padding: 0;
}

article blockquote {
    margin-left: 0;
    padding-left: 1.3em;
    border-left: 1px dotted #aaa;
    color: #666;
}

article hr {
    border: none;
    height: 1px;
    width: 7rem;
    margin: 2.5rem 0 0.5rem;
    background: #aaa;
}

article table {
    border-spacing: collapse;
    border-collapse: collapse;
}

article th, article td {
    padding: 0.3rem 0.5rem;
    margin: 0;
}

article th {
    font-weight: bold;
    text-align: left;
    border-bottom: 1px solid #eee;
}

.files {
    list-style: none;
    padding: 0;
    margin: 0;
}

.files li {
    margin: 0 .65rem;
    padding: .65rem;
    border-bottom: 1px dotted #ddd;
    font-size: .75rem;
}

.files li:last-child {
    border-bottom: none;
}

.files .fa {
    margin-right: .3rem;
    height: 14px;
    width: 14px;
}
`
<|endoftext|>


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

package client

import (
	"gopkg.in/goyy/goyy.v0/data/result"
	"gopkg.in/goyy/goyy.v0/util/errors"
	"gopkg.in/goyy/goyy.v0/util/strings"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Client struct {
	URL         string
	Params      url.Values
	Header      http.Header
	Cookies     []*http.Cookie
	Timeout     int
	OnTimeout   func()
	OnError     func(error)
	OnCompleted func(*result.Client)
}

func (me *Client) DoGet() {
	me.do("GET")
}

func (me *Client) DoPost() {
	me.do("POST")
}

func (me *Client) GoGet() {
	go me.do("GET")
}

func (me *Client) GoPost() {
	go me.do("POST")
}

func (me *Client) QueueGet() {
	go me.do("GET")
}

func (me *Client) QueuePost() {
	go me.do("POST")
}

func (me *Client) onError(err error) {
	if me.OnError != nil {
		me.OnError(err)
	}
}

func (me *Client) do(method string) {
	if strings.IsBlank(me.URL) {
		me.onError(errors.NewNotBlank("URL"))
		return
	}
	client := &http.Client{}
	req, err := me.getRequest(method)
	if err != nil {
		me.onError(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		logger.Debug(err.Error())
		me.onError(err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Debug(err.Error())
		me.onError(err)
		return
	}
	if me.OnCompleted != nil {
		r := &result.Client{
			Body:       body,
			Status:     resp.Status,
			StatusCode: resp.StatusCode,
			Header:     resp.Header,
			Cookies:    resp.Cookies(),
		}
		me.OnCompleted(r)
	}
}

func (me *Client) getRequest(method string) (*http.Request, error) {
	if method == "GET" {
		url := me.URL
		if me.Params != nil {
			if strings.Contains(me.URL, "?") {
				url = me.URL + "&" + me.Params.Encode()
			} else {
				url = me.URL + "?" + me.Params.Encode()
			}
		}
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			logger.Debug(err.Error())
			return req, err
		}
		req.Header = me.Header
		for _, c := range me.Cookies {
			req.AddCookie(c)
		}
		return req, err
	} else {
		req, err := http.NewRequest("POST", me.URL, strings.NewReader(me.Params.Encode()))
		if err != nil {
			logger.Debug(err.Error())
			return req, err
		}
		req.Header = me.Header
		if strings.IsBlank(req.Header.Get("Content-Type")) {
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		}
		for _, c := range me.Cookies {
			req.AddCookie(c)
		}
		return req, err
	}
}
<commit_msg>Added response state value judgment<commit_after>// Copyright 2014 The goyy Authors.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package client

import (
	"gopkg.in/goyy/goyy.v0/data/result"
	"gopkg.in/goyy/goyy.v0/util/errors"
	"gopkg.in/goyy/goyy.v0/util/strings"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Client struct {
	URL         string
	Params      url.Values
	Header      http.Header
	Cookies     []*http.Cookie
	Timeout     int
	OnTimeout   func()
	OnError     func(error)
	OnCompleted func(*result.Client)
}

func (me *Client) DoGet() {
	me.do("GET")
}

func (me *Client) DoPost() {
	me.do("POST")
}

func (me *Client) GoGet() {
	go me.do("GET")
}

func (me *Client) GoPost() {
	go me.do("POST")
}

func (me *Client) QueueGet() {
	go me.do("GET")
}

func (me *Client) QueuePost() {
	go me.do("POST")
}

func (me *Client) onError(err error) {
	if me.OnError != nil {
		me.OnError(err)
	} else {
		panic(err.Error())
	}
}

func (me *Client) do(method string) {
	if strings.IsBlank(me.URL) {
		me.onError(errors.NewNotBlank("URL"))
		return
	}
	client := &http.Client{}
	req, err := me.getRequest(method)
	if err != nil {
		me.onError(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		logger.Debug(err.Error())
		me.onError(err)
		return
	}
	if resp.StatusCode >= 400 {
		me.onError(errors.New(resp.Status))
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Debug(err.Error())
		me.onError(err)
		return
	}
	if me.OnCompleted != nil {
		r := &result.Client{
			Body:       body,
			Status:     resp.Status,
			StatusCode: resp.StatusCode,
			Header:     resp.Header,
			Cookies:    resp.Cookies(),
		}
		me.OnCompleted(r)
	}
}

func (me *Client) getRequest(method string) (*http.Request, error) {
	if method == "GET" {
		url := me.URL
		if me.Params != nil {
			if strings.Contains(me.URL, "?") {
				url = me.URL + "&" + me.Params.Encode()
			} else {
				url = me.URL + "?" + me.Params.Encode()
			}
		}
		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			logger.Debug(err.Error())
			return req, err
		}
		req.Header = me.Header
		for _, c := range me.Cookies {
			req.AddCookie(c)
		}
		return req, err
	} else {
		req, err := http.NewRequest("POST", me.URL, strings.NewReader(me.Params.Encode()))
		if err != nil {
			logger.Debug(err.Error())
			return req, err
		}
		req.Header = me.Header
		if strings.IsBlank(req.Header.Get("Content-Type")) {
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		}
		for _, c := range me.Cookies {
			req.AddCookie(c)
		}
		return req, err
	}
}
<|endoftext|>