コード例 #1
0
ファイル: app.go プロジェクト: rainycape/governator.io
func init() {
	template.AddFuncs(template.FuncMap{
		"#config": func(name string, def string) template.HTML {
			var buf bytes.Buffer
			buf.WriteString("<h3 class=\"config\">")
			buf.WriteString(html.Escape(name))
			if def != "" {
				buf.WriteString(" <span class=\"label label-success\">optional</span>")
				fmt.Fprintf(&buf, " <span class=\"default\">default: %s</span>", html.Escape(def))
			} else {
				buf.WriteString(" <span class=\"label label-danger\">required</span>")
			}
			buf.WriteString("</h3>")
			return template.HTML(buf.String())
		}})
	config.MustParse()
	App = app.New()
	App.SetTrustXHeaders(true)

	// Redirect all other possible hosts to governator.io
	redir := app.RedirectHandler("http://governator.io${0}", true)
	App.Handle("(.*)", redir, app.HostHandler("governator-io.appspot.com"))
	App.Handle("(.*)", redir, app.HostHandler("www.governator.io"))

	App.HandleAssets("/assets/", pathutil.Relative("assets"))
	App.Handle("^/$", app.TemplateHandler("main.html", nil))
	App.Handle("^/install\\.sh$", fileHandler("contrib/install.sh"))
	App.Handle("^/get/releases/linux/x86_64/latest/governator$", fileHandler("governator"))

	App.Handle("^/contrib/(.*)", func(ctx *app.Context) {
		path := filepath.Join(data, "contrib", filepath.FromSlash(ctx.IndexValue(0)))
		serveFile(ctx, path)
	})
}
コード例 #2
0
ファイル: format.go プロジェクト: rainycape/gondola
func FormatNode(fset *token.FileSet, node interface{}) (string, error) {
	var buf bytes.Buffer
	if err := printer.Fprint(&buf, fset, node); err != nil {
		return "", err
	}
	escaped := html.Escape(buf.String())
	return FormatComments(escaped), nil
}
コード例 #3
0
ファイル: repr.go プロジェクト: rainycape/gondola
func descRepr(p uint64, val *reflect.Value, _html bool) string {
	var typeName string
	isInterface := val != nil && val.Kind() == reflect.Interface
	if isInterface {
		typeName = html.Escape(fmt.Sprintf("%T", val.Interface()))
	}
	ptr := fmt.Sprintf("0x%x", p)
	if val != nil && _html {
		title := fmt.Sprintf("%+v", val.Interface())
		if isInterface {
			return fmt.Sprintf("@ %s(<abbr title=\"%s\">%s</abbr>)", typeName, html.Escape(title), ptr)
		}
		return fmt.Sprintf("@ <abbr title=\"%s\">%s</abbr>", html.Escape(title), ptr)
	}
	if isInterface {
		return fmt.Sprintf("@ %s(%s)", typeName, ptr)
	}
	return fmt.Sprintf("@ %s", ptr)
}
コード例 #4
0
ファイル: form.go プロジェクト: rainycape/gondola
func (f *Form) endLabel(buf *bytes.Buffer, field *Field, label string, pos int) error {
	buf.WriteString(html.Escape(label))
	f.closeTag(buf, "label")
	if f.renderer != nil {
		if err := f.renderer.EndLabel(buf, field, pos); err != nil {
			return err
		}
	}
	return nil
}
コード例 #5
0
ファイル: form.go プロジェクト: rainycape/gondola
func (f *Form) writeInput(buf *bytes.Buffer, itype string, field *Field) error {
	if err := f.beginInput(buf, field, -1); err != nil {
		return err
	}
	attrs := html.Attrs{
		"id":   field.Id(),
		"type": itype,
		"name": field.HTMLName,
	}
	if err := f.prepareFieldAttributes(field, attrs, -1); err != nil {
		return err
	}
	switch field.Type {
	case CHECKBOX:
		if t, ok := types.IsTrue(field.value.Interface()); t && ok {
			attrs["checked"] = "checked"
		}
	case TEXT, PASSWORD, EMAIL, HIDDEN:
		attrs["value"] = html.Escape(types.ToString(field.Value()))
		if field.Placeholder != "" {
			attrs["placeholder"] = html.Escape(field.Placeholder.TranslatedString(f.ctx))
		}
		if ml, ok := field.Tag().MaxLength(); ok {
			attrs["maxlength"] = strconv.Itoa(ml)
		}
	case FILE:
	default:
		panic("unreachable")
	}
	f.openTag(buf, "input", attrs)
	if field.Type == CHECKBOX {
		// Close the label before calling EndInput
		if err := f.endLabel(buf, field, field.Label.TranslatedString(f.ctx), -1); err != nil {
			return err
		}
	}
	if err := f.endInput(buf, field, -1); err != nil {
		return err
	}
	return nil
}
コード例 #6
0
ファイル: repr.go プロジェクト: rainycape/gondola
func valRepr(s *gosym.Sym, typ reflect.Type, values []string, _html bool) (r string) {
	val, _ := strconv.ParseUint(values[0], 0, 64)
	var val2 uint64
	if len(values) > 1 {
		val2, _ = strconv.ParseUint(values[1], 0, 64)
	}
	// If there's a panic prettyfy'ing the value just
	// assume it's a pointer. It's better than
	// omitting the error page.
	defer func() {
		if recover() != nil {
			r = pointerRepr(nil, val, false)
		}
	}()
	switch types.Kind(typ.Kind()) {
	case types.Bool:
		if val == 0 {
			return "= false"
		}
		return "= true"
	case types.Int:
		return "= " + strconv.FormatInt(int64(val), 10)
	case types.Uint:
		return "= " + strconv.FormatUint(val, 10)
	case types.Float:
		if typ.Kind() == reflect.Float32 {
			return "= " + strconv.FormatFloat(float64(math.Float32frombits(uint32(val))), 'g', -1, 32)
		}
		return "= " + strconv.FormatFloat(math.Float64frombits(uint64(val)), 'g', -1, 64)
	case types.Slice:
		return sliceRepr(val, val2, s)
	case types.String:
		v := stringRepr(val, val2)
		if _html {
			v = html.Escape(v)
		}
		return v
	case types.Interface:
		if typ.NumMethod() == 0 {
			return emptyInterfaceRepr(val, val2)
		}
		idata := [2]uintptr{uintptr(val), uintptr(val2)}
		v := reflect.NewAt(typ, unsafe.Pointer(&idata[0])).Elem()
		return descRepr(val, &v, _html)
	case types.Func:
		fn := reflect.NewAt(typ, unsafe.Pointer(&val)).Elem()
		f := runtime.FuncForPC(fn.Pointer())
		if f != nil {
			return "= " + f.Name()
		}
	}
	return pointerRepr(typ, val, _html)
}
コード例 #7
0
ファイル: form.go プロジェクト: rainycape/gondola
func toHTMLValue(val interface{}) string {
	v := reflect.ValueOf(val)
	if v.IsValid() {
		for v.Kind() == reflect.Ptr {
			v = v.Elem()
		}
		if v.IsValid() {
			// Avoid enum types with a String() method to be represented
			// as a string. Use their numeric representation.
			k := types.Kind(v.Kind())
			if k == types.Int {
				return strconv.FormatInt(v.Int(), 10)
			}
			if k == types.Uint {
				return strconv.FormatUint(v.Uint(), 10)
			}
		}
	}
	return html.Escape(types.ToString(val))
}
コード例 #8
0
ファイル: runtime.go プロジェクト: rainycape/gondola
func formatSource(filename string, line int, count int, numbers bool, highlight bool, _html bool) (string, error) {
	begin := line - count - 1
	count = count*2 + 1
	if begin < 0 {
		count += begin
		begin = 0
	}
	source, err := stringutil.FileLines(filename, begin, count, false)
	if err != nil {
		return "", err
	}

	var format string
	if numbers {
		// Line numbers start at 1
		begin++
		maxLen := len(strconv.Itoa(begin + count))
		format = fmt.Sprintf("%%%dd: %%s", maxLen)
	}
	slines := strings.Split(source, "\n")
	for ii, v := range slines {
		if numbers {
			v = fmt.Sprintf(format, begin, v)
		}
		if _html {
			v = html.Escape(v)
		}
		if highlight && begin == line {
			if _html {
				v = fmt.Sprintf("<span class=\"current\">%s</span>", v)
			} else {
				v += " <==="
			}
		}
		slines[ii] = v
		begin++
	}
	return strings.Join(slines, "\n"), nil
}
コード例 #9
0
ファイル: form.go プロジェクト: rainycape/gondola
func (f *Form) writeField(buf *bytes.Buffer, field *Field) error {
	var closed bool
	if field.Type != HIDDEN {
		closed = field.Type != CHECKBOX
		label := field.Label.TranslatedString(f.ctx)
		if err := f.writeLabel(buf, field, field.Id(), label, closed, -1); err != nil {
			return err
		}
	}
	var err error
	switch field.Type {
	case TEXT:
		err = f.writeInput(buf, "text", field)
	case PASSWORD:
		err = f.writeInput(buf, "password", field)
	case EMAIL:
		err = f.writeInput(buf, "email", field)
	case HIDDEN:
		err = f.writeInput(buf, "hidden", field)
	case FILE:
		err = f.writeInput(buf, "file", field)
	case TEXTAREA:
		attrs := html.Attrs{
			"id":   field.Id(),
			"name": field.HTMLName,
		}
		if _, ok := field.Tag().IntValue("rows"); ok {
			attrs["rows"] = field.Tag().Value("rows")
		}
		if err := f.prepareFieldAttributes(field, attrs, -1); err != nil {
			return err
		}
		f.openTag(buf, "textarea", attrs)
		buf.WriteString(toHTMLValue(field.Value()))
		f.closeTag(buf, "textarea")
	case CHECKBOX:
		err = f.writeInput(buf, "checkbox", field)
	case RADIO:
		for ii, v := range f.fieldChoices(field) {
			var value interface{}
			id := fmt.Sprintf("%s_%d", field.Id(), ii)
			if err := f.writeLabel(buf, field, id, v.TranslatedName(f.ctx), false, ii); err != nil {
				return err
			}
			if err := f.beginInput(buf, field, ii); err != nil {
				return err
			}
			attrs := html.Attrs{
				"id":   id,
				"name": field.HTMLName,
				"type": "radio",
			}
			if v.Value != nil {
				attrs["value"] = toHTMLValue(v.Value)
				value = v.Value
			} else {
				value = v.Name
			}
			if reflect.DeepEqual(value, field.Value()) {
				attrs["checked"] = "checked"
			}
			if err := f.prepareFieldAttributes(field, attrs, ii); err != nil {
				return err
			}
			f.openTag(buf, "input", attrs)
			if err := f.endLabel(buf, field, v.TranslatedName(f.ctx), ii); err != nil {
				return err
			}
			if err := f.endInput(buf, field, ii); err != nil {
				return err
			}
		}
	case SELECT:
		attrs := html.Attrs{
			"id":   field.Id(),
			"name": field.HTMLName,
		}
		if field.Tag().Has("multiple") {
			attrs["multiple"] = "multiple"
		}
		if err := f.prepareFieldAttributes(field, attrs, -1); err != nil {
			return err
		}
		f.openTag(buf, "select", attrs)
		for ii, v := range f.fieldChoices(field) {
			var value interface{}
			oattrs := html.Attrs{}
			if v.Value != nil {
				oattrs["value"] = toHTMLValue(v.Value)
				value = v.Value
			} else {
				value = v.Name
			}
			if reflect.DeepEqual(value, field.Value()) {
				oattrs["selected"] = "selected"
			}
			if err := f.prepareFieldAttributes(field, attrs, ii); err != nil {
				return err
			}
			f.openTag(buf, "option", oattrs)
			buf.WriteString(html.Escape(v.TranslatedName(f.ctx)))
			f.closeTag(buf, "option")
		}
		f.closeTag(buf, "select")
	}
	return err
}
コード例 #10
0
ファイル: funcs.go プロジェクト: rainycape/gondola
func toHtml(s string) template.HTML {
	return template.HTML(strings.Replace(html.Escape(s), "\n", "<br>", -1))
}
コード例 #11
0
ファイル: source.go プロジェクト: rainycape/gondola
func SourceHandler(ctx *app.Context) {
	dctx := doc.GetEnvironment(ctx.App())
	rel := ctx.IndexValue(0)
	p := dctx.FromSlash(rel)
	pDir := dctx.Dir(p)
	if pDir == "." {
		pDir = p
	} else {

	}
	dir := packageDir(dctx, pDir)
	filePath := dir
	if pDir+dctx.Separator != p && pDir != p {
		filePath = dctx.Join(dir, dctx.Base(p))
	}
	log.Debugf("Loading source from %s", filePath)
	var breadcrumbs []*breadcrumb
	for ii := 0; ii < len(rel); {
		var end int
		slash := strings.IndexByte(rel[ii:], '/')
		if slash < 0 {
			end = len(rel)
		} else {
			end = ii + slash
		}
		breadcrumbs = append(breadcrumbs, &breadcrumb{
			Title: rel[ii:end],
			Href:  ctx.MustReverse(SourceHandlerName, rel[:end]),
		})
		ii = end + 1
	}
	var tmpl string
	var title string
	var files []string
	var code template.HTML
	var lines []int
	if dctx.IsDir(filePath) {
		if rel != "" && rel[len(rel)-1] != '/' {
			ctx.MustRedirectReverse(true, SourceHandlerName, rel+"/")
			return
		}
		contents, err := dctx.ReadDir(filePath)
		if err != nil {
			panic(err)
		}
		for _, v := range contents {
			if n := v.Name(); len(n) > 0 && n[0] != '.' {
				files = append(files, n)
			}
		}
		title = "Directory " + dctx.Base(rel)
		tmpl = "dir.html"
	} else {
		f, err := dctx.OpenFile(filePath)
		if err != nil {
			ctx.NotFound("File not found")
			return
		}
		defer f.Close()
		contents, err := ioutil.ReadAll(f)
		if err != nil {
			panic(err)
		}
		contentType := http.DetectContentType(contents)
		if !strings.HasPrefix(contentType, "text") {
			ctx.Header().Set("Content-Type", contentType)
			switch contentType {
			case "image/gif", "image/png", "image/jpeg":
			default:
				ctx.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s;", dctx.Base(rel)))
			}
			ctx.Write(contents)
			return
		}
		title = "File " + dctx.Base(rel)
		var buf bytes.Buffer
		buf.WriteString("<span id=\"line-1\">")
		last := 0
		line := 1
		for ii, v := range contents {
			if v == '\n' {
				buf.WriteString(html.Escape(string(contents[last:ii])))
				lines = append(lines, line)
				last = ii
				line++
				buf.WriteString(fmt.Sprintf("</span><span id=\"line-%d\">", line))
			}
		}
		buf.Write(contents[last:])
		buf.WriteString("</span>")
		code = template.HTML(buf.String())
		tmpl = "source.html"
	}
	data := map[string]interface{}{
		"Title":       rel,
		"Header":      title,
		"Breadcrumbs": breadcrumbs,
		"Files":       files,
		"Code":        code,
		"Lines":       lines,
		"Padding":     math.Ceil(math.Log10(float64(len(lines)+1))) + 0.1,
		"Highlighter": highlighters[path.Ext(rel)],
	}
	ctx.MustExecute(tmpl, data)
}