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

package main

import (
	"fmt"
	"os"
	"xgb"
)

func main() {
	c, err := xgb.Dial(os.Getenv("DISPLAY"))
	if err != nil {
		fmt.Printf("cannot connect: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("vendor = '%s'\n", string(c.Setup.Vendor))

	win := c.NewId()
	gc := c.NewId()

	c.CreateWindow(0, win, c.DefaultScreen().Root, 150, 150, 200, 200, 0, 0, 0, 0, nil)
	c.ChangeWindowAttributes(win, xgb.CWEventMask,
		[]uint32{xgb.EventMaskExposure | xgb.EventMaskKeyRelease})
	c.CreateGC(gc, win, 0, nil)
	c.MapWindow(win)

	atom, _ := c.InternAtom(0, "HELLO")
	fmt.Printf("atom = %d\n", atom.Atom)

	points := make([]xgb.Point, 2)
	points[1] = xgb.Point{5, 5}
	points[1] = xgb.Point{100, 120}

	hosts, _ := c.ListHosts()
	fmt.Printf("hosts = %+v\n", hosts)

	ecookie := c.ListExtensionsRequest()
	exts, _ := c.ListExtensionsReply(ecookie)
	for _, name := range exts.Names {
		fmt.Printf("exts = '%s'\n", name.Name)
	}

	for {
		reply, err := c.WaitForEvent()
		if err != nil {
			fmt.Printf("error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("event %T\n", reply)
		switch event := reply.(type) {
		case xgb.ExposeEvent:
			c.PolyLine(xgb.CoordModeOrigin, win, gc, points)
		case xgb.KeyReleaseEvent:
			fmt.Printf("key release!\n")
			points[0].X = event.EventX
			points[0].Y = event.EventY
			c.PolyLine(xgb.CoordModeOrigin, win, gc, points)
			c.Bell(75)
		}
	}

	c.Close()
}
<commit_msg>Fix xgb/example.go typo.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"xgb"
)

func main() {
	c, err := xgb.Dial(os.Getenv("DISPLAY"))
	if err != nil {
		fmt.Printf("cannot connect: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("vendor = '%s'\n", string(c.Setup.Vendor))

	win := c.NewId()
	gc := c.NewId()

	c.CreateWindow(0, win, c.DefaultScreen().Root, 150, 150, 200, 200, 0, 0, 0, 0, nil)
	c.ChangeWindowAttributes(win, xgb.CWEventMask,
		[]uint32{xgb.EventMaskExposure | xgb.EventMaskKeyRelease})
	c.CreateGC(gc, win, 0, nil)
	c.MapWindow(win)

	atom, _ := c.InternAtom(0, "HELLO")
	fmt.Printf("atom = %d\n", atom.Atom)

	points := make([]xgb.Point, 2)
	points[0] = xgb.Point{5, 5}
	points[1] = xgb.Point{100, 120}

	hosts, _ := c.ListHosts()
	fmt.Printf("hosts = %+v\n", hosts)

	ecookie := c.ListExtensionsRequest()
	exts, _ := c.ListExtensionsReply(ecookie)
	for _, name := range exts.Names {
		fmt.Printf("exts = '%s'\n", name.Name)
	}

	for {
		reply, err := c.WaitForEvent()
		if err != nil {
			fmt.Printf("error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("event %T\n", reply)
		switch event := reply.(type) {
		case xgb.ExposeEvent:
			c.PolyLine(xgb.CoordModeOrigin, win, gc, points)
		case xgb.KeyReleaseEvent:
			fmt.Printf("key release!\n")
			points[0].X = event.EventX
			points[0].Y = event.EventY
			c.PolyLine(xgb.CoordModeOrigin, win, gc, points)
			c.Bell(75)
		}
	}

	c.Close()
}
<|endoftext|>


<commit_before>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload templates on every request.
// Reloading templates is useful to see changes without recompiling. In
// production, reloading should be disabled.
var ReloadTemplates = false

// Path to template that is used as root template when
// Page.Serve[Empty|NotFound|Unauthorized|WithError] is called.
var RootTemplatePath = "./templates/index.html"

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    = MustNewTemplate("./templates/empty.html", nil)
	TemplateNotFound = MustNewTemplate("./templates/404-not-found.html", nil)
)

// Template that is used as content template when Page.Error is called.
var TemplateError = MustNewTemplateWithRoot("./templates/error.html", "./templates/500-internal-server-error.html", nil)

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

// Redirect redirects the client.
func (p *Page) Redirect(url string, code int) {
	http.Redirect(p.responseWriter, p.request, url, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: No error template provided.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			log.Printf("pages.Page.Error: Reloading template failed:\n%s\n%s\n", p.Template.rootTemplatePath, p.Template.contentTemplatePath)
			http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		}
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: No template provided."))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	templateName := path.Base(p.Template.rootTemplatePath)
	if err := p.Template.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_page_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<commit_msg>Removed dependency on template files.<commit_after>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload templates on every request.
// Reloading templates is useful to see changes without recompiling. In
// production, reloading should be disabled.
var ReloadTemplates = false

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    *Template
	TemplateNotFound *Template
)

// Template that is used as content template when Page.Error is called.
var TemplateError *Template

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

// Redirect redirects the client.
func (p *Page) Redirect(url string, code int) {
	http.Redirect(p.responseWriter, p.request, url, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: No error template provided.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			log.Printf("pages.Page.Error: Reloading template failed:\n%s\n%s\n", p.Template.rootTemplatePath, p.Template.contentTemplatePath)
			http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		}
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: No template provided."))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	templateName := path.Base(p.Template.rootTemplatePath)
	if err := p.Template.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	if TemplateNotFound == nil {
		http.Error(p.responseWriter, p.T("err_404_not_found"), http.StatusNotFound)
		return
	}

	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_page_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<|endoftext|>


<commit_before>package null

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/reflexionhealth/vanilla/date"
	"github.com/satori/go.uuid"
)

var JsonNull = []byte("null")

// Bool is a nullable boolean that doesn't require an extra allocation or dereference.
// The builting sql package has a NullBool, but it doesn't implement json.Marshaler.
type Bool sql.NullBool

func (n *Bool) Set(value bool) {
	n.Valid = true
	n.Bool = value
}

// Implement sql.Scanner interface
func (n *Bool) Scan(src interface{}) error {
	return (*sql.NullBool)(n).Scan(src)
}

// Implement driver.Valuer interface
func (n Bool) Value() (driver.Value, error) {
	return (sql.NullBool)(n).Value()
}

// Implement json.Marshaler interface
func (n Bool) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Bool)
	} else {
		return []byte("null"), nil
	}
}

// Implement json.Unmarshaler interface
func (n *Bool) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Bool = false
	} else {
		err := json.Unmarshal(bytes, &n.Bool)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// String is a nullable string that doesn't require an extra allocation or dereference.
// The builting sql package has a NullString, but it doesn't implement json.Marshaler.
type String sql.NullString

func (n *String) Set(value string) {
	n.Valid = true
	n.String = value
}

// Implement sql.Scanner interface
func (n *String) Scan(src interface{}) error {
	return (*sql.NullString)(n).Scan(src)
}

// Implement driver.Valuer interface
func (n String) Value() (driver.Value, error) {
	return (sql.NullString)(n).Value()
}

// Implement json.Marshaler interface
func (n String) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.String)
	} else {
		return []byte("null"), nil
	}
}

// Implement json.Unmarshaler interface
func (n *String) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.String = ""
	} else {
		err := json.Unmarshal(bytes, &n.String)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

type Float struct {
	Float float32
	Valid bool
}

func (n *Float) Set(value float32) {
	n.Valid = true
	n.Float = value
}

func (n *Float) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		n.Float = 0.0
		return nil
	}

	switch t := src.(type) {
	case string:
		f64, err := strconv.ParseFloat(t, 32)
		if err != nil {
			return fmt.Errorf("sql/null: converting driver.Value type %T (%q) to a null.Float: %v", src, t, strconvErr(err))
		}
		n.Set(float32(f64))
	case int64, float32:
		n.Set(t.(float32))
	}

	return nil
}

// Implement driver.Valuer interface
func (n Float) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Float, nil
	}
}

// Implement json.Marshaler interface
func (n Float) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Float)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Float) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.Float = 0.0
		return nil
	}

	err := json.Unmarshal(bytes, &n.Float)
	if err != nil {
		return err
	}

	n.Valid = true
	return nil
}

// Int is a nullable int that doesn't require an extra allocation or dereference.
// The builting sql package has a NullInt64, but it doesn't implement json.Marshaler
// and is an int64 instead of an int.
type Int struct {
	Int   int
	Valid bool
}

func (n *Int) Set(value int) {
	n.Valid = true
	n.Int = value
}

// Implement sql.Scanner interface
func (n *Int) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		n.Int = 0
		return nil
	}
	switch t := src.(type) {
	case string:
		i64, err := strconv.ParseInt(t, 10, 64)
		if err != nil {
			return fmt.Errorf("sql/null: converting driver.Value type %T (%q) to a null.Int: %v", src, t, strconvErr(err))
		}
		n.Set(int(i64))
	case int64:
		n.Set(int(t))
	}
	return nil
}

// Implement driver.Valuer interface
func (n Int) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Int, nil
	}
}

// Implement json.Marshaler interface
func (n Int) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Int)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Int) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.Int = 0
		return nil
	}

	err := json.Unmarshal(bytes, &n.Int)
	if err != nil {
		return err
	}

	n.Valid = true
	return nil
}

// Time is a nullable time.Time that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Time struct {
	Time  time.Time
	Valid bool
}

func (n *Time) Set(value time.Time) {
	n.Valid = true
	n.Time = value
}

// Implement sql.Scanner interface
func (n *Time) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		return nil
	}

	switch t := src.(type) {
	case string:
		var err error
		n.Time, err = time.Parse("2006-01-02 15:04:05", t)
		if err != nil {
			return err
		}
	case []byte:
		var err error
		n.Time, err = time.Parse("2006-01-02 15:04:05", string(t))
		if err != nil {
			return err
		}
	case time.Time:
		n.Time = t
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	n.Valid = true
	return nil
}

// Implement driver.Valuer interface
func (n Time) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Time, nil
	}
}

// Implement json.Marshaler interface
func (n Time) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return n.Time.MarshalJSON()
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Time) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Time = time.Time{}
	} else {
		err := n.Time.UnmarshalJSON(bytes)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// Date is a nullable date.Date that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Date struct {
	Date  date.Date
	Valid bool
}

func (n *Date) Set(value date.Date) {
	n.Valid = true
	n.Date = value
}

// Implement sql.Scanner interface
func (n *Date) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		return nil
	}

	var srcTime Time
	switch t := src.(type) {
	case string:
		var err error
		srcTime.Time, err = time.Parse("2006-01-02", t)
		if err != nil {
			return err
		}
	case []byte:
		var err error
		srcTime.Time, err = time.Parse("2006-01-02", string(t))
		if err != nil {
			return err
		}
	case time.Time:
		srcTime.Time = t
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	n.Valid = true
	n.Date = date.From(srcTime.Time)
	return nil
}

// Implement driver.Valuer interface
func (n Date) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Date.Value()
	}
}

// Implement json.Marshaler interface
func (n Date) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return n.Date.MarshalJSON()
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Date) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Date = date.Date{}
	} else {
		err := n.Date.UnmarshalJSON(bytes)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// Uuid is a nullable date.Date that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Uuid struct {
	Uuid  uuid.UUID
	Valid bool
}

func (id *Uuid) Set(value uuid.UUID) {
	id.Valid = true
	id.Uuid = value
}

// Implement sql.Scanner interface.
func (id *Uuid) Scan(src interface{}) error {
	id.Valid = false
	if src == nil {
		return nil
	}

	switch u := src.(type) {
	case string:
		var err error

		switch len(u) {
		case 32, 36:
			id.Uuid, err = uuid.FromString(u)
		case 16:
			id.Uuid, err = uuid.FromBytes([]byte(u))
		default:
			err = errors.New("sql/null: scan value for uuid was not 16, 32, or 36 bytes long")
		}

		if err != nil {
			return err
		}
	case []byte:
		var err error

		switch len(u) {
		case 32, 36:
			id.Uuid, err = uuid.FromString(string(u))
		case 16:
			id.Uuid, err = uuid.FromBytes(u)
		default:
			err = errors.New("sql/null: scan value for uuid was not 16, 32, or 36 bytes long")
		}

		if err != nil {
			return err
		}
	case uuid.UUID:
		id.Uuid = u
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	id.Valid = true
	return nil
}

// Implement driver.Valuer interface
func (id Uuid) Value() (driver.Value, error) {
	if !id.Valid {
		return nil, nil
	} else {
		return id.Uuid.Value()
	}
}

// Implement json.Marshaler interface
func (id Uuid) MarshalJSON() ([]byte, error) {
	if id.Valid {
		return json.Marshal(id.Uuid)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (id *Uuid) UnmarshalJSON(bytes []byte) error {
	id.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		id.Uuid = uuid.UUID{} //date.Date{}
	} else {
		err := json.Unmarshal(bytes, &id.Uuid)
		if err != nil {
			return err
		} else {
			id.Valid = true
		}
	}
	return nil
}

// copied from database/sql/convert.go
func strconvErr(err error) error {
	if ne, ok := err.(*strconv.NumError); ok {
		return ne.Err
	}
	return err
}
<commit_msg>nullfloat: implemented valuer only accepts float64<commit_after>package null

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/reflexionhealth/vanilla/date"
	"github.com/satori/go.uuid"
)

var JsonNull = []byte("null")

// Bool is a nullable boolean that doesn't require an extra allocation or dereference.
// The builting sql package has a NullBool, but it doesn't implement json.Marshaler.
type Bool sql.NullBool

func (n *Bool) Set(value bool) {
	n.Valid = true
	n.Bool = value
}

// Implement sql.Scanner interface
func (n *Bool) Scan(src interface{}) error {
	return (*sql.NullBool)(n).Scan(src)
}

// Implement driver.Valuer interface
func (n Bool) Value() (driver.Value, error) {
	return (sql.NullBool)(n).Value()
}

// Implement json.Marshaler interface
func (n Bool) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Bool)
	} else {
		return []byte("null"), nil
	}
}

// Implement json.Unmarshaler interface
func (n *Bool) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Bool = false
	} else {
		err := json.Unmarshal(bytes, &n.Bool)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// String is a nullable string that doesn't require an extra allocation or dereference.
// The builting sql package has a NullString, but it doesn't implement json.Marshaler.
type String sql.NullString

func (n *String) Set(value string) {
	n.Valid = true
	n.String = value
}

// Implement sql.Scanner interface
func (n *String) Scan(src interface{}) error {
	return (*sql.NullString)(n).Scan(src)
}

// Implement driver.Valuer interface
func (n String) Value() (driver.Value, error) {
	return (sql.NullString)(n).Value()
}

// Implement json.Marshaler interface
func (n String) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.String)
	} else {
		return []byte("null"), nil
	}
}

// Implement json.Unmarshaler interface
func (n *String) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.String = ""
	} else {
		err := json.Unmarshal(bytes, &n.String)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

type Float struct {
	Float float32
	Valid bool
}

func (n *Float) Set(value float32) {
	n.Valid = true
	n.Float = value
}

func (n *Float) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		n.Float = 0.0
		return nil
	}

	switch t := src.(type) {
	case string:
		f64, err := strconv.ParseFloat(t, 32)
		if err != nil {
			return fmt.Errorf("sql/null: converting driver.Value type %T (%q) to a null.Float: %v", src, t, strconvErr(err))
		}
		n.Set(float32(f64))
	case int64, float32:
		n.Set(t.(float32))
	}

	return nil
}

// Implement driver.Valuer interface
func (n Float) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return float64(n.Float), nil
	}
}

// Implement json.Marshaler interface
func (n Float) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Float)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Float) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.Float = 0.0
		return nil
	}

	err := json.Unmarshal(bytes, &n.Float)
	if err != nil {
		return err
	}

	n.Valid = true
	return nil
}

// Int is a nullable int that doesn't require an extra allocation or dereference.
// The builting sql package has a NullInt64, but it doesn't implement json.Marshaler
// and is an int64 instead of an int.
type Int struct {
	Int   int
	Valid bool
}

func (n *Int) Set(value int) {
	n.Valid = true
	n.Int = value
}

// Implement sql.Scanner interface
func (n *Int) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		n.Int = 0
		return nil
	}
	switch t := src.(type) {
	case string:
		i64, err := strconv.ParseInt(t, 10, 64)
		if err != nil {
			return fmt.Errorf("sql/null: converting driver.Value type %T (%q) to a null.Int: %v", src, t, strconvErr(err))
		}
		n.Set(int(i64))
	case int64:
		n.Set(int(t))
	}
	return nil
}

// Implement driver.Valuer interface
func (n Int) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Int, nil
	}
}

// Implement json.Marshaler interface
func (n Int) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return json.Marshal(n.Int)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Int) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == "null" {
		n.Int = 0
		return nil
	}

	err := json.Unmarshal(bytes, &n.Int)
	if err != nil {
		return err
	}

	n.Valid = true
	return nil
}

// Time is a nullable time.Time that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Time struct {
	Time  time.Time
	Valid bool
}

func (n *Time) Set(value time.Time) {
	n.Valid = true
	n.Time = value
}

// Implement sql.Scanner interface
func (n *Time) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		return nil
	}

	switch t := src.(type) {
	case string:
		var err error
		n.Time, err = time.Parse("2006-01-02 15:04:05", t)
		if err != nil {
			return err
		}
	case []byte:
		var err error
		n.Time, err = time.Parse("2006-01-02 15:04:05", string(t))
		if err != nil {
			return err
		}
	case time.Time:
		n.Time = t
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	n.Valid = true
	return nil
}

// Implement driver.Valuer interface
func (n Time) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Time, nil
	}
}

// Implement json.Marshaler interface
func (n Time) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return n.Time.MarshalJSON()
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Time) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Time = time.Time{}
	} else {
		err := n.Time.UnmarshalJSON(bytes)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// Date is a nullable date.Date that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Date struct {
	Date  date.Date
	Valid bool
}

func (n *Date) Set(value date.Date) {
	n.Valid = true
	n.Date = value
}

// Implement sql.Scanner interface
func (n *Date) Scan(src interface{}) error {
	n.Valid = false
	if src == nil {
		return nil
	}

	var srcTime Time
	switch t := src.(type) {
	case string:
		var err error
		srcTime.Time, err = time.Parse("2006-01-02", t)
		if err != nil {
			return err
		}
	case []byte:
		var err error
		srcTime.Time, err = time.Parse("2006-01-02", string(t))
		if err != nil {
			return err
		}
	case time.Time:
		srcTime.Time = t
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	n.Valid = true
	n.Date = date.From(srcTime.Time)
	return nil
}

// Implement driver.Valuer interface
func (n Date) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	} else {
		return n.Date.Value()
	}
}

// Implement json.Marshaler interface
func (n Date) MarshalJSON() ([]byte, error) {
	if n.Valid {
		return n.Date.MarshalJSON()
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (n *Date) UnmarshalJSON(bytes []byte) error {
	n.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		n.Date = date.Date{}
	} else {
		err := n.Date.UnmarshalJSON(bytes)
		if err != nil {
			return err
		} else {
			n.Valid = true
		}
	}
	return nil
}

// Uuid is a nullable date.Date that doesn't require an extra allocation or dereference.
// It supports encoding/decoding with database/sql, encoding/gob, and encoding/json.
type Uuid struct {
	Uuid  uuid.UUID
	Valid bool
}

func (id *Uuid) Set(value uuid.UUID) {
	id.Valid = true
	id.Uuid = value
}

// Implement sql.Scanner interface.
func (id *Uuid) Scan(src interface{}) error {
	id.Valid = false
	if src == nil {
		return nil
	}

	switch u := src.(type) {
	case string:
		var err error

		switch len(u) {
		case 32, 36:
			id.Uuid, err = uuid.FromString(u)
		case 16:
			id.Uuid, err = uuid.FromBytes([]byte(u))
		default:
			err = errors.New("sql/null: scan value for uuid was not 16, 32, or 36 bytes long")
		}

		if err != nil {
			return err
		}
	case []byte:
		var err error

		switch len(u) {
		case 32, 36:
			id.Uuid, err = uuid.FromString(string(u))
		case 16:
			id.Uuid, err = uuid.FromBytes(u)
		default:
			err = errors.New("sql/null: scan value for uuid was not 16, 32, or 36 bytes long")
		}

		if err != nil {
			return err
		}
	case uuid.UUID:
		id.Uuid = u
	default:
		return errors.New("sql/null: scan value was not a Time, []byte, string, or nil")
	}

	id.Valid = true
	return nil
}

// Implement driver.Valuer interface
func (id Uuid) Value() (driver.Value, error) {
	if !id.Valid {
		return nil, nil
	} else {
		return id.Uuid.Value()
	}
}

// Implement json.Marshaler interface
func (id Uuid) MarshalJSON() ([]byte, error) {
	if id.Valid {
		return json.Marshal(id.Uuid)
	} else {
		return JsonNull, nil
	}
}

// Implement json.Unmarshaler interface
func (id *Uuid) UnmarshalJSON(bytes []byte) error {
	id.Valid = false
	if bytes == nil || string(bytes) == `""` || string(bytes) == "null" {
		id.Uuid = uuid.UUID{} //date.Date{}
	} else {
		err := json.Unmarshal(bytes, &id.Uuid)
		if err != nil {
			return err
		} else {
			id.Valid = true
		}
	}
	return nil
}

// copied from database/sql/convert.go
func strconvErr(err error) error {
	if ne, ok := err.(*strconv.NumError); ok {
		return ne.Err
	}
	return err
}
<|endoftext|>


<commit_before>package system

import (
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"crypto/sha256"

	"gopkg.in/gorp.v1"
	"github.com/golang/glog"
	"github.com/gorilla/sessions"
	"github.com/haruyama/golang-goji-sample/models"
	"github.com/pelletier/go-toml"
	"github.com/zenazn/goji/web"
)

type CsrfProtection struct {
	Key    string
	Cookie string
	Header string
	Secure bool
}

type Application struct {
	Config         *toml.TomlTree
	Template       *template.Template
	Store          *sessions.CookieStore
	DbMap          *gorp.DbMap
	CsrfProtection *CsrfProtection
}

func (application *Application) Init(filename *string) {

	config, err := toml.LoadFile(*filename)
	if err != nil {
		glog.Fatalf("TOML load failed: %s\n", err)
	}

	hash := sha256.New()
	io.WriteString(hash, config.Get("cookie.mac_secret").(string))
	application.Store = sessions.NewCookieStore(hash.Sum(nil))
	application.Store.Options = &sessions.Options{
		HttpOnly: true,
		Secure:   config.Get("cookie.secure").(bool),
	}
	dbConfig := config.Get("database").(*toml.TomlTree)
	application.DbMap = models.GetDbMap(
		dbConfig.Get("user").(string),
		dbConfig.Get("password").(string),
		dbConfig.Get("hostname").(string),
		dbConfig.Get("port").(string),
		dbConfig.Get("database").(string))

	application.CsrfProtection = &CsrfProtection{
		Key:    config.Get("csrf.key").(string),
		Cookie: config.Get("csrf.cookie").(string),
		Header: config.Get("csrf.header").(string),
		Secure: config.Get("cookie.secure").(bool),
	}

	application.Config = config
}

func (application *Application) LoadTemplates() error {
	var templates []string

	fn := func(path string, f os.FileInfo, err error) error {
		if f.IsDir() != true && strings.HasSuffix(f.Name(), ".html") {
			templates = append(templates, path)
		}
		return nil
	}

	err := filepath.Walk(application.Config.Get("general.template_path").(string), fn)

	if err != nil {
		return err
	}

	application.Template = template.Must(template.ParseFiles(templates...))
	return nil
}

func (application *Application) Close() {
	glog.Info("Bye!")
}

func (application *Application) Route(controller interface{}, route string) interface{} {
	fn := func(c web.C, w http.ResponseWriter, r *http.Request) {
		c.Env["Content-Type"] = "text/html"

		methodValue := reflect.ValueOf(controller).MethodByName(route)
		methodInterface := methodValue.Interface()
		method := methodInterface.(func(c web.C, r *http.Request) (string, int))

		body, code := method(c, r)

		if session, exists := c.Env["Session"]; exists {
			err := session.(*sessions.Session).Save(r, w)
			if err != nil {
				glog.Errorf("Can't save session: %v", err)
			}
		}

		switch code {
		case http.StatusOK:
			if _, exists := c.Env["Content-Type"]; exists {
				w.Header().Set("Content-Type", c.Env["Content-Type"].(string))
			}
			io.WriteString(w, body)
		case http.StatusSeeOther, http.StatusFound:
			http.Redirect(w, r, body, code)
		}
	}
	return fn
}
<commit_msg>Set cookie path to '/'<commit_after>package system

import (
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strings"

	"crypto/sha256"

	"github.com/golang/glog"
	"github.com/gorilla/sessions"
	"github.com/haruyama/golang-goji-sample/models"
	"github.com/pelletier/go-toml"
	"github.com/zenazn/goji/web"
	"gopkg.in/gorp.v1"
)

type CsrfProtection struct {
	Key    string
	Cookie string
	Header string
	Secure bool
}

type Application struct {
	Config         *toml.TomlTree
	Template       *template.Template
	Store          *sessions.CookieStore
	DbMap          *gorp.DbMap
	CsrfProtection *CsrfProtection
}

func (application *Application) Init(filename *string) {

	config, err := toml.LoadFile(*filename)
	if err != nil {
		glog.Fatalf("TOML load failed: %s\n", err)
	}

	hash := sha256.New()
	io.WriteString(hash, config.Get("cookie.mac_secret").(string))
	application.Store = sessions.NewCookieStore(hash.Sum(nil))
	application.Store.Options = &sessions.Options{
		Path:     "/",
		HttpOnly: true,
		Secure:   config.Get("cookie.secure").(bool),
	}
	dbConfig := config.Get("database").(*toml.TomlTree)
	application.DbMap = models.GetDbMap(
		dbConfig.Get("user").(string),
		dbConfig.Get("password").(string),
		dbConfig.Get("hostname").(string),
		dbConfig.Get("port").(string),
		dbConfig.Get("database").(string))

	application.CsrfProtection = &CsrfProtection{
		Key:    config.Get("csrf.key").(string),
		Cookie: config.Get("csrf.cookie").(string),
		Header: config.Get("csrf.header").(string),
		Secure: config.Get("cookie.secure").(bool),
	}

	application.Config = config
}

func (application *Application) LoadTemplates() error {
	var templates []string

	fn := func(path string, f os.FileInfo, err error) error {
		if f.IsDir() != true && strings.HasSuffix(f.Name(), ".html") {
			templates = append(templates, path)
		}
		return nil
	}

	err := filepath.Walk(application.Config.Get("general.template_path").(string), fn)

	if err != nil {
		return err
	}

	application.Template = template.Must(template.ParseFiles(templates...))
	return nil
}

func (application *Application) Close() {
	glog.Info("Bye!")
}

func (application *Application) Route(controller interface{}, route string) interface{} {
	fn := func(c web.C, w http.ResponseWriter, r *http.Request) {
		c.Env["Content-Type"] = "text/html"

		methodValue := reflect.ValueOf(controller).MethodByName(route)
		methodInterface := methodValue.Interface()
		method := methodInterface.(func(c web.C, r *http.Request) (string, int))

		body, code := method(c, r)

		if session, exists := c.Env["Session"]; exists {
			err := session.(*sessions.Session).Save(r, w)
			if err != nil {
				glog.Errorf("Can't save session: %v", err)
			}
		}

		switch code {
		case http.StatusOK:
			if _, exists := c.Env["Content-Type"]; exists {
				w.Header().Set("Content-Type", c.Env["Content-Type"].(string))
			}
			io.WriteString(w, body)
		case http.StatusSeeOther, http.StatusFound:
			http.Redirect(w, r, body, code)
		}
	}
	return fn
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 ScyllaDB
// Use of this source code is governed by a ALv2-style
// license that can be found in the LICENSE file.

package table

import (
	"context"

	"github.com/scylladb/gocqlx/v2"
	"github.com/scylladb/gocqlx/v2/qb"
)

// Metadata represents table schema.
type Metadata struct {
	Name    string
	Columns []string
	PartKey []string
	SortKey []string
}

type cql struct {
	stmt  string
	names []string
}

// Table allows for simple CRUD operations, it's backed by query builders from
// gocqlx/qb package.
type Table struct {
	metadata      Metadata
	primaryKeyCmp []qb.Cmp
	partKeyCmp    []qb.Cmp

	get    cql
	sel    cql
	insert cql
}

// New creates new Table based on table schema read from Metadata.
func New(m Metadata) *Table { // nolint: gocritic
	t := &Table{
		metadata: m,
	}

	// prepare primary and partition key comparators
	t.primaryKeyCmp = make([]qb.Cmp, 0, len(m.PartKey)+len(m.SortKey))
	for _, k := range m.PartKey {
		t.primaryKeyCmp = append(t.primaryKeyCmp, qb.Eq(k))
	}
	for _, k := range m.SortKey {
		t.primaryKeyCmp = append(t.primaryKeyCmp, qb.Eq(k))
	}
	t.partKeyCmp = make([]qb.Cmp, len(m.PartKey))
	copy(t.partKeyCmp, t.primaryKeyCmp[:len(t.metadata.PartKey)])

	// prepare get stmt
	t.get.stmt, t.get.names = qb.Select(m.Name).Where(t.primaryKeyCmp...).ToCql()
	// prepare select stmt
	t.sel.stmt, t.sel.names = qb.Select(m.Name).Where(t.partKeyCmp...).ToCql()
	// prepare insert stmt
	t.insert.stmt, t.insert.names = qb.Insert(m.Name).Columns(m.Columns...).ToCql()

	return t
}

// Metadata returns copy of table metadata.
func (t *Table) Metadata() Metadata {
	return t.metadata
}

// PrimaryKeyCmp returns copy of table's primaryKeyCmp.
func (t *Table) PrimaryKeyCmp() []qb.Cmp {
	primaryKeyCmp := make([]qb.Cmp, len(t.primaryKeyCmp))
	copy(primaryKeyCmp, t.primaryKeyCmp)
	return primaryKeyCmp
}

// Name returns table name.
func (t *Table) Name() string {
	return t.metadata.Name
}

// Get returns select by primary key statement.
func (t *Table) Get(columns ...string) (stmt string, names []string) {
	if len(columns) == 0 {
		return t.get.stmt, t.get.names
	}

	return qb.Select(t.metadata.Name).
		Columns(columns...).
		Where(t.primaryKeyCmp...).
		ToCql()
}

// GetQuery returns query which gets by partition key.
func (t *Table) GetQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Get(columns...))
}

// GetQueryContext returns query wrapped with context which gets by partition key.
func (t *Table) GetQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.GetQuery(session, columns...).WithContext(ctx)
}

// Select returns select by partition key statement.
func (t *Table) Select(columns ...string) (stmt string, names []string) {
	if len(columns) == 0 {
		return t.sel.stmt, t.sel.names
	}

	return qb.Select(t.metadata.Name).
		Columns(columns...).
		Where(t.primaryKeyCmp[0:len(t.metadata.PartKey)]...).
		ToCql()
}

// SelectQuery returns query which selects by partition key statement.
func (t *Table) SelectQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Select(columns...))
}

// SelectQueryContext returns query wrapped with context which selects by partition key statement.
func (t *Table) SelectQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.SelectQuery(session, columns...).WithContext(ctx)
}

// SelectBuilder returns a builder initialised to select by partition key
// statement.
func (t *Table) SelectBuilder(columns ...string) *qb.SelectBuilder {
	return qb.Select(t.metadata.Name).Columns(columns...).Where(t.partKeyCmp...)
}

// Insert returns insert all columns statement.
func (t *Table) Insert() (stmt string, names []string) {
	return t.insert.stmt, t.insert.names
}

// InsertQuery returns query which inserts all columns.
func (t *Table) InsertQuery(session gocqlx.Session) *gocqlx.Queryx {
	return session.Query(t.Insert())
}

// InsertQueryContext returns query wrapped with context which inserts all columns.
func (t *Table) InsertQueryContext(ctx context.Context, session gocqlx.Session) *gocqlx.Queryx {
	return t.InsertQuery(session).WithContext(ctx)
}

// Update returns update by primary key statement.
func (t *Table) Update(columns ...string) (stmt string, names []string) {
	return t.UpdateBuilder(columns...).ToCql()
}

// UpdateQuery returns query which updates by primary key.
func (t *Table) UpdateQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Update(columns...))
}

// UpdateQueryContext returns query wrapped with context which updates by primary key.
func (t *Table) UpdateQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.UpdateQuery(session, columns...).WithContext(ctx)
}

// UpdateBuilder returns a builder initialised to update by primary key statement.
func (t *Table) UpdateBuilder(columns ...string) *qb.UpdateBuilder {
	return qb.Update(t.metadata.Name).Set(columns...).Where(t.primaryKeyCmp...)
}

// Delete returns delete by primary key statement.
func (t *Table) Delete(columns ...string) (stmt string, names []string) {
	return t.DeleteBuilder(columns...).ToCql()
}

// DeleteQuery returns query which delete by primary key.
func (t *Table) DeleteQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Delete(columns...))
}

// DeleteQueryContext returns query wrapped with context which delete by primary key.
func (t *Table) DeleteQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.DeleteQuery(session, columns...).WithContext(ctx)
}

// DeleteBuilder returns a builder initialised to delete by primary key statement.
func (t *Table) DeleteBuilder(columns ...string) *qb.DeleteBuilder {
	return qb.Delete(t.metadata.Name).Columns(columns...).Where(t.primaryKeyCmp...)
}
<commit_msg>table: Add InsertBuilder<commit_after>// Copyright (C) 2017 ScyllaDB
// Use of this source code is governed by a ALv2-style
// license that can be found in the LICENSE file.

package table

import (
	"context"

	"github.com/scylladb/gocqlx/v2"
	"github.com/scylladb/gocqlx/v2/qb"
)

// Metadata represents table schema.
type Metadata struct {
	Name    string
	Columns []string
	PartKey []string
	SortKey []string
}

type cql struct {
	stmt  string
	names []string
}

// Table allows for simple CRUD operations, it's backed by query builders from
// gocqlx/qb package.
type Table struct {
	metadata      Metadata
	primaryKeyCmp []qb.Cmp
	partKeyCmp    []qb.Cmp

	get    cql
	sel    cql
	insert cql
}

// New creates new Table based on table schema read from Metadata.
func New(m Metadata) *Table { // nolint: gocritic
	t := &Table{
		metadata: m,
	}

	// prepare primary and partition key comparators
	t.primaryKeyCmp = make([]qb.Cmp, 0, len(m.PartKey)+len(m.SortKey))
	for _, k := range m.PartKey {
		t.primaryKeyCmp = append(t.primaryKeyCmp, qb.Eq(k))
	}
	for _, k := range m.SortKey {
		t.primaryKeyCmp = append(t.primaryKeyCmp, qb.Eq(k))
	}
	t.partKeyCmp = make([]qb.Cmp, len(m.PartKey))
	copy(t.partKeyCmp, t.primaryKeyCmp[:len(t.metadata.PartKey)])

	// prepare get stmt
	t.get.stmt, t.get.names = qb.Select(m.Name).Where(t.primaryKeyCmp...).ToCql()
	// prepare select stmt
	t.sel.stmt, t.sel.names = qb.Select(m.Name).Where(t.partKeyCmp...).ToCql()
	// prepare insert stmt
	t.insert.stmt, t.insert.names = qb.Insert(m.Name).Columns(m.Columns...).ToCql()

	return t
}

// Metadata returns copy of table metadata.
func (t *Table) Metadata() Metadata {
	return t.metadata
}

// PrimaryKeyCmp returns copy of table's primaryKeyCmp.
func (t *Table) PrimaryKeyCmp() []qb.Cmp {
	primaryKeyCmp := make([]qb.Cmp, len(t.primaryKeyCmp))
	copy(primaryKeyCmp, t.primaryKeyCmp)
	return primaryKeyCmp
}

// Name returns table name.
func (t *Table) Name() string {
	return t.metadata.Name
}

// Get returns select by primary key statement.
func (t *Table) Get(columns ...string) (stmt string, names []string) {
	if len(columns) == 0 {
		return t.get.stmt, t.get.names
	}

	return qb.Select(t.metadata.Name).
		Columns(columns...).
		Where(t.primaryKeyCmp...).
		ToCql()
}

// GetQuery returns query which gets by partition key.
func (t *Table) GetQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Get(columns...))
}

// GetQueryContext returns query wrapped with context which gets by partition key.
func (t *Table) GetQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.GetQuery(session, columns...).WithContext(ctx)
}

// Select returns select by partition key statement.
func (t *Table) Select(columns ...string) (stmt string, names []string) {
	if len(columns) == 0 {
		return t.sel.stmt, t.sel.names
	}

	return qb.Select(t.metadata.Name).
		Columns(columns...).
		Where(t.primaryKeyCmp[0:len(t.metadata.PartKey)]...).
		ToCql()
}

// SelectQuery returns query which selects by partition key statement.
func (t *Table) SelectQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Select(columns...))
}

// SelectQueryContext returns query wrapped with context which selects by partition key statement.
func (t *Table) SelectQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.SelectQuery(session, columns...).WithContext(ctx)
}

// SelectBuilder returns a builder initialised to select by partition key
// statement.
func (t *Table) SelectBuilder(columns ...string) *qb.SelectBuilder {
	return qb.Select(t.metadata.Name).Columns(columns...).Where(t.partKeyCmp...)
}

// Insert returns insert all columns statement.
func (t *Table) Insert() (stmt string, names []string) {
	return t.insert.stmt, t.insert.names
}

// InsertQuery returns query which inserts all columns.
func (t *Table) InsertQuery(session gocqlx.Session) *gocqlx.Queryx {
	return session.Query(t.Insert())
}

// InsertQueryContext returns query wrapped with context which inserts all columns.
func (t *Table) InsertQueryContext(ctx context.Context, session gocqlx.Session) *gocqlx.Queryx {
	return t.InsertQuery(session).WithContext(ctx)
}

// InsertBuilder returns a builder initialised with all columns.
func (t *Table) InsertBuilder() *qb.InsertBuilder {
	return qb.Insert(t.metadata.Name).Columns(t.metadata.Columns...)
}

// Update returns update by primary key statement.
func (t *Table) Update(columns ...string) (stmt string, names []string) {
	return t.UpdateBuilder(columns...).ToCql()
}

// UpdateQuery returns query which updates by primary key.
func (t *Table) UpdateQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Update(columns...))
}

// UpdateQueryContext returns query wrapped with context which updates by primary key.
func (t *Table) UpdateQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.UpdateQuery(session, columns...).WithContext(ctx)
}

// UpdateBuilder returns a builder initialised to update by primary key statement.
func (t *Table) UpdateBuilder(columns ...string) *qb.UpdateBuilder {
	return qb.Update(t.metadata.Name).Set(columns...).Where(t.primaryKeyCmp...)
}

// Delete returns delete by primary key statement.
func (t *Table) Delete(columns ...string) (stmt string, names []string) {
	return t.DeleteBuilder(columns...).ToCql()
}

// DeleteQuery returns query which delete by primary key.
func (t *Table) DeleteQuery(session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return session.Query(t.Delete(columns...))
}

// DeleteQueryContext returns query wrapped with context which delete by primary key.
func (t *Table) DeleteQueryContext(ctx context.Context, session gocqlx.Session, columns ...string) *gocqlx.Queryx {
	return t.DeleteQuery(session, columns...).WithContext(ctx)
}

// DeleteBuilder returns a builder initialised to delete by primary key statement.
func (t *Table) DeleteBuilder(columns ...string) *qb.DeleteBuilder {
	return qb.Delete(t.metadata.Name).Columns(columns...).Where(t.primaryKeyCmp...)
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gorilla/mux"
	. "github.com/smartystreets/goconvey/convey"
)

func TestGetTables(t *testing.T) {
	Convey("Get tables without custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables", nil)
		w := httptest.NewRecorder()
		So(err, ShouldBeNil)
		validate(w, r, GetTables)
	})

	Convey("Get tables with custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables?c.relname=test", nil)
		w := httptest.NewRecorder()
		So(err, ShouldBeNil)
		validate(w, r, GetTables)
	})
}

func TestGetTablesByDatabaseAndSchema(t *testing.T) {
	router := mux.NewRouter()
	router.HandleFunc("/{database}/{schema}", GetTablesByDatabaseAndSchema).Methods("GET")
	server := httptest.NewServer(router)
	defer server.Close()
	Convey("Get tables by database and schema without custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public")
	})

	Convey("Get tables by database and schema with custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public?t.tablename=test")
	})
}

func TestSelectFromTable(t *testing.T) {
	router := mux.NewRouter()
	router.HandleFunc("/{database}/{schema}/{table}", SelectFromTables).Methods("GET")
	server := httptest.NewServer(router)
	defer server.Close()
	Convey("execute select in a table without custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public")
	})

	Convey("execute select in a table with custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public/test?name=nuveo")
	})
}
<commit_msg>fix test<commit_after>package controllers

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gorilla/mux"
	. "github.com/smartystreets/goconvey/convey"
)

func TestGetTables(t *testing.T) {
	Convey("Get tables without custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables", nil)
		w := httptest.NewRecorder()
		So(err, ShouldBeNil)
		validate(w, r, GetTables)
	})

	Convey("Get tables with custom where clause", t, func() {
		r, err := http.NewRequest("GET", "/tables?c.relname=test", nil)
		w := httptest.NewRecorder()
		So(err, ShouldBeNil)
		validate(w, r, GetTables)
	})
}

func TestGetTablesByDatabaseAndSchema(t *testing.T) {
	router := mux.NewRouter()
	router.HandleFunc("/{database}/{schema}", GetTablesByDatabaseAndSchema).Methods("GET")
	server := httptest.NewServer(router)
	defer server.Close()
	Convey("Get tables by database and schema without custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public")
	})

	Convey("Get tables by database and schema with custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public?t.tablename=test")
	})
}

func TestSelectFromTable(t *testing.T) {
	router := mux.NewRouter()
	router.HandleFunc("/{database}/{schema}/{table}", SelectFromTables).Methods("GET")
	server := httptest.NewServer(router)
	defer server.Close()
	Convey("execute select in a table without custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public/test")
	})

	Convey("execute select in a table with custom where clause", t, func() {
		doValidRequest(server.URL + "/prest/public/test?name=nuveo")
	})
}
<|endoftext|>


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

// obdi manages deployment processes
package main

import (
	//"fmt"
	"github.com/mclarkson/obdi/external/ant0ine/go-json-rest/rest"
	"net/http"
	"sync"
)

var mutex = &sync.Mutex{}
var apimutex = &sync.Mutex{}

func main() {

	db := NewDB()
	api := NewApi(db)

	db.CreateAdminAccount()

	// TODO: disable this
	db.DB().LogMode(false)

	handler := rest.ResourceHandler{
		EnableRelaxedContentType: true,
		//DisableJsonIndent: true,
		//EnableGzip:        true,
	}
	handler.SetRoutes(

		&rest.Route{"POST", "/login", api.DoLogin},

		&rest.Route{"POST", "/#login/:GUID/logout", api.Logout},

		// ADMIN FUNCTIONS

		// USERS

		&rest.Route{"GET", "/:login/:GUID/users", api.GetAllUsers},

		&rest.Route{"POST", "/:login/:GUID/users", api.AddUser},

		&rest.Route{"PUT", "/:login/:GUID/users/:id", api.UpdateUser},

		&rest.Route{"DELETE", "/:login/:GUID/users/:id", api.DeleteUser},

		// Data Centres

		&rest.Route{"GET", "/:login/:GUID/dcs", api.GetAllDcs},

		&rest.Route{"POST", "/:login/:GUID/dcs", api.AddDc},

		&rest.Route{"DELETE", "/:login/:GUID/dcs/:id", api.DeleteDc},

		&rest.Route{"PUT", "/:login/:GUID/dcs/:id", api.UpdateDc},

		// Environments

		&rest.Route{"GET", "/#login/:GUID/envs", api.GetAllEnvs},

		&rest.Route{"POST", "/:login/:GUID/envs", api.AddEnv},

		&rest.Route{"DELETE", "/:login/:GUID/envs/:id", api.DeleteEnv},

		&rest.Route{"PUT", "/:login/:GUID/envs/:id", api.UpdateEnv},

		// User Permissions

		&rest.Route{"GET", "/:login/:GUID/perms", api.GetAllPerms},

		&rest.Route{"POST", "/:login/:GUID/perms", api.AddPerm},

		&rest.Route{"DELETE", "/:login/:GUID/perms/:id", api.DeletePerm},

		&rest.Route{"PUT", "/:login/:GUID/perms/:id", api.UpdatePerm},

		// Data Centre Capabilities

		&rest.Route{"GET", "/:login/:GUID/dccaps", api.GetAllDcCaps},

		&rest.Route{"POST", "/:login/:GUID/dccaps", api.AddDcCap},

		&rest.Route{"DELETE", "/:login/:GUID/dccaps/:id", api.DeleteDcCap},

		&rest.Route{"PUT", "/:login/:GUID/dccaps/:id", api.UpdateDcCap},

		// Data Centre Capability Maps

		&rest.Route{"GET", "/:login/:GUID/dccapmaps", api.GetAllDcCapMaps},

		&rest.Route{"POST", "/:login/:GUID/dccapmaps", api.AddDcCapMap},

		&rest.Route{"DELETE", "/:login/:GUID/dccapmaps/:id", api.DeleteDcCapMap},

		&rest.Route{"PUT", "/:login/:GUID/dccapmaps/:id", api.UpdateDcCapMap},

		// Environment Capabilities

		&rest.Route{"GET", "/:login/:GUID/envcaps", api.GetAllEnvCaps},

		&rest.Route{"POST", "/:login/:GUID/envcaps", api.AddEnvCap},

		&rest.Route{"DELETE", "/:login/:GUID/envcaps/:id", api.DeleteEnvCap},

		&rest.Route{"PUT", "/:login/:GUID/envcaps/:id", api.UpdateEnvCap},

		// Data Centre Capability Maps

		&rest.Route{"GET", "/:login/:GUID/envcapmaps", api.GetAllEnvCapMaps},

		&rest.Route{"POST", "/:login/:GUID/envcapmaps", api.AddEnvCapMap},

		&rest.Route{"DELETE", "/:login/:GUID/envcapmaps/:id", api.DeleteEnvCapMap},

		&rest.Route{"PUT", "/:login/:GUID/envcapmaps/:id", api.UpdateEnvCapMap},

		// Scripts

		&rest.Route{"GET", "/#login/:GUID/scripts", api.GetAllScripts},

		&rest.Route{"POST", "/:login/:GUID/scripts", api.AddScript},

		&rest.Route{"DELETE", "/:login/:GUID/scripts/:id", api.DeleteScript},

		&rest.Route{"PUT", "/:login/:GUID/scripts/:id", api.UpdateScript},

		// Jobs

		&rest.Route{"GET", "/#login/:GUID/jobs", api.GetAllJobs},

		&rest.Route{"POST", "/#login/:GUID/jobs", api.AddJob},

		&rest.Route{"DELETE", "/#login/:GUID/jobs/kill/:id", api.KillJob},

		&rest.Route{"DELETE", "/#login/:GUID/jobs/:id", api.DeleteJob},

		&rest.Route{"PUT", "/#login/:GUID/jobs/:id", api.UpdateJob},

		// Plugins

		&rest.Route{"GET", "/#login/:GUID/plugins", api.GetAllPlugins},

		&rest.Route{"POST", "/#login/:GUID/plugins", api.AddPlugin},

		&rest.Route{"DELETE", "/#login/:GUID/plugins/:id", api.DeletePlugin},

		&rest.Route{"PUT", "/#login/:GUID/plugins/:id", api.UpdatePlugin},

		// Files

		&rest.Route{"GET", "/#login/:GUID/files", api.GetAllFiles},

		&rest.Route{"POST", "/#login/:GUID/files", api.AddFile},

		&rest.Route{"DELETE", "/#login/:GUID/files/:id", api.DeleteFile},

		&rest.Route{"PUT", "/#login/:GUID/files/:id", api.UpdateFile},

		// Notifications

		&rest.Route{"GET", "/#login/:GUID/outputlines", api.GetAllOutputLines},

		&rest.Route{"POST", "/#login/:GUID/outputlines", api.AddOutputLine},

		&rest.Route{"DELETE", "/#login/:GUID/outputlines/:id",
			api.DeleteOutputLine},

		/* No changing output logs
		   // //&rest.Route{"PUT", "/#login/:GUID/outputlines/:id", // //
		   // api.UpdateOutputLine},
		*/

		// Generic

		&rest.Route{"GET", "/#login/:GUID/#endpoint",
			api.GenericGetEndpoint},

		&rest.Route{"GET", "/#login/:GUID/#endpoint/#subitem",
			api.GenericGetEndpoint},

		&rest.Route{"POST", "/#login/:GUID/#endpoint",
			api.GenericPostEndpoint},

		&rest.Route{"POST", "/#login/:GUID/#endpoint/#subitem",
			api.GenericPostEndpoint},

		&rest.Route{"DELETE", "/#login/:GUID/#endpoint/:id",
			api.GenericDeleteEndpoint},

		&rest.Route{"DELETE", "/#login/:GUID/#endpoint/#subitem/:id",
			api.GenericDeleteEndpoint},

		&rest.Route{"PUT", "/#login/:GUID/#endpoint", api.GenericPutEndpoint},

		&rest.Route{"PUT", "/#login/:GUID/#endpoint/#subitem",
			api.GenericPutEndpoint},
	)

	// Add the REST API handle
	http.Handle("/api/", http.StripPrefix("/api", &handler))

	// Add the Web Server handle
	changeHeaderThenServe := func(h http.Handler) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			// HTTP 1.1
			w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
			// HTTP 1.0
			w.Header().Add("Pragma", "no-cache")
			// Proxies
			w.Header().Add("Expires", "0")
			h.ServeHTTP(w, r)
		}
	}
	fs := http.FileServer(http.Dir(config.StaticContent))
	fs = changeHeaderThenServe(fs)
	http.Handle("/manager/", http.StripPrefix("/manager", fs))

	// Add the Manager template handle
	http.HandleFunc("/manager/run", api.serveRunTemplate)

	// Add the Admin template handle
	http.HandleFunc("/manager/admin", api.serveRunTemplate)

	if config.SSLEnabled {
		if err := http.ListenAndServeTLS(config.ListenAddr,
			config.SSLCertFile, config.SSLKeyFile, nil); err != nil {
			logit(err.Error())
		}
	} else {
		if err := http.ListenAndServe(config.ListenAddr, nil); err != nil {
			logit(err.Error())
		}
	}
}
<commit_msg>Allow '.' in hostname<commit_after>// Obdi - a REST interface and GUI for deploying software
// Copyright (C) 2014  Mark Clarkson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// obdi manages deployment processes
package main

import (
	//"fmt"
	"github.com/mclarkson/obdi/external/ant0ine/go-json-rest/rest"
	"net/http"
	"sync"
)

var mutex = &sync.Mutex{}
var apimutex = &sync.Mutex{}

func main() {

	db := NewDB()
	api := NewApi(db)

	db.CreateAdminAccount()

	// TODO: disable this
	db.DB().LogMode(false)

	handler := rest.ResourceHandler{
		EnableRelaxedContentType: true,
		//DisableJsonIndent: true,
		//EnableGzip:        true,
	}
	handler.SetRoutes(

		&rest.Route{"POST", "/login", api.DoLogin},

		&rest.Route{"POST", "/#login/:GUID/logout", api.Logout},

		// ADMIN FUNCTIONS

		// USERS

		&rest.Route{"GET", "/:login/:GUID/users", api.GetAllUsers},

		&rest.Route{"POST", "/:login/:GUID/users", api.AddUser},

		&rest.Route{"PUT", "/:login/:GUID/users/:id", api.UpdateUser},

		&rest.Route{"DELETE", "/:login/:GUID/users/:id", api.DeleteUser},

		// Data Centres

		&rest.Route{"GET", "/:login/:GUID/dcs", api.GetAllDcs},

		&rest.Route{"POST", "/:login/:GUID/dcs", api.AddDc},

		&rest.Route{"DELETE", "/:login/:GUID/dcs/:id", api.DeleteDc},

		&rest.Route{"PUT", "/:login/:GUID/dcs/:id", api.UpdateDc},

		// Environments

		&rest.Route{"GET", "/#login/:GUID/envs", api.GetAllEnvs},

		&rest.Route{"POST", "/:login/:GUID/envs", api.AddEnv},

		&rest.Route{"DELETE", "/:login/:GUID/envs/:id", api.DeleteEnv},

		&rest.Route{"PUT", "/:login/:GUID/envs/:id", api.UpdateEnv},

		// User Permissions

		&rest.Route{"GET", "/:login/:GUID/perms", api.GetAllPerms},

		&rest.Route{"POST", "/:login/:GUID/perms", api.AddPerm},

		&rest.Route{"DELETE", "/:login/:GUID/perms/:id", api.DeletePerm},

		&rest.Route{"PUT", "/:login/:GUID/perms/:id", api.UpdatePerm},

		// Data Centre Capabilities

		&rest.Route{"GET", "/:login/:GUID/dccaps", api.GetAllDcCaps},

		&rest.Route{"POST", "/:login/:GUID/dccaps", api.AddDcCap},

		&rest.Route{"DELETE", "/:login/:GUID/dccaps/:id", api.DeleteDcCap},

		&rest.Route{"PUT", "/:login/:GUID/dccaps/:id", api.UpdateDcCap},

		// Data Centre Capability Maps

		&rest.Route{"GET", "/:login/:GUID/dccapmaps", api.GetAllDcCapMaps},

		&rest.Route{"POST", "/:login/:GUID/dccapmaps", api.AddDcCapMap},

		&rest.Route{"DELETE", "/:login/:GUID/dccapmaps/:id", api.DeleteDcCapMap},

		&rest.Route{"PUT", "/:login/:GUID/dccapmaps/:id", api.UpdateDcCapMap},

		// Environment Capabilities

		&rest.Route{"GET", "/:login/:GUID/envcaps", api.GetAllEnvCaps},

		&rest.Route{"POST", "/:login/:GUID/envcaps", api.AddEnvCap},

		&rest.Route{"DELETE", "/:login/:GUID/envcaps/:id", api.DeleteEnvCap},

		&rest.Route{"PUT", "/:login/:GUID/envcaps/:id", api.UpdateEnvCap},

		// Data Centre Capability Maps

		&rest.Route{"GET", "/:login/:GUID/envcapmaps", api.GetAllEnvCapMaps},

		&rest.Route{"POST", "/:login/:GUID/envcapmaps", api.AddEnvCapMap},

		&rest.Route{"DELETE", "/:login/:GUID/envcapmaps/:id", api.DeleteEnvCapMap},

		&rest.Route{"PUT", "/:login/:GUID/envcapmaps/:id", api.UpdateEnvCapMap},

		// Scripts

		&rest.Route{"GET", "/#login/:GUID/scripts", api.GetAllScripts},

		&rest.Route{"POST", "/:login/:GUID/scripts", api.AddScript},

		&rest.Route{"DELETE", "/:login/:GUID/scripts/:id", api.DeleteScript},

		&rest.Route{"PUT", "/:login/:GUID/scripts/:id", api.UpdateScript},

		// Jobs

		&rest.Route{"GET", "/#login/:GUID/jobs", api.GetAllJobs},

		&rest.Route{"POST", "/#login/:GUID/jobs", api.AddJob},

		&rest.Route{"DELETE", "/#login/:GUID/jobs/kill/:id", api.KillJob},

		&rest.Route{"DELETE", "/#login/:GUID/jobs/:id", api.DeleteJob},

		&rest.Route{"PUT", "/#login/:GUID/jobs/:id", api.UpdateJob},

		// Plugins

		&rest.Route{"GET", "/#login/:GUID/plugins", api.GetAllPlugins},

		&rest.Route{"POST", "/#login/:GUID/plugins", api.AddPlugin},

		&rest.Route{"DELETE", "/#login/:GUID/plugins/:id", api.DeletePlugin},

		&rest.Route{"PUT", "/#login/:GUID/plugins/:id", api.UpdatePlugin},

		// Files

		&rest.Route{"GET", "/#login/:GUID/files", api.GetAllFiles},

		&rest.Route{"POST", "/#login/:GUID/files", api.AddFile},

		&rest.Route{"DELETE", "/#login/:GUID/files/:id", api.DeleteFile},

		&rest.Route{"PUT", "/#login/:GUID/files/:id", api.UpdateFile},

		// Notifications

		&rest.Route{"GET", "/#login/:GUID/outputlines", api.GetAllOutputLines},

		&rest.Route{"POST", "/#login/:GUID/outputlines", api.AddOutputLine},

		&rest.Route{"DELETE", "/#login/:GUID/outputlines/:id",
			api.DeleteOutputLine},

		/* No changing output logs
		   // //&rest.Route{"PUT", "/#login/:GUID/outputlines/:id", // //
		   // api.UpdateOutputLine},
		*/

		// Generic

		&rest.Route{"GET", "/#login/:GUID/#endpoint",
			api.GenericGetEndpoint},

		&rest.Route{"GET", "/#login/:GUID/#endpoint/#subitem",
			api.GenericGetEndpoint},

		&rest.Route{"POST", "/#login/:GUID/#endpoint",
			api.GenericPostEndpoint},

		&rest.Route{"POST", "/#login/:GUID/#endpoint/#subitem",
			api.GenericPostEndpoint},

		&rest.Route{"DELETE", "/#login/:GUID/#endpoint/#id",
			api.GenericDeleteEndpoint},

		&rest.Route{"DELETE", "/#login/:GUID/#endpoint/#subitem/#id",
			api.GenericDeleteEndpoint},

		&rest.Route{"PUT", "/#login/:GUID/#endpoint", api.GenericPutEndpoint},

		&rest.Route{"PUT", "/#login/:GUID/#endpoint/#subitem",
			api.GenericPutEndpoint},
	)

	// Add the REST API handle
	http.Handle("/api/", http.StripPrefix("/api", &handler))

	// Add the Web Server handle
	changeHeaderThenServe := func(h http.Handler) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			// HTTP 1.1
			w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
			// HTTP 1.0
			w.Header().Add("Pragma", "no-cache")
			// Proxies
			w.Header().Add("Expires", "0")
			h.ServeHTTP(w, r)
		}
	}
	fs := http.FileServer(http.Dir(config.StaticContent))
	fs = changeHeaderThenServe(fs)
	http.Handle("/manager/", http.StripPrefix("/manager", fs))

	// Add the Manager template handle
	http.HandleFunc("/manager/run", api.serveRunTemplate)

	// Add the Admin template handle
	http.HandleFunc("/manager/admin", api.serveRunTemplate)

	if config.SSLEnabled {
		if err := http.ListenAndServeTLS(config.ListenAddr,
			config.SSLCertFile, config.SSLKeyFile, nil); err != nil {
			logit(err.Error())
		}
	} else {
		if err := http.ListenAndServe(config.ListenAddr, nil); err != nil {
			logit(err.Error())
		}
	}
}
<|endoftext|>


<commit_before>package crawler

import (
	"errors"
	"strings"
	"unicode"

	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

var (
	// ErrMinificationUnexpectedNodeType - found unexpected node type
	ErrMinificationUnexpectedNodeType = errors.New("minification1.minification1.parseNode: unexpected node type")
)

type minification1 struct {
}

func (m *minification1) removeAttr(node *html.Node) {
	lenAttr := len(node.Attr)
	if lenAttr != 0 {
		attr := node.Attr
		i := 0
		j := 0
		for ; i != lenAttr; i++ {
			key := strings.ToLower(attr[i].Key)
			if strings.HasPrefix(key, "data-") {
				continue
			}
			switch key {
			case "id":
			case "alt":
			case "cols":
			case "class":
			case "title":
			case "width":
			case "align":
			case "style":
			case "color":
			case "valign":
			case "target":
			case "height":
			case "border":
			case "hspace":
			case "vspace":
			case "bgcolor":
			case "onclick":
			case "colspan":
			case "itemprop":
			case "disabled":
			case "itemtype":
			case "itemscope":
			case "cellspacing":
			case "cellpadding":
			case "bordercolor":
			default:
				if i != j {
					attr[j] = attr[i]
				}
				j++
			}
		}
		if i != j {
			node.Attr = attr[:j]
		}
	}
}

func (m *minification1) getAttrVal(node *html.Node, attrName string) string {
	for _, attr := range node.Attr {
		if attr.Key == attrName {
			return attr.Val
		}
	}

	return ""
}

func (m *minification1) getAttrValLower(node *html.Node, attrName string) string {
	return strings.ToLower(m.getAttrVal(node, attrName))
}

func (m *minification1) mergeNodes(parent, prev, next *html.Node, addSeparator bool) *html.Node {
	var result *html.Node
	prevText := prev != nil && prev.Type == html.TextNode
	nextText := next != nil && next.Type == html.TextNode
	delim := ""
	if addSeparator {
		delim = " "
	}

	if prevText && nextText {
		prev.Data = strings.TrimRightFunc(prev.Data, unicode.IsSpace) +
			delim + strings.TrimLeftFunc(next.Data, unicode.IsSpace)
		parent.RemoveChild(next)
		result = prev.NextSibling
	} else if prevText {
		prev.Data = strings.TrimRightFunc(prev.Data, unicode.IsSpace) + delim
		result = next
	} else if nextText {
		next.Data = delim + strings.TrimLeftFunc(next.Data, unicode.IsSpace)
		result = next
	} else if addSeparator {
		newNode := &html.Node{
			Parent:      parent,
			FirstChild:  nil,
			LastChild:   nil,
			PrevSibling: prev,
			NextSibling: next,
			Type:        html.TextNode,
			Data:        delim,
			Namespace:   parent.Namespace}
		if prev != nil {
			prev.NextSibling = newNode
		} else {
			parent.FirstChild = newNode
		}
		if next != nil {
			next.PrevSibling = newNode
		} else {
			parent.LastChild = newNode
		}
		result = next
	} else {
		result = next
	}

	return result
}

func (m *minification1) removeNode(node *html.Node, addSeparator bool) (*html.Node, error) {
	prev, next, parent := node.PrevSibling, node.NextSibling, node.Parent
	parent.RemoveChild(node)
	result := m.mergeNodes(parent, prev, next, addSeparator)

	return result, nil
}

func (m *minification1) parseChildren(node *html.Node) (*html.Node, error) {
	var err error
	for it := node.FirstChild; it != nil; {
		it, err = m.parseNode(it)
		if err != nil {
			return node.NextSibling, err
		}
	}

	return node.NextSibling, nil
}

func (m *minification1) parseElements(node *html.Node) (*html.Node, error) {
	switch node.DataAtom {
	case atom.Script:
		return m.removeNode(node, true)
	case atom.Button:
		return m.removeNode(node, true)
	case atom.Object:
		return m.removeNode(node, true)
	case atom.Select:
		return m.removeNode(node, true)
	case atom.Style:
		return m.removeNode(node, true)
	case atom.Param:
		return m.removeNode(node, true)
	case atom.Embed:
		return m.removeNode(node, true)
	case atom.Form:
		return m.removeNode(node, true)
	case atom.Time:
		return m.removeNode(node, true)
	case atom.Img:
		return m.removeNode(node, true)
	case atom.Svg:
		return m.removeNode(node, true)
	case atom.Br:
		return m.removeNode(node, true)
	case atom.Hr:
		return m.removeNode(node, true)
	case atom.Wbr:
		return m.removeNode(node, false)
	case atom.Input:
		typeInput := m.getAttrValLower(node, "type")
		if typeInput == "radio" ||
			typeInput == "checkbox" ||
			typeInput == "hidden" ||
			typeInput == "button" ||
			typeInput == "submit" ||
			typeInput == "reset" ||
			typeInput == "file" ||
			typeInput == "image" {
			return m.removeNode(node, true)
		}
	}

	m.removeAttr(node)

	return m.parseChildren(node)
}

func (m *minification1) parseNode(node *html.Node) (*html.Node, error) {
	switch node.Type {
	case html.DocumentNode: // +children -attr (first node)
		return m.parseChildren(node)
	case html.ElementNode: // +children +attr
		return m.parseElements(node)
	case html.TextNode: // -children -attr
		return node.NextSibling, nil
	case html.DoctypeNode: // ignore
		return node.NextSibling, nil
	case html.CommentNode: // remove
		return m.removeNode(node, true)
	default:
		return nil, ErrMinificationUnexpectedNodeType
	}
}

// RunMinification1 - start minification node
func RunMinification1(node *html.Node) error {
	m := minification1{}
	_, err := m.parseNode(node)
	return err
}
<commit_msg>функция раскрытия тега<commit_after>package crawler

import (
	"errors"
	"strings"
	"unicode"

	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

var (
	// ErrMinificationUnexpectedNodeType - found unexpected node type
	ErrMinificationUnexpectedNodeType = errors.New("minification1.minification1.parseNode: unexpected node type")
)

type minification1 struct {
}

func (m *minification1) removeAttr(node *html.Node) {
	lenAttr := len(node.Attr)
	if lenAttr != 0 {
		attr := node.Attr
		i := 0
		j := 0
		for ; i != lenAttr; i++ {
			key := strings.ToLower(attr[i].Key)
			if strings.HasPrefix(key, "data-") {
				continue
			}
			switch key {
			case "id":
			case "alt":
			case "cols":
			case "class":
			case "title":
			case "width":
			case "align":
			case "style":
			case "color":
			case "valign":
			case "target":
			case "height":
			case "border":
			case "hspace":
			case "vspace":
			case "bgcolor":
			case "onclick":
			case "colspan":
			case "itemprop":
			case "disabled":
			case "itemtype":
			case "itemscope":
			case "cellspacing":
			case "cellpadding":
			case "bordercolor":
			default:
				if i != j {
					attr[j] = attr[i]
				}
				j++
			}
		}
		if i != j {
			node.Attr = attr[:j]
		}
	}
}

func (m *minification1) getAttrVal(node *html.Node, attrName string) string {
	for _, attr := range node.Attr {
		if attr.Key == attrName {
			return attr.Val
		}
	}

	return ""
}

func (m *minification1) getAttrValLower(node *html.Node, attrName string) string {
	return strings.ToLower(m.getAttrVal(node, attrName))
}

func (m *minification1) mergeNodes(parent, prev, next *html.Node, addSeparator bool) *html.Node {
	var result *html.Node
	prevText := prev != nil && prev.Type == html.TextNode
	nextText := next != nil && next.Type == html.TextNode
	delim := ""
	if addSeparator {
		delim = " "
	}

	if prevText && nextText {
		prev.Data = strings.TrimRightFunc(prev.Data, unicode.IsSpace) +
			delim + strings.TrimLeftFunc(next.Data, unicode.IsSpace)
		parent.RemoveChild(next)
		result = prev.NextSibling
	} else if prevText {
		prev.Data = strings.TrimRightFunc(prev.Data, unicode.IsSpace) + delim
		result = next
	} else if nextText {
		next.Data = delim + strings.TrimLeftFunc(next.Data, unicode.IsSpace)
		result = next
	} else if addSeparator {
		newNode := &html.Node{
			Parent:      parent,
			FirstChild:  nil,
			LastChild:   nil,
			PrevSibling: prev,
			NextSibling: next,
			Type:        html.TextNode,
			Data:        delim,
			Namespace:   parent.Namespace}
		if prev != nil {
			prev.NextSibling = newNode
		} else {
			parent.FirstChild = newNode
		}
		if next != nil {
			next.PrevSibling = newNode
		} else {
			parent.LastChild = newNode
		}
		result = next
	} else {
		result = next
	}

	return result
}

func (m *minification1) removeNode(node *html.Node, addSeparator bool) (*html.Node, error) {
	prev, next, parent := node.PrevSibling, node.NextSibling, node.Parent
	parent.RemoveChild(node)
	result := m.mergeNodes(parent, prev, next, addSeparator)

	return result, nil
}

func (m *minification1) openNode(node *html.Node, addSeparator bool) (*html.Node, error) {
	parent := node.Parent
	first, last := node.FirstChild, node.LastChild
	prev, next := node.PrevSibling, node.NextSibling

	if first == nil {
		return m.removeNode(node, addSeparator)
	}

	for it := first; it != nil; it = it.NextSibling {
		it.Parent = parent
	}

	if parent.FirstChild == node {
		parent.FirstChild = first
	}
	if parent.LastChild == node {
		parent.LastChild = last
	}

	if prev != nil {
		first.PrevSibling = prev
		prev.NextSibling = first
	}
	if next != nil {
		last.NextSibling = next
		next.PrevSibling = last
	}

	node.Parent = nil
	node.PrevSibling = nil
	node.NextSibling = nil

	result := m.mergeNodes(parent, prev, first, addSeparator)
	result = m.mergeNodes(parent, last, next, addSeparator)

	return result, nil
}

func (m *minification1) parseChildren(node *html.Node) (*html.Node, error) {
	var err error
	for it := node.FirstChild; it != nil; {
		it, err = m.parseNode(it)
		if err != nil {
			return node.NextSibling, err
		}
	}

	return node.NextSibling, nil
}

func (m *minification1) parseElements(node *html.Node) (*html.Node, error) {
	switch node.DataAtom {
	case atom.Script:
		return m.removeNode(node, true)
	case atom.Button:
		return m.removeNode(node, true)
	case atom.Object:
		return m.removeNode(node, true)
	case atom.Select:
		return m.removeNode(node, true)
	case atom.Style:
		return m.removeNode(node, true)
	case atom.Param:
		return m.removeNode(node, true)
	case atom.Embed:
		return m.removeNode(node, true)
	case atom.Form:
		return m.removeNode(node, true)
	case atom.Time:
		return m.removeNode(node, true)
	case atom.Img:
		return m.removeNode(node, true)
	case atom.Svg:
		return m.removeNode(node, true)
	case atom.Br:
		return m.removeNode(node, true)
	case atom.Hr:
		return m.removeNode(node, true)
	case atom.Wbr:
		return m.removeNode(node, false)
	case atom.Input:
		typeInput := m.getAttrValLower(node, "type")
		if typeInput == "radio" ||
			typeInput == "checkbox" ||
			typeInput == "hidden" ||
			typeInput == "button" ||
			typeInput == "submit" ||
			typeInput == "reset" ||
			typeInput == "file" ||
			typeInput == "image" {
			return m.removeNode(node, true)
		}
	}

	switch node.DataAtom {
	case atom.B:
		return m.openNode(node, false)
	}

	m.removeAttr(node)

	return m.parseChildren(node)
}

func (m *minification1) parseNode(node *html.Node) (*html.Node, error) {
	switch node.Type {
	case html.DocumentNode: // +children -attr (first node)
		return m.parseChildren(node)
	case html.ElementNode: // +children +attr
		return m.parseElements(node)
	case html.TextNode: // -children -attr
		return node.NextSibling, nil
	case html.DoctypeNode: // ignore
		return node.NextSibling, nil
	case html.CommentNode: // remove
		return m.removeNode(node, true)
	default:
		return nil, ErrMinificationUnexpectedNodeType
	}
}

// RunMinification1 - start minification node
func RunMinification1(node *html.Node) error {
	m := minification1{}
	_, err := m.parseNode(node)
	return err
}
<|endoftext|>