<commit_before>package handlers

import (
	"database/sql"
	"fmt"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"

	"golang.org/x/net/webdav"

	"pixur.org/pixur/schema"
	_ "pixur.org/pixur/tasks"
)

type PixFS struct {
	// embeds
	webdav.FileSystem

	// deps
	DB *sql.DB
}

func (fs *PixFS) Mkdir(name string, perm os.FileMode) error {
	return os.ErrPermission
}

func (fs *PixFS) RemoveAll(name string) error {
	return os.ErrPermission
}

func (fs *PixFS) Rename(oldName, newName string) error {
	return os.ErrPermission
}

func (fs *PixFS) Stat(name string) (os.FileInfo, error) {
	if len(filepath.Ext(name)) != 0 {
		base := strings.TrimSuffix(filepath.Base(name), filepath.Ext(name))
		fmt.Println(name, "  ", base)
		var v schema.Varint
		if consumed, err := v.Decode(base); err != nil {
			return nil, os.ErrNotExist
		} else if len(base) > consumed {
			// Thumbnails have this property
			return nil, os.ErrNotExist
		}
	}

	return fs.FileSystem.Stat(name)
}

func (fs *PixFS) OpenFile(name string, flag int, perm os.FileMode) (webdav.File, error) {
	if len(filepath.Ext(name)) != 0 {
		fmt.Println(name + "zzz")
		// Exclude thumbnails from showing up, which are noisy.
		base := strings.TrimSuffix(filepath.Base(name), filepath.Ext(name))
		var v schema.Varint
		if consumed, err := v.Decode(base); err != nil {
			return nil, os.ErrNotExist
		} else if len(base) > consumed {
			// Thumbnails have this property
			return nil, os.ErrNotExist
		}
	}
	if flag != os.O_RDONLY || perm != 0 {
		return nil, os.ErrPermission
	}

	f, err := fs.FileSystem.OpenFile(name, flag, perm)
	if err != nil {
		return nil, err
	}

	return &wrapper{File: f}, nil
}

type wrapper struct {
	webdav.File
}

func (w *wrapper) Readdir(count int) ([]os.FileInfo, error) {
	infos, err := w.File.Readdir(count)
	if err != nil {
		return nil, err
	}
	var goodInfos []os.FileInfo

	for _, info := range infos {
		if strings.ContainsRune(path.Base(info.Name()), 'u') {
			continue
		}

		goodInfos = append(goodInfos, info)
	}

	return goodInfos, nil
}

func init() {
	register(func(mux *http.ServeMux, c *ServerConfig) {
		mux.Handle("/api/dav/", &webdav.Handler{
			Prefix: "/api/dav",
			FileSystem: &PixFS{
				FileSystem: webdav.Dir(c.PixPath),
				DB:         c.DB,
			},
			LockSystem: webdav.NewMemLS(),
		})
	})
}
<commit_msg>Fix bug in Dav handler<commit_after>package handlers

import (
	"database/sql"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/net/webdav"

	"pixur.org/pixur/schema"
)

type PixFS struct {
	// embeds
	webdav.FileSystem

	// deps
	DB *sql.DB
}

func (fs *PixFS) Mkdir(name string, perm os.FileMode) error {
	return os.ErrPermission
}

func (fs *PixFS) RemoveAll(name string) error {
	return os.ErrPermission
}

func (fs *PixFS) Rename(oldName, newName string) error {
	return os.ErrPermission
}

func (fs *PixFS) Stat(name string) (os.FileInfo, error) {
	if isThumbnail(name) {
		return nil, os.ErrNotExist
	}

	return fs.FileSystem.Stat(name)
}

func (fs *PixFS) OpenFile(name string, flag int, perm os.FileMode) (webdav.File, error) {
	if isThumbnail(name) {
		return nil, os.ErrNotExist
	}
	if flag != os.O_RDONLY || perm != 0 {
		return nil, os.ErrPermission
	}

	f, err := fs.FileSystem.OpenFile(name, flag, perm)
	if err != nil {
		return nil, err
	}

	return &wrapper{File: f}, nil
}

type wrapper struct {
	webdav.File
}

func (w *wrapper) Readdir(count int) ([]os.FileInfo, error) {
	infos, err := w.File.Readdir(count)
	if err != nil {
		return nil, err
	}
	var goodInfos []os.FileInfo

	for _, info := range infos {
		if isThumbnail(info.Name()) {
			continue
		}

		goodInfos = append(goodInfos, info)
	}

	return goodInfos, nil
}

func isThumbnail(name string) bool {
	base := strings.TrimSuffix(filepath.Base(name), filepath.Ext(name))
	var v schema.Varint
	consumed, err := v.Decode(base)
	if err != nil {
		return false
	}
	return len(base) > consumed
}

func init() {
	register(func(mux *http.ServeMux, c *ServerConfig) {
		mux.Handle("/api/dav/", &webdav.Handler{
			Prefix: "/api/dav",
			FileSystem: &PixFS{
				FileSystem: webdav.Dir(c.PixPath),
				DB:         c.DB,
			},
			LockSystem: webdav.NewMemLS(),
		})
	})
}
<|endoftext|>


<commit_before>package httpclient

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"net/url"
	"reflect"
	"strings"
	"testing"

	"github.com/golang/mock/gomock"
)

type responseTestCase struct {
	returnResponse *http.Response
	returnErr      error
	expectedResp   *http.Response
	expectedErr    error
}

func TestNewContextCanWrapDefaultClient(t *testing.T) {
	clientContext := NewContext(http.DefaultClient)
	if _, ok := clientContext.(ClientContext); !ok {
		t.Error("http.DefaultClient can not be wrapped with ClientContext")
	}
}

func TestClientContextGetContextAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"returns response": {
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			ctx := context.TODO()
			req, err := http.NewRequest("GET", "http://test.com", nil)
			if err != nil {
				panic(err)
			}
			req = req.WithContext(ctx)

			mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.expectedResp, tt.expectedErr)
			resp, err := client.GetContext(ctx, "http://test.com")
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if !reflect.DeepEqual(err, tt.expectedErr) {
				t.Errorf("Incorrect error;\n\texpected: %#v\n\t     got: %#v", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextPostAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"returns response": {
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			ctx := context.TODO()
			contentType := "text/html"
			body := bytes.NewBufferString("")
			req, err := http.NewRequest("POST", "http://test.com", body)
			if err != nil {
				panic(err)
			}
			req.Header.Set("content-type", contentType)
			req = req.WithContext(ctx)

			mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			resp, err := client.PostContext(ctx, "http://test.com", contentType, body)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if !reflect.DeepEqual(err, tt.expectedErr) {
				t.Errorf("Incorrect error;\n\texpected: %#v\n\t     got: %#v", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextHeadAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"returns response": {
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			ctx := context.TODO()
			req, err := http.NewRequest("HEAD", "http://test.com", nil)
			if err != nil {
				panic(err)
			}
			req = req.WithContext(ctx)

			mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			resp, err := client.HeadContext(ctx, "http://test.com")
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if !reflect.DeepEqual(err, tt.expectedErr) {
				t.Errorf("Incorrect error;\n\texpected: %#v\n\t     got: %#v", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextPostFormAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"returns response": {
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			var values url.Values
			ctx := context.TODO()
			contentType := "application/x-www-form-urlencoded"
			body := strings.NewReader(values.Encode())
			req, err := http.NewRequest("POST", "http://test.com", body)
			if err != nil {
				panic(err)
			}
			req.Header.Set("content-type", contentType)
			req = req.WithContext(ctx)

			mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			resp, err := client.PostFormContext(ctx, "http://test.com", values)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if !reflect.DeepEqual(err, tt.expectedErr) {
				t.Errorf("Incorrect error;\n\texpected: %#v\n\t     got: %#v", tt.expectedErr, err)
			}
		})
	}
}

type reqMatcher struct {
	x *http.Request
}

var _ gomock.Matcher = reqMatcher{}

func (m reqMatcher) Matches(i interface{}) bool {
	x, ok := i.(*http.Request)
	if !ok {
		return false
	}

	r := true
	r = r && m.x.Method == x.Method
	r = r && m.x.URL.String() == x.URL.String()
	r = r && m.x.Header.Get("content-type") == x.Header.Get("content-type")
	r = r && reflect.DeepEqual(m.x.Body, x.Body)
	r = r && m.x.Context() == x.Context()
	return r
}

func (m reqMatcher) String() string {
	return fmt.Sprintf("is equal to %v", m.x)
}
<commit_msg>Test error cases when creating a new request<commit_after>package httpclient

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"net/url"
	"reflect"
	"strings"
	"testing"

	"github.com/golang/mock/gomock"
)

type responseTestCase struct {
	url            string
	shouldMock     bool
	returnResponse *http.Response
	returnErr      error
	expectedResp   *http.Response
	expectedErr    error
}

func TestNewContextCanWrapDefaultClient(t *testing.T) {
	clientContext := NewContext(http.DefaultClient)
	if _, ok := clientContext.(ClientContext); !ok {
		t.Error("http.DefaultClient can not be wrapped with ClientContext")
	}
}

func TestClientContextGetContextAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"malformed url": {
			url:         "://malformed",
			shouldMock:  false,
			expectedErr: fmt.Errorf("parse ://malformed: missing protocol scheme"),
		},
		"returns response": {
			url:            "http://test.com",
			shouldMock:     true,
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			url:         "http://test.com",
			shouldMock:  true,
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)
			ctx := context.TODO()

			if tt.shouldMock {
				req, err := http.NewRequest("GET", tt.url, nil)
				if err != nil {
					panic(err)
				}
				req = req.WithContext(ctx)

				mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.expectedResp, tt.expectedErr)
			}

			resp, err := client.GetContext(ctx, tt.url)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if (err != nil || tt.expectedErr != nil) && err.Error() != tt.expectedErr.Error() {
				t.Errorf("Incorrect error;\n\texpected: %s\n\t     got: %s", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextPostAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"malformed url": {
			url:         "://malformed",
			shouldMock:  false,
			expectedErr: fmt.Errorf("parse ://malformed: missing protocol scheme"),
		},
		"returns response": {
			url:            "http://test.com",
			shouldMock:     true,
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			url:         "http://test.com",
			shouldMock:  true,
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			ctx := context.TODO()
			contentType := "text/html"
			body := bytes.NewBufferString("")

			if tt.shouldMock {
				req, err := http.NewRequest("POST", tt.url, body)
				if err != nil {
					panic(err)
				}
				req.Header.Set("content-type", contentType)
				req = req.WithContext(ctx)

				mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			}

			resp, err := client.PostContext(ctx, tt.url, contentType, body)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if (err != nil || tt.expectedErr != nil) && err.Error() != tt.expectedErr.Error() {
				t.Errorf("Incorrect error;\n\texpected: %s\n\t     got: %s", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextHeadAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"malformed url": {
			url:         "://malformed",
			shouldMock:  false,
			expectedErr: fmt.Errorf("parse ://malformed: missing protocol scheme"),
		},
		"returns response": {
			url:            "http://test.com",
			shouldMock:     true,
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			url:         "http://test.com",
			shouldMock:  true,
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			ctx := context.TODO()

			if tt.shouldMock {
				req, err := http.NewRequest("HEAD", tt.url, nil)
				if err != nil {
					panic(err)
				}
				req = req.WithContext(ctx)

				mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			}

			resp, err := client.HeadContext(ctx, tt.url)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if (err != nil || tt.expectedErr != nil) && err.Error() != tt.expectedErr.Error() {
				t.Errorf("Incorrect error;\n\texpected: %s\n\t     got: %s", tt.expectedErr, err)
			}
		})
	}
}

func TestClientContextPostFormAddsContext(t *testing.T) {
	var testCases = map[string]responseTestCase{
		"malformed url": {
			url:         "://malformed",
			shouldMock:  false,
			expectedErr: fmt.Errorf("parse ://malformed: missing protocol scheme"),
		},
		"returns response": {
			url:            "http://test.com",
			shouldMock:     true,
			returnResponse: &http.Response{},
			expectedResp:   &http.Response{},
		},
		"returns error": {
			url:         "http://test.com",
			shouldMock:  true,
			returnErr:   fmt.Errorf("error"),
			expectedErr: fmt.Errorf("error"),
		},
	}

	for testName, tt := range testCases {
		t.Run(testName, func(t *testing.T) {
			mockCtrl := gomock.NewController(t)
			defer mockCtrl.Finish()

			mockClient := NewMockClient(mockCtrl)
			client := NewContext(mockClient)

			var values url.Values
			ctx := context.TODO()
			contentType := "application/x-www-form-urlencoded"
			body := strings.NewReader(values.Encode())

			if tt.shouldMock {
				req, err := http.NewRequest("POST", tt.url, body)
				if err != nil {
					panic(err)
				}
				req.Header.Set("content-type", contentType)
				req = req.WithContext(ctx)

				mockClient.EXPECT().Do(reqMatcher{req}).Return(tt.returnResponse, tt.returnErr)
			}

			resp, err := client.PostFormContext(ctx, tt.url, values)
			if !reflect.DeepEqual(resp, tt.expectedResp) {
				t.Errorf("Incorrect response;\n\texpected: %#v\n\t     got: %#v", tt.expectedResp, resp)
			}

			if (err != nil || tt.expectedErr != nil) && err.Error() != tt.expectedErr.Error() {
				t.Errorf("Incorrect error;\n\texpected: %s\n\t     got: %s", tt.expectedErr, err)
			}
		})
	}
}

type reqMatcher struct {
	x *http.Request
}

var _ gomock.Matcher = reqMatcher{}

func (m reqMatcher) Matches(i interface{}) bool {
	x, ok := i.(*http.Request)
	if !ok {
		return false
	}

	r := true
	r = r && m.x.Method == x.Method
	r = r && m.x.URL.String() == x.URL.String()
	r = r && m.x.Header.Get("content-type") == x.Header.Get("content-type")
	r = r && reflect.DeepEqual(m.x.Body, x.Body)
	r = r && m.x.Context() == x.Context()
	return r
}

func (m reqMatcher) String() string {
	return fmt.Sprintf("is equal to %v", m.x)
}
<|endoftext|>


<commit_before>package handlers

import (
	"errors"
	"fmt"
	"net/http"
	"strings"

	"appengine"
	"appengine/user"

	"code.google.com/p/xsrftoken"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type TagData struct {
	Posts   *[]Entry
	Tag     string
	Aliases []string
}

func TagHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	tag := r.Param("id")

	if tag == "" {
		http.Redirect(w, r.Request, "/tags", 301)
	}

	if tag != strings.ToLower(tag) {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", strings.ToLower(tag)), 301)
	}

	isAlias, alias := models.GetAlias(c, tag)
	if isAlias {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", alias), 301)
	}

	entries, err := models.PostsWithTag(c, tag)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	aliases := models.GetTagAliases(c, tag)
	data := &TagData{Posts: entries, Tag: tag, Aliases: *aliases}
	w.Render("tag", data)
}

type TagsData struct {
	Tags map[string]int
}

func TagsHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	w.Render("tags", &TagsData{Tags: models.AllTags(c)})
}

type AliasData struct {
	Aliases map[string]string
	Xsrf    string
	IsAdmin bool
}

func TagAliasGetHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		token := xsrftoken.Generate(models.GetFlagLogError(c, "SESSION_KEY"), u.String(), "/aliases")
		w.Render("aliases", &AliasData{
			Aliases: models.AliasMap(c),
			Xsrf:    token,
			IsAdmin: user.IsAdmin(c),
		})
		return
	}
}

func TagAliasPostHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		err := r.ParseForm()
		if err != nil {
			c.Warningf("Couldn't parse form: %v", r)
		}
		xsrf := r.Request.FormValue("xsrf")
		from := r.Request.FormValue("name")
		to := r.Request.FormValue("tag")

		if xsrftoken.Valid(xsrf, models.GetFlagLogError(c, "SESSION_KEY"), u.String(), r.Request.URL.Path) {
			c.Infof("Valid Token!")
			a := models.NewAlias(from, to)
			err = a.Save(c)
			if err != nil {
				http.Error(w, err.Error(), 500)
				return
			}
		} else {
			c.Infof("Invalid Token...")
			http.Error(w, errors.New("Invalid Token").Error(), 403)
			return
		}

		http.Redirect(w, r.Request, "/aliases", 302)
		return
	}
}
<commit_msg>maybe<commit_after>package handlers

import (
	"errors"
	"fmt"
	"net/http"
	"strings"

	"appengine"
	"appengine/user"

	"code.google.com/p/xsrftoken"

	"github.com/icco/natnatnat/models"
	"github.com/pilu/traffic"
)

type TagData struct {
	Posts   *[]models.Entry
	Tag     string
	Aliases []string
}

func TagHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	tag := r.Param("id")

	if tag == "" {
		http.Redirect(w, r.Request, "/tags", 301)
	}

	if tag != strings.ToLower(tag) {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", strings.ToLower(tag)), 301)
	}

	isAlias, alias := models.GetAlias(c, tag)
	if isAlias {
		http.Redirect(w, r.Request, fmt.Sprintf("/tags/%s", alias), 301)
	}

	entries, err := models.PostsWithTag(c, tag)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	aliases := models.GetTagAliases(c, tag)
	data := &TagData{Posts: entries, Tag: tag, Aliases: *aliases}
	w.Render("tag", data)
}

type TagsData struct {
	Tags map[string]int
}

func TagsHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	w.Render("tags", &TagsData{Tags: models.AllTags(c)})
}

type AliasData struct {
	Aliases map[string]string
	Xsrf    string
	IsAdmin bool
}

func TagAliasGetHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		token := xsrftoken.Generate(models.GetFlagLogError(c, "SESSION_KEY"), u.String(), "/aliases")
		w.Render("aliases", &AliasData{
			Aliases: models.AliasMap(c),
			Xsrf:    token,
			IsAdmin: user.IsAdmin(c),
		})
		return
	}
}

func TagAliasPostHandler(w traffic.ResponseWriter, r *traffic.Request) {
	c := appengine.NewContext(r.Request)
	u := user.Current(c)
	if u == nil {
		url, _ := user.LoginURL(c, "/aliases")
		http.Redirect(w, r.Request, url, 302)
		return
	} else {
		c.Infof("Logged in as: %s", u.String())
	}

	if u != nil && !user.IsAdmin(c) {
		http.Error(w, errors.New("Not a valid user.").Error(), 403)
		return
	} else {
		err := r.ParseForm()
		if err != nil {
			c.Warningf("Couldn't parse form: %v", r)
		}
		xsrf := r.Request.FormValue("xsrf")
		from := r.Request.FormValue("name")
		to := r.Request.FormValue("tag")

		if xsrftoken.Valid(xsrf, models.GetFlagLogError(c, "SESSION_KEY"), u.String(), r.Request.URL.Path) {
			c.Infof("Valid Token!")
			a := models.NewAlias(from, to)
			err = a.Save(c)
			if err != nil {
				http.Error(w, err.Error(), 500)
				return
			}
		} else {
			c.Infof("Invalid Token...")
			http.Error(w, errors.New("Invalid Token").Error(), 403)
			return
		}

		http.Redirect(w, r.Request, "/aliases", 302)
		return
	}
}
<|endoftext|>


<commit_before>package router

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
)

var params = []Param{
	{"name", "John"},
	{"age", "32"},
	{"gender", "M"},
}

var testParamsData = `[
  {
    "key": "name",
    "value": "John"
  },
  {
    "key": "age",
    "value": "32"
  },
  {
    "key": "gender",
    "value": "M"
  }
]`

func TestControlParamsSetGet(t *testing.T) {

	c := new(Control)
	c.Set(params...)
	for _, param := range params {
		if c.Get(param.Key) != param.Value {
			t.Error("Expected for", param.Key, ":", param.Value, ", got", c.Get(param.Key))
		}
	}
}

func TestControlCode(t *testing.T) {
	c := new(Control)
	// code transcends, must be less than 600
	c.Code(606)
	if c.code != 0 {
		t.Error("Expected code", "0", "got", c.code)
	}
	c.Code(404)
	if c.code != 404 {
		t.Error("Expected code", "404", "got", c.code)
	}
}

func TestMetaData(t *testing.T) {
	req, err := http.NewRequest("GET", "module/:data", nil)
	if err != nil {
		t.Error(err)
	}
	hd := Header{
		APIVersion: "2.1",
	}
	c := new(Control)
	c.CompactJSON(true).UseMetaData()
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.APIVersion(hd.APIVersion).HeaderContext(hd.Context).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	hd.Context = "bart"
	hd.Method = "people.get"
	hd.ID = "id17"
	params := []Param{Param{Key: "userId", Value: "@me"}, Param{Key: "groupId", Value: "@self"}}
	hd.Params = params
	c.Set(params...).HeaderContext(hd.Context).Method(hd.Method).ID(hd.ID).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	altParams := map[string]string{"userId": "@me", "groupId": "@self"}
	hd.Params = altParams
	c.SetParams(altParams).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
}

func TestErrorData(t *testing.T) {
	req, err := http.NewRequest("GET", "module/:data", nil)
	if err != nil {
		t.Error(err)
	}
	ed := ErrorHeader{
		Code:    http.StatusBadRequest,
		Message: "Unexpected parameter :data",
	}
	c := new(Control)
	c.CompactJSON(true)
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.SetError(ed.Code, ed.Message).Body(nil)
	if content, err := json.Marshal(map[string]ErrorHeader{"error": ed}); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	errors := []Error{
		Error{Message: "File Not Found"},
	}
	ed.Errors = errors
	c.AddError(errors...).Body(nil)
	if content, err := json.Marshal(map[string]ErrorHeader{"error": ed}); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
}

func TestControlBody(t *testing.T) {
	req, err := http.NewRequest("GET", "hello/:name", nil)
	if err != nil {
		t.Error(err)
	}
	c := new(Control)
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.Body("Hello")
	if trw.Body.String() != "Hello" {
		t.Error("Expected", "Hello", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(123)
	if trw.Body.String() != "123" {
		t.Error("Expected", "123", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(123.1)
	if trw.Body.String() != "123.1" {
		t.Error("Expected", "123.1", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(params)
	if trw.Body.String() != testParamsData {
		t.Error("Expected", testParamsData, "got", trw.Body.String())
	}
}
<commit_msg>Simplify code<commit_after>package router

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
)

var params = []Param{
	{"name", "John"},
	{"age", "32"},
	{"gender", "M"},
}

var testParamsData = `[
  {
    "key": "name",
    "value": "John"
  },
  {
    "key": "age",
    "value": "32"
  },
  {
    "key": "gender",
    "value": "M"
  }
]`

func TestControlParamsSetGet(t *testing.T) {

	c := new(Control)
	c.Set(params...)
	for _, param := range params {
		if c.Get(param.Key) != param.Value {
			t.Error("Expected for", param.Key, ":", param.Value, ", got", c.Get(param.Key))
		}
	}
}

func TestControlCode(t *testing.T) {
	c := new(Control)
	// code transcends, must be less than 600
	c.Code(606)
	if c.code != 0 {
		t.Error("Expected code", "0", "got", c.code)
	}
	c.Code(404)
	if c.code != 404 {
		t.Error("Expected code", "404", "got", c.code)
	}
}

func TestMetaData(t *testing.T) {
	req, err := http.NewRequest("GET", "module/:data", nil)
	if err != nil {
		t.Error(err)
	}
	hd := Header{
		APIVersion: "2.1",
	}
	c := new(Control)
	c.CompactJSON(true).UseMetaData()
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.APIVersion(hd.APIVersion).HeaderContext(hd.Context).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	hd.Context = "bart"
	hd.Method = "people.get"
	hd.ID = "id17"
	params := []Param{{Key: "userId", Value: "@me"}, {Key: "groupId", Value: "@self"}}
	hd.Params = params
	c.Set(params...).HeaderContext(hd.Context).Method(hd.Method).ID(hd.ID).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	altParams := map[string]string{"userId": "@me", "groupId": "@self"}
	hd.Params = altParams
	c.SetParams(altParams).Body(nil)
	if content, err := json.Marshal(hd); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
}

func TestErrorData(t *testing.T) {
	req, err := http.NewRequest("GET", "module/:data", nil)
	if err != nil {
		t.Error(err)
	}
	ed := ErrorHeader{
		Code:    http.StatusBadRequest,
		Message: "Unexpected parameter :data",
	}
	c := new(Control)
	c.CompactJSON(true)
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.SetError(ed.Code, ed.Message).Body(nil)
	if content, err := json.Marshal(map[string]ErrorHeader{"error": ed}); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	errors := []Error{
		{Message: "File Not Found"},
	}
	ed.Errors = errors
	c.AddError(errors...).Body(nil)
	if content, err := json.Marshal(map[string]ErrorHeader{"error": ed}); err == nil {
		if trw.Body.String() != string(content) {
			t.Error("Expected", string(content), "got", trw.Body.String())
		}
	} else {
		t.Error(err)
	}
}

func TestControlBody(t *testing.T) {
	req, err := http.NewRequest("GET", "hello/:name", nil)
	if err != nil {
		t.Error(err)
	}
	c := new(Control)
	trw := httptest.NewRecorder()
	c.Writer, c.Request = trw, req
	c.Body("Hello")
	if trw.Body.String() != "Hello" {
		t.Error("Expected", "Hello", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(123)
	if trw.Body.String() != "123" {
		t.Error("Expected", "123", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(123.1)
	if trw.Body.String() != "123.1" {
		t.Error("Expected", "123.1", "got", trw.Body.String())
	}
	trw = httptest.NewRecorder()
	c.Writer = trw
	c.Body(params)
	if trw.Body.String() != testParamsData {
		t.Error("Expected", testParamsData, "got", trw.Body.String())
	}
}
<|endoftext|>


<commit_before>package missinggo

import "net/url"

// Returns URL opaque as an unrooted path.
func URLOpaquePath(u *url.URL) string {
	if u.Opaque != "" {
		return u.Opaque
	}
	return u.Path
}
<commit_msg>Add CleanURLPath and URLJoinSubPath<commit_after>package missinggo

import (
	"net/url"
	"path"
)

// Returns URL opaque as an unrooted path.
func URLOpaquePath(u *url.URL) string {
	if u.Opaque != "" {
		return u.Opaque
	}
	return u.Path
}

// Cleans the (absolute) URL path, removing unnecessary . and .. elements. See
// "net/http".cleanPath.
func CleanURLPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}
	cp := path.Clean(p)
	// Add the trailing slash back, as it's relevant to a URL.
	if p[len(p)-1] == '/' && cp != "/" {
		cp += "/"
	}
	return cp
}

func URLJoinSubPath(base, rel string) string {
	baseURL, err := url.Parse(base)
	if err != nil {
		// Honey badger doesn't give a fuck.
		panic(err)
	}
	rel = CleanURLPath(rel)
	baseURL.Path = path.Join(baseURL.Path, rel)
	return baseURL.String()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"strings"

	"github.com/motemen/ghq/gitutil"
)

// Convert SCP-like URL to SSH URL(e.g. [user@]host.xz:path/to/repo.git/)
// ref. http://git-scm.com/docs/git-fetch#_git_urls
// (golang hasn't supported Perl-like negative look-behind match)
var (
	hasSchemePattern          = regexp.MustCompile("^[^:]+://")
	scpLikeURLPattern         = regexp.MustCompile("^([^@]+@)?([^:]+):(/?.+)$")
	looksLikeAuthorityPattern = regexp.MustCompile(`[A-Za-z0-9]\.[A-Za-z]+(?::\d{1,5})?$`)
)

func newURL(ref string) (*url.URL, error) {
	if !hasSchemePattern.MatchString(ref) {
		if scpLikeURLPattern.MatchString(ref) {
			matched := scpLikeURLPattern.FindStringSubmatch(ref)
			user := matched[1]
			host := matched[2]
			path := matched[3]

			ref = fmt.Sprintf("ssh://%s%s/%s", user, host, path)
		} else {
			// If ref is like "github.com/motemen/ghq" convert to "https://github.com/motemen/ghq"
			paths := strings.Split(ref, "/")
			if len(paths) > 1 && looksLikeAuthorityPattern.MatchString(paths[0]) {
				ref = "https://" + ref
			}
		}
	}

	url, err := url.Parse(ref)
	if err != nil {
		return url, err
	}

	if !url.IsAbs() {
		if !strings.Contains(url.Path, "/") {
			url.Path, err = fillUsernameToPath(url.Path)
			if err != nil {
				return url, err
			}
		}
		url.Scheme = "https"
		url.Host = "github.com"
		if url.Path[0] != '/' {
			url.Path = "/" + url.Path
		}
	}

	return url, nil
}

func convertGitURLHTTPToSSH(url *url.URL) (*url.URL, error) {
	user := "git"
	if url.User != nil {
		user = url.User.Username()
	}
	sshURL := fmt.Sprintf("ssh://%s@%s%s", user, url.Host, url.Path)
	return url.Parse(sshURL)
}

func fillUsernameToPath(path string) (string, error) {
	completeUser, err := gitutil.ConfigSingle("ghq.completeUser")
	if err != nil {
		return path, err
	}
	if completeUser == "false" {
		return path + "/" + path, nil
	}

	user, err := gitutil.ConfigSingle("ghq.user")
	if err != nil {
		return path, err
	}
	if user == "" {
		user = os.Getenv("GITHUB_USER")
	}
	if user == "" {
		switch runtime.GOOS {
		case "windows":
			user = os.Getenv("USERNAME")
		default:
			user = os.Getenv("USER")
		}
	}
	if user == "" {
		// Make the error if it does not match any pattern
		return path, fmt.Errorf("set ghq.user to your gitconfig")
	}
	path = user + "/" + path
	return path, nil
}
<commit_msg>remove extra / from ref when path has "/" prefix<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"strings"

	"github.com/motemen/ghq/gitutil"
)

// Convert SCP-like URL to SSH URL(e.g. [user@]host.xz:path/to/repo.git/)
// ref. http://git-scm.com/docs/git-fetch#_git_urls
// (golang hasn't supported Perl-like negative look-behind match)
var (
	hasSchemePattern          = regexp.MustCompile("^[^:]+://")
	scpLikeURLPattern         = regexp.MustCompile("^([^@]+@)?([^:]+):(/?.+)$")
	looksLikeAuthorityPattern = regexp.MustCompile(`[A-Za-z0-9]\.[A-Za-z]+(?::\d{1,5})?$`)
)

func newURL(ref string) (*url.URL, error) {
	if !hasSchemePattern.MatchString(ref) {
		if scpLikeURLPattern.MatchString(ref) {
			matched := scpLikeURLPattern.FindStringSubmatch(ref)
			user := matched[1]
			host := matched[2]
			path := matched[3]

			if strings.HasPrefix(path, "/") {
				ref = fmt.Sprintf("ssh://%s%s%s", user, host, path)
			} else {
				ref = fmt.Sprintf("ssh://%s%s/%s", user, host, path)
			}
		} else {
			// If ref is like "github.com/motemen/ghq" convert to "https://github.com/motemen/ghq"
			paths := strings.Split(ref, "/")
			if len(paths) > 1 && looksLikeAuthorityPattern.MatchString(paths[0]) {
				ref = "https://" + ref
			}
		}
	}

	url, err := url.Parse(ref)
	if err != nil {
		return url, err
	}

	if !url.IsAbs() {
		if !strings.Contains(url.Path, "/") {
			url.Path, err = fillUsernameToPath(url.Path)
			if err != nil {
				return url, err
			}
		}
		url.Scheme = "https"
		url.Host = "github.com"
		if url.Path[0] != '/' {
			url.Path = "/" + url.Path
		}
	}

	return url, nil
}

func convertGitURLHTTPToSSH(url *url.URL) (*url.URL, error) {
	user := "git"
	if url.User != nil {
		user = url.User.Username()
	}
	sshURL := fmt.Sprintf("ssh://%s@%s%s", user, url.Host, url.Path)
	return url.Parse(sshURL)
}

func fillUsernameToPath(path string) (string, error) {
	completeUser, err := gitutil.ConfigSingle("ghq.completeUser")
	if err != nil {
		return path, err
	}
	if completeUser == "false" {
		return path + "/" + path, nil
	}

	user, err := gitutil.ConfigSingle("ghq.user")
	if err != nil {
		return path, err
	}
	if user == "" {
		user = os.Getenv("GITHUB_USER")
	}
	if user == "" {
		switch runtime.GOOS {
		case "windows":
			user = os.Getenv("USERNAME")
		default:
			user = os.Getenv("USER")
		}
	}
	if user == "" {
		// Make the error if it does not match any pattern
		return path, fmt.Errorf("set ghq.user to your gitconfig")
	}
	path = user + "/" + path
	return path, nil
}
<|endoftext|>


<commit_before>package cidrutil

import (
	"fmt"
	"net"
	"strings"

	"github.com/hashicorp/vault/helper/strutil"
)

// IPBelongsToCIDR checks if the given IP is encompassed by the given CIDR block
func IPBelongsToCIDR(ipAddr string, cidr string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	ip := net.ParseIP(ipAddr)
	if ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	_, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		return false, err
	}

	if !ipnet.Contains(ip) {
		return false, nil
	}

	return true, nil
}

// IPBelongsToCIDRBlocksString checks if the given IP is encompassed by any of
// the given CIDR blocks, when the input is a string composed by joining all
// the CIDR blocks using a separator. The input is separated based on the given
// separator and the IP is checked to be belonged by any CIDR block.
func IPBelongsToCIDRBlocksString(ipAddr string, cidrList, separator string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	if cidrList == "" {
		return false, fmt.Errorf("missing CIDR list")
	}

	if separator == "" {
		return false, fmt.Errorf("missing separator")
	}

	if ip := net.ParseIP(ipAddr); ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	return IPBelongsToCIDRBlocksSlice(ipAddr, strutil.ParseDedupAndSortStrings(cidrList, separator))
}

// IPBelongsToCIDRBlocksSlice checks if the given IP is encompassed by any of the given
// CIDR blocks
func IPBelongsToCIDRBlocksSlice(ipAddr string, cidrs []string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	if len(cidrs) == 0 {
		return false, fmt.Errorf("missing CIDR blocks to be checked against")
	}

	if ip := net.ParseIP(ipAddr); ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	for _, cidr := range cidrs {
		belongs, err := IPBelongsToCIDR(ipAddr, cidr)
		if err != nil {
			return false, err
		}
		if belongs {
			return true, nil
		}
	}

	return false, nil
}

// ValidateCIDRListString checks if the list of CIDR blocks are valid, given
// that the input is a string composed by joining all the CIDR blocks using a
// separator. The input is separated based on the given separator and validity
// of each is checked.
func ValidateCIDRListString(cidrList string, separator string) (bool, error) {
	if cidrList == "" {
		return false, fmt.Errorf("missing CIDR list that needs validation")
	}
	if separator == "" {
		return false, fmt.Errorf("missing separator")
	}

	return ValidateCIDRListSlice(strutil.ParseDedupAndSortStrings(cidrList, separator))
}

// ValidateCIDRListSlice checks if the given list of CIDR blocks are valid
func ValidateCIDRListSlice(cidrBlocks []string) (bool, error) {
	if len(cidrBlocks) == 0 {
		return false, fmt.Errorf("missing CIDR blocks that needs validation")
	}

	for _, block := range cidrBlocks {
		if _, _, err := net.ParseCIDR(strings.TrimSpace(block)); err != nil {
			return false, err
		}
	}

	return true, nil
}

// Subset checks if the IPs belonging to a given CIDR block is a subset of IPs
// belonging to another CIDR block.
func Subset(cidr1, cidr2 string) (bool, error) {
	if cidr1 == "" {
		return false, fmt.Errorf("missing CIDR to be checked against")
	}

	if cidr2 == "" {
		return false, fmt.Errorf("missing CIDR that needs to be checked")
	}

	ip1, net1, err := net.ParseCIDR(cidr1)
	if err != nil {
		return false, fmt.Errorf("failed to parse the CIDR to be checked against: %q", err)
	}

	maskLen1, _ := net1.Mask.Size()
	if ip1.To4().String() != "0.0.0.0" && maskLen1 == 0 {
		return false, fmt.Errorf("CIDR to be checked against is not in its canonical form")
	}

	ip2, net2, err := net.ParseCIDR(cidr2)
	if err != nil {
		return false, fmt.Errorf("failed to parse the CIDR that needs to be checked: %q", err)
	}

	maskLen2, _ := net2.Mask.Size()
	if ip2.To4().String() != "0.0.0.0" && maskLen2 == 0 {
		return false, fmt.Errorf("CIDR that needs to be checked is not in its canonical form")
	}

	// If the mask length of the CIDR that needs to be checked is smaller
	// then the mask length of the CIDR to be checked against, then the
	// former will encompass more IPs than the latter, and hence can't be a
	// subset of the latter.
	if maskLen2 < maskLen1 {
		return false, nil
	}

	belongs, err := IPBelongsToCIDR(net2.IP.String(), cidr1)
	if err != nil {
		return false, err
	}

	return belongs, nil
}

// SubsetBlocks checks if each CIDR block of a given set of CIDR blocks, is a
// subset of at least one CIDR block belonging to another set of CIDR blocks.
// First parameter is the set of CIDR blocks to check against and the second
// parameter is the set of CIDR blocks that needs to be checked.
func SubsetBlocks(cidrBlocks1, cidrBlocks2 []string) (bool, error) {
	if len(cidrBlocks1) == 0 {
		return false, fmt.Errorf("missing CIDR blocks to be checked against")
	}

	if len(cidrBlocks2) == 0 {
		return false, fmt.Errorf("missing CIDR blocks that needs to be checked")
	}

	// Check if all the elements of cidrBlocks2 is a subset of at least one
	// element of cidrBlocks1
	for _, cidrBlock2 := range cidrBlocks2 {
		isSubset := false
		for _, cidrBlock1 := range cidrBlocks1 {
			subset, err := Subset(cidrBlock1, cidrBlock2)
			if err != nil {
				return false, err
			}
			// If CIDR is a subset of any of the CIDR block, its
			// good enough. Break out.
			if subset {
				isSubset = true
				break
			}
		}
		// CIDR block was not a subset of any of the CIDR blocks in the
		// set of blocks to check against
		if !isSubset {
			return false, nil
		}
	}

	return true, nil
}
<commit_msg>Use net.IPv4zero to check for zero address<commit_after>package cidrutil

import (
	"fmt"
	"net"
	"strings"

	"github.com/hashicorp/vault/helper/strutil"
)

// IPBelongsToCIDR checks if the given IP is encompassed by the given CIDR block
func IPBelongsToCIDR(ipAddr string, cidr string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	ip := net.ParseIP(ipAddr)
	if ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	_, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		return false, err
	}

	if !ipnet.Contains(ip) {
		return false, nil
	}

	return true, nil
}

// IPBelongsToCIDRBlocksString checks if the given IP is encompassed by any of
// the given CIDR blocks, when the input is a string composed by joining all
// the CIDR blocks using a separator. The input is separated based on the given
// separator and the IP is checked to be belonged by any CIDR block.
func IPBelongsToCIDRBlocksString(ipAddr string, cidrList, separator string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	if cidrList == "" {
		return false, fmt.Errorf("missing CIDR list")
	}

	if separator == "" {
		return false, fmt.Errorf("missing separator")
	}

	if ip := net.ParseIP(ipAddr); ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	return IPBelongsToCIDRBlocksSlice(ipAddr, strutil.ParseDedupAndSortStrings(cidrList, separator))
}

// IPBelongsToCIDRBlocksSlice checks if the given IP is encompassed by any of the given
// CIDR blocks
func IPBelongsToCIDRBlocksSlice(ipAddr string, cidrs []string) (bool, error) {
	if ipAddr == "" {
		return false, fmt.Errorf("missing IP address")
	}

	if len(cidrs) == 0 {
		return false, fmt.Errorf("missing CIDR blocks to be checked against")
	}

	if ip := net.ParseIP(ipAddr); ip == nil {
		return false, fmt.Errorf("invalid IP address")
	}

	for _, cidr := range cidrs {
		belongs, err := IPBelongsToCIDR(ipAddr, cidr)
		if err != nil {
			return false, err
		}
		if belongs {
			return true, nil
		}
	}

	return false, nil
}

// ValidateCIDRListString checks if the list of CIDR blocks are valid, given
// that the input is a string composed by joining all the CIDR blocks using a
// separator. The input is separated based on the given separator and validity
// of each is checked.
func ValidateCIDRListString(cidrList string, separator string) (bool, error) {
	if cidrList == "" {
		return false, fmt.Errorf("missing CIDR list that needs validation")
	}
	if separator == "" {
		return false, fmt.Errorf("missing separator")
	}

	return ValidateCIDRListSlice(strutil.ParseDedupAndSortStrings(cidrList, separator))
}

// ValidateCIDRListSlice checks if the given list of CIDR blocks are valid
func ValidateCIDRListSlice(cidrBlocks []string) (bool, error) {
	if len(cidrBlocks) == 0 {
		return false, fmt.Errorf("missing CIDR blocks that needs validation")
	}

	for _, block := range cidrBlocks {
		if _, _, err := net.ParseCIDR(strings.TrimSpace(block)); err != nil {
			return false, err
		}
	}

	return true, nil
}

// Subset checks if the IPs belonging to a given CIDR block is a subset of IPs
// belonging to another CIDR block.
func Subset(cidr1, cidr2 string) (bool, error) {
	if cidr1 == "" {
		return false, fmt.Errorf("missing CIDR to be checked against")
	}

	if cidr2 == "" {
		return false, fmt.Errorf("missing CIDR that needs to be checked")
	}

	ip1, net1, err := net.ParseCIDR(cidr1)
	if err != nil {
		return false, fmt.Errorf("failed to parse the CIDR to be checked against: %q", err)
	}

	maskLen1, _ := net1.Mask.Size()
	if ip1.To4().Equal(net.IPv4zero) && maskLen1 == 0 {
		return false, fmt.Errorf("CIDR to be checked against is not in its canonical form")
	}

	ip2, net2, err := net.ParseCIDR(cidr2)
	if err != nil {
		return false, fmt.Errorf("failed to parse the CIDR that needs to be checked: %q", err)
	}

	maskLen2, _ := net2.Mask.Size()
	if ip2.To4().Equal(net.IPv4zero) && maskLen2 == 0 {
		return false, fmt.Errorf("CIDR that needs to be checked is not in its canonical form")
	}

	// If the mask length of the CIDR that needs to be checked is smaller
	// then the mask length of the CIDR to be checked against, then the
	// former will encompass more IPs than the latter, and hence can't be a
	// subset of the latter.
	if maskLen2 < maskLen1 {
		return false, nil
	}

	belongs, err := IPBelongsToCIDR(net2.IP.String(), cidr1)
	if err != nil {
		return false, err
	}

	return belongs, nil
}

// SubsetBlocks checks if each CIDR block of a given set of CIDR blocks, is a
// subset of at least one CIDR block belonging to another set of CIDR blocks.
// First parameter is the set of CIDR blocks to check against and the second
// parameter is the set of CIDR blocks that needs to be checked.
func SubsetBlocks(cidrBlocks1, cidrBlocks2 []string) (bool, error) {
	if len(cidrBlocks1) == 0 {
		return false, fmt.Errorf("missing CIDR blocks to be checked against")
	}

	if len(cidrBlocks2) == 0 {
		return false, fmt.Errorf("missing CIDR blocks that needs to be checked")
	}

	// Check if all the elements of cidrBlocks2 is a subset of at least one
	// element of cidrBlocks1
	for _, cidrBlock2 := range cidrBlocks2 {
		isSubset := false
		for _, cidrBlock1 := range cidrBlocks1 {
			subset, err := Subset(cidrBlock1, cidrBlock2)
			if err != nil {
				return false, err
			}
			// If CIDR is a subset of any of the CIDR block, its
			// good enough. Break out.
			if subset {
				isSubset = true
				break
			}
		}
		// CIDR block was not a subset of any of the CIDR blocks in the
		// set of blocks to check against
		if !isSubset {
			return false, nil
		}
	}

	return true, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package templates

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

func init() {
	caddy.RegisterModule(Templates{})
}

// Templates is a middleware which executes response bodies as Go templates.
// The syntax is documented in the Go standard library's
// [text/template package](https://golang.org/pkg/text/template/).
//
// ⚠ Template functions/actions are still experimental, so they are subject to change.
//
// [All Sprig functions](https://masterminds.github.io/sprig/) are supported.
//
// In addition to the standard functions and the Sprig library, Caddy adds
// extra functions and data that are available to a template:
//
// ##### `.Args`
//
// Access arguments passed to this page/context, for example as the result of a `include`.
//
// ```
// {{.Args 0}} // first argument
// ```
//
// ##### `.Cookie`
//
// Gets the value of a cookie by name.
//
// ```
// {{.Cookie "cookiename"}}
// ```
//
// ##### `env`
//
// Gets an environment variable.
//
// ```
// {{env "VAR_NAME"}}
// ```
//
// ##### `placeholder`
//
// Gets an [placeholder variable](/docs/conventions#placeholders).
// The braces (`{}`) have to be omitted.
//
// ```
// {{placeholder "http.request.uri.path"}}
// {{placeholder "http.error.status_code"}}
// ```
//
// ##### `.Host`
//
// Returns the hostname portion (no port) of the Host header of the HTTP request.
//
// ```
// {{.Host}}
// ```
//
// ##### `httpInclude`
//
// Includes the contents of another file by making a virtual HTTP request (also known as a sub-request). The URI path must exist on the same virtual server because the request does not use sockets; instead, the request is crafted in memory and the handler is invoked directly for increased efficiency.
//
// ```
// {{httpInclude "/foo/bar?q=val"}}
// ```
//
// ##### `import`
//
// Imports the contents of another file and adds any template definitions to the template stack. If there are no defitions, the filepath will be the defition name. Any {{ define }} blocks will be accessible by {{ template }} or {{ block }}. Imports must happen before the template or block action is called
//
// **filename.html**
// ```
// {{ define "main" }}
// content
// {{ end }}
//
// **index.html**
// ```
// {{ import "/path/to/file.html" }}
// {{ template "main" }}
// ```
//
// ##### `include`
//
// Includes the contents of another file and renders in-place. Optionally can pass key-value pairs as arguments to be accessed by the included file.
//
// ```
// {{include "path/to/file.html"}}  // no arguments
// {{include "path/to/file.html" "arg1" 2 "value 3"}}  // with arguments
// ```
//
// ##### `listFiles`
//
// Returns a list of the files in the given directory, which is relative to the template context's file root.
//
// ```
// {{listFiles "/mydir"}}
// ```
//
// ##### `markdown`
//
// Renders the given Markdown text as HTML. This uses the
// [Goldmark](https://github.com/yuin/goldmark) library,
// which is CommonMark compliant. It also has these plugins
// enabled: Github Flavored Markdown, Footnote and syntax
// highlighting provided by [Chroma](https://github.com/alecthomas/chroma).
//
// ```
// {{markdown "My _markdown_ text"}}
// ```
//
// ##### `.RemoteIP`
//
// Returns the client's IP address.
//
// ```
// {{.RemoteIP}}
// ```
//
// ##### `.Req`
//
// Accesses the current HTTP request, which has various fields, including:
//
//    - `.Method` - the method
//    - `.URL` - the URL, which in turn has component fields (Scheme, Host, Path, etc.)
//    - `.Header` - the header fields
//    - `.Host` - the Host or :authority header of the request
//
// ```
// {{.Req.Header.Get "User-Agent"}}
// ```
//
// ##### `.OriginalReq`
//
// Like .Req, except it accesses the original HTTP request before rewrites or other internal modifications.
//
// ##### `.RespHeader.Add`
//
// Adds a header field to the HTTP response.
//
// ```
// {{.RespHeader.Add "Field-Name" "val"}}
// ```
//
// ##### `.RespHeader.Del`
//
// Deletes a header field on the HTTP response.
//
// ```
// {{.RespHeader.Del "Field-Name"}}
// ```
//
// ##### `.RespHeader.Set`
//
// Sets a header field on the HTTP response, replacing any existing value.
//
// ```
// {{.RespHeader.Set "Field-Name" "val"}}
// ```
//
// ##### `splitFrontMatter`
//
// Splits front matter out from the body. Front matter is metadata that appears at the very beginning of a file or string. Front matter can be in YAML, TOML, or JSON formats:
//
// **TOML** front matter starts and ends with `+++`:
//
// ```
// +++
// template = "blog"
// title = "Blog Homepage"
// sitename = "A Caddy site"
// +++
// ```
//
// **YAML** is surrounded by `---`:
//
// ```
// ---
// template: blog
// title: Blog Homepage
// sitename: A Caddy site
// ---
// ```
//
//
// **JSON** is simply `{` and `}`:
//
// ```
// {
// 	"template": "blog",
// 	"title": "Blog Homepage",
// 	"sitename": "A Caddy site"
// }
// ```
//
// The resulting front matter will be made available like so:
//
// - `.Meta` to access the metadata fields, for example: `{{$parsed.Meta.title}}`
// - `.Body` to access the body after the front matter, for example: `{{markdown $parsed.Body}}`
//
//
// ##### `stripHTML`
//
// Removes HTML from a string.
//
// ```
// {{stripHTML "Shows <b>only</b> text content"}}
// ```
//
type Templates struct {
	// The root path from which to load files. Required if template functions
	// accessing the file system are used (such as include). Default is
	// `{http.vars.root}` if set, or current working directory otherwise.
	FileRoot string `json:"file_root,omitempty"`

	// The MIME types for which to render templates. It is important to use
	// this if the route matchers do not exclude images or other binary files.
	// Default is text/plain, text/markdown, and text/html.
	MIMETypes []string `json:"mime_types,omitempty"`

	// The template action delimiters. If set, must be precisely two elements:
	// the opening and closing delimiters. Default: `["{{", "}}"]`
	Delimiters []string `json:"delimiters,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (Templates) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.templates",
		New: func() caddy.Module { return new(Templates) },
	}
}

// Provision provisions t.
func (t *Templates) Provision(ctx caddy.Context) error {
	if t.MIMETypes == nil {
		t.MIMETypes = defaultMIMETypes
	}
	if t.FileRoot == "" {
		t.FileRoot = "{http.vars.root}"
	}
	return nil
}

// Validate ensures t has a valid configuration.
func (t *Templates) Validate() error {
	if len(t.Delimiters) != 0 && len(t.Delimiters) != 2 {
		return fmt.Errorf("delimiters must consist of exactly two elements: opening and closing")
	}
	return nil
}

func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	buf := bufPool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufPool.Put(buf)

	// shouldBuf determines whether to execute templates on this response,
	// since generally we will not want to execute for images or CSS, etc.
	shouldBuf := func(status int, header http.Header) bool {
		ct := header.Get("Content-Type")
		for _, mt := range t.MIMETypes {
			if strings.Contains(ct, mt) {
				return true
			}
		}
		return false
	}

	rec := caddyhttp.NewResponseRecorder(w, buf, shouldBuf)

	err := next.ServeHTTP(rec, r)
	if err != nil {
		return err
	}
	if !rec.Buffered() {
		return nil
	}

	err = t.executeTemplate(rec, r)
	if err != nil {
		return err
	}

	rec.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
	rec.Header().Del("Accept-Ranges") // we don't know ranges for dynamically-created content
	rec.Header().Del("Last-Modified") // useless for dynamic content since it's always changing

	// we don't know a way to quickly generate etag for dynamic content,
	// and weak etags still cause browsers to rely on it even after a
	// refresh, so disable them until we find a better way to do this
	rec.Header().Del("Etag")

	return rec.WriteResponse()
}

// executeTemplate executes the template contained in wb.buf and replaces it with the results.
func (t *Templates) executeTemplate(rr caddyhttp.ResponseRecorder, r *http.Request) error {
	var fs http.FileSystem
	if t.FileRoot != "" {
		repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
		fs = http.Dir(repl.ReplaceAll(t.FileRoot, "."))
	}

	ctx := &TemplateContext{
		Root:       fs,
		Req:        r,
		RespHeader: WrappedHeader{rr.Header()},
		config:     t,
	}

	err := ctx.executeTemplateInBuffer(r.URL.Path, rr.Buffer())
	if err != nil {
		// templates may return a custom HTTP error to be propagated to the client,
		// otherwise for any other error we assume the template is broken
		var handlerErr caddyhttp.HandlerError
		if errors.As(err, &handlerErr) {
			return handlerErr
		}
		return caddyhttp.Error(http.StatusInternalServerError, err)
	}

	return nil
}

// virtualResponseWriter is used in virtualized HTTP requests
// that templates may execute.
type virtualResponseWriter struct {
	status int
	header http.Header
	body   *bytes.Buffer
}

func (vrw *virtualResponseWriter) Header() http.Header {
	return vrw.header
}

func (vrw *virtualResponseWriter) WriteHeader(statusCode int) {
	vrw.status = statusCode
}

func (vrw *virtualResponseWriter) Write(data []byte) (int, error) {
	return vrw.body.Write(data)
}

var defaultMIMETypes = []string{
	"text/html",
	"text/plain",
	"text/markdown",
}

// Interface guards
var (
	_ caddy.Provisioner           = (*Templates)(nil)
	_ caddy.Validator             = (*Templates)(nil)
	_ caddyhttp.MiddlewareHandler = (*Templates)(nil)
)
<commit_msg>templates: Fix docs for .Args<commit_after>// Copyright 2015 Matthew Holt and The Caddy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package templates

import (
	"bytes"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

func init() {
	caddy.RegisterModule(Templates{})
}

// Templates is a middleware which executes response bodies as Go templates.
// The syntax is documented in the Go standard library's
// [text/template package](https://golang.org/pkg/text/template/).
//
// ⚠ Template functions/actions are still experimental, so they are subject to change.
//
// [All Sprig functions](https://masterminds.github.io/sprig/) are supported.
//
// In addition to the standard functions and the Sprig library, Caddy adds
// extra functions and data that are available to a template:
//
// ##### `.Args`
//
// A slice of arguments passed to this page/context, for example as the result of a `include`.
//
// ```
// {{index .Args 0}} // first argument
// ```
//
// ##### `.Cookie`
//
// Gets the value of a cookie by name.
//
// ```
// {{.Cookie "cookiename"}}
// ```
//
// ##### `env`
//
// Gets an environment variable.
//
// ```
// {{env "VAR_NAME"}}
// ```
//
// ##### `placeholder`
//
// Gets an [placeholder variable](/docs/conventions#placeholders).
// The braces (`{}`) have to be omitted.
//
// ```
// {{placeholder "http.request.uri.path"}}
// {{placeholder "http.error.status_code"}}
// ```
//
// ##### `.Host`
//
// Returns the hostname portion (no port) of the Host header of the HTTP request.
//
// ```
// {{.Host}}
// ```
//
// ##### `httpInclude`
//
// Includes the contents of another file by making a virtual HTTP request (also known as a sub-request). The URI path must exist on the same virtual server because the request does not use sockets; instead, the request is crafted in memory and the handler is invoked directly for increased efficiency.
//
// ```
// {{httpInclude "/foo/bar?q=val"}}
// ```
//
// ##### `import`
//
// Imports the contents of another file and adds any template definitions to the template stack. If there are no defitions, the filepath will be the defition name. Any {{ define }} blocks will be accessible by {{ template }} or {{ block }}. Imports must happen before the template or block action is called
//
// **filename.html**
// ```
// {{ define "main" }}
// content
// {{ end }}
//
// **index.html**
// ```
// {{ import "/path/to/file.html" }}
// {{ template "main" }}
// ```
//
// ##### `include`
//
// Includes the contents of another file and renders in-place. Optionally can pass key-value pairs as arguments to be accessed by the included file.
//
// ```
// {{include "path/to/file.html"}}  // no arguments
// {{include "path/to/file.html" "arg1" 2 "value 3"}}  // with arguments
// ```
//
// ##### `listFiles`
//
// Returns a list of the files in the given directory, which is relative to the template context's file root.
//
// ```
// {{listFiles "/mydir"}}
// ```
//
// ##### `markdown`
//
// Renders the given Markdown text as HTML. This uses the
// [Goldmark](https://github.com/yuin/goldmark) library,
// which is CommonMark compliant. It also has these plugins
// enabled: Github Flavored Markdown, Footnote and syntax
// highlighting provided by [Chroma](https://github.com/alecthomas/chroma).
//
// ```
// {{markdown "My _markdown_ text"}}
// ```
//
// ##### `.RemoteIP`
//
// Returns the client's IP address.
//
// ```
// {{.RemoteIP}}
// ```
//
// ##### `.Req`
//
// Accesses the current HTTP request, which has various fields, including:
//
//    - `.Method` - the method
//    - `.URL` - the URL, which in turn has component fields (Scheme, Host, Path, etc.)
//    - `.Header` - the header fields
//    - `.Host` - the Host or :authority header of the request
//
// ```
// {{.Req.Header.Get "User-Agent"}}
// ```
//
// ##### `.OriginalReq`
//
// Like .Req, except it accesses the original HTTP request before rewrites or other internal modifications.
//
// ##### `.RespHeader.Add`
//
// Adds a header field to the HTTP response.
//
// ```
// {{.RespHeader.Add "Field-Name" "val"}}
// ```
//
// ##### `.RespHeader.Del`
//
// Deletes a header field on the HTTP response.
//
// ```
// {{.RespHeader.Del "Field-Name"}}
// ```
//
// ##### `.RespHeader.Set`
//
// Sets a header field on the HTTP response, replacing any existing value.
//
// ```
// {{.RespHeader.Set "Field-Name" "val"}}
// ```
//
// ##### `splitFrontMatter`
//
// Splits front matter out from the body. Front matter is metadata that appears at the very beginning of a file or string. Front matter can be in YAML, TOML, or JSON formats:
//
// **TOML** front matter starts and ends with `+++`:
//
// ```
// +++
// template = "blog"
// title = "Blog Homepage"
// sitename = "A Caddy site"
// +++
// ```
//
// **YAML** is surrounded by `---`:
//
// ```
// ---
// template: blog
// title: Blog Homepage
// sitename: A Caddy site
// ---
// ```
//
//
// **JSON** is simply `{` and `}`:
//
// ```
// {
// 	"template": "blog",
// 	"title": "Blog Homepage",
// 	"sitename": "A Caddy site"
// }
// ```
//
// The resulting front matter will be made available like so:
//
// - `.Meta` to access the metadata fields, for example: `{{$parsed.Meta.title}}`
// - `.Body` to access the body after the front matter, for example: `{{markdown $parsed.Body}}`
//
//
// ##### `stripHTML`
//
// Removes HTML from a string.
//
// ```
// {{stripHTML "Shows <b>only</b> text content"}}
// ```
//
type Templates struct {
	// The root path from which to load files. Required if template functions
	// accessing the file system are used (such as include). Default is
	// `{http.vars.root}` if set, or current working directory otherwise.
	FileRoot string `json:"file_root,omitempty"`

	// The MIME types for which to render templates. It is important to use
	// this if the route matchers do not exclude images or other binary files.
	// Default is text/plain, text/markdown, and text/html.
	MIMETypes []string `json:"mime_types,omitempty"`

	// The template action delimiters. If set, must be precisely two elements:
	// the opening and closing delimiters. Default: `["{{", "}}"]`
	Delimiters []string `json:"delimiters,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (Templates) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.templates",
		New: func() caddy.Module { return new(Templates) },
	}
}

// Provision provisions t.
func (t *Templates) Provision(ctx caddy.Context) error {
	if t.MIMETypes == nil {
		t.MIMETypes = defaultMIMETypes
	}
	if t.FileRoot == "" {
		t.FileRoot = "{http.vars.root}"
	}
	return nil
}

// Validate ensures t has a valid configuration.
func (t *Templates) Validate() error {
	if len(t.Delimiters) != 0 && len(t.Delimiters) != 2 {
		return fmt.Errorf("delimiters must consist of exactly two elements: opening and closing")
	}
	return nil
}

func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	buf := bufPool.Get().(*bytes.Buffer)
	buf.Reset()
	defer bufPool.Put(buf)

	// shouldBuf determines whether to execute templates on this response,
	// since generally we will not want to execute for images or CSS, etc.
	shouldBuf := func(status int, header http.Header) bool {
		ct := header.Get("Content-Type")
		for _, mt := range t.MIMETypes {
			if strings.Contains(ct, mt) {
				return true
			}
		}
		return false
	}

	rec := caddyhttp.NewResponseRecorder(w, buf, shouldBuf)

	err := next.ServeHTTP(rec, r)
	if err != nil {
		return err
	}
	if !rec.Buffered() {
		return nil
	}

	err = t.executeTemplate(rec, r)
	if err != nil {
		return err
	}

	rec.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
	rec.Header().Del("Accept-Ranges") // we don't know ranges for dynamically-created content
	rec.Header().Del("Last-Modified") // useless for dynamic content since it's always changing

	// we don't know a way to quickly generate etag for dynamic content,
	// and weak etags still cause browsers to rely on it even after a
	// refresh, so disable them until we find a better way to do this
	rec.Header().Del("Etag")

	return rec.WriteResponse()
}

// executeTemplate executes the template contained in wb.buf and replaces it with the results.
func (t *Templates) executeTemplate(rr caddyhttp.ResponseRecorder, r *http.Request) error {
	var fs http.FileSystem
	if t.FileRoot != "" {
		repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
		fs = http.Dir(repl.ReplaceAll(t.FileRoot, "."))
	}

	ctx := &TemplateContext{
		Root:       fs,
		Req:        r,
		RespHeader: WrappedHeader{rr.Header()},
		config:     t,
	}

	err := ctx.executeTemplateInBuffer(r.URL.Path, rr.Buffer())
	if err != nil {
		// templates may return a custom HTTP error to be propagated to the client,
		// otherwise for any other error we assume the template is broken
		var handlerErr caddyhttp.HandlerError
		if errors.As(err, &handlerErr) {
			return handlerErr
		}
		return caddyhttp.Error(http.StatusInternalServerError, err)
	}

	return nil
}

// virtualResponseWriter is used in virtualized HTTP requests
// that templates may execute.
type virtualResponseWriter struct {
	status int
	header http.Header
	body   *bytes.Buffer
}

func (vrw *virtualResponseWriter) Header() http.Header {
	return vrw.header
}

func (vrw *virtualResponseWriter) WriteHeader(statusCode int) {
	vrw.status = statusCode
}

func (vrw *virtualResponseWriter) Write(data []byte) (int, error) {
	return vrw.body.Write(data)
}

var defaultMIMETypes = []string{
	"text/html",
	"text/plain",
	"text/markdown",
}

// Interface guards
var (
	_ caddy.Provisioner           = (*Templates)(nil)
	_ caddy.Validator             = (*Templates)(nil)
	_ caddyhttp.MiddlewareHandler = (*Templates)(nil)
)
<|endoftext|>


<commit_before>package pixel

import (
	"fmt"
	"math"
	"math/cmplx"
)

// Vec is a 2d vector type. It is unusually implemented as complex128 for convenience. Since Go does
// not allow operator overloading, implementing vector as a struct leads to a bunch of methods for
// addition, subtraction and multiplication of vectors. With complex128, much of this functionality
// is given through operators.
//
// Create vectors with the V constructor:
//
//   u := pixel.V(1, 2)
//   v := pixel.V(8, -3)
//
// Add and subtract them using the standard + and - operators:
//
//   w := u + v
//   fmt.Println(w)     // Vec(9, -1)
//   fmt.Println(u - v) // Vec(-7, 5)
//
// Additional standard vector operations can be obtained with methods:
//
//   u := pixel.V(2, 3)
//   v := pixel.V(8, 1)
//   if u.X() < 0 {
//       fmt.Println("this won't happend")
//   }
//   x := u.Unit().Dot(v.Unit())
type Vec complex128

// V returns a new 2d vector with the given coordinates.
func V(x, y float64) Vec {
	return Vec(complex(x, y))
}

// String returns the string representation of a vector u as "Vec(x, y)".
func (u Vec) String() string {
	return fmt.Sprintf("Vec(%v, %v)", u.X(), u.Y())
}

// X returns the x coordinate of a vector u.
func (u Vec) X() float64 {
	return real(u)
}

// Y returns the y coordinate of a vector u.
func (u Vec) Y() float64 {
	return imag(u)
}

// Len returns the length of a vector u.
func (u Vec) Len() float64 {
	return cmplx.Abs(complex128(u))
}

// Angle returns the angle between a vector u and the x-axis. The result is in the range [-Pi, Pi].
func (u Vec) Angle() float64 {
	return cmplx.Phase(complex128(u))
}

// Unit returns a vector of length 1 with the same angle as u.
func (u Vec) Unit() Vec {
	return u / V(u.Len(), 0)
}

// Scaled returns a vector u multiplied by c.
func (u Vec) Scaled(c float64) Vec {
	return u * V(c, 0)
}

// Rotated returns a vector u rotated by the given angle in radians.
func (u Vec) Rotated(angle float64) Vec {
	return u * V(math.Cos(angle), math.Sin(angle))
}

// Dot returns the dot product of vectors u and v.
func (u Vec) Dot(v Vec) float64 {
	return u.X()*v.X() + u.Y()*v.Y()
}

// Cross return the cross product of vectors u and v.
func (u Vec) Cross(v Vec) float64 {
	return u.X()*v.Y() - v.X()*u.Y()
}
<commit_msg>improve doc on vec<commit_after>package pixel

import (
	"fmt"
	"math"
	"math/cmplx"
)

// Vec is a 2d vector type. It is unusually implemented as complex128 for convenience. Since Go does
// not allow operator overloading, implementing vector as a struct leads to a bunch of methods for
// addition, subtraction and multiplication of vectors. With complex128, much of this functionality
// is given through operators.
//
// Create vectors with the V constructor:
//
//   u := pixel.V(1, 2)
//   v := pixel.V(8, -3)
//
// Add and subtract them using the standard + and - operators:
//
//   w := u + v
//   fmt.Println(w)     // Vec(9, -1)
//   fmt.Println(u - v) // Vec(-7, 5)
//
// Additional standard vector operations can be obtained with methods:
//
//   u := pixel.V(2, 3)
//   v := pixel.V(8, 1)
//   if u.X() < 0 {
//       fmt.Println("this won't happend")
//   }
//   x := u.Unit().Dot(v.Unit())
type Vec complex128

// V returns a new 2d vector with the given coordinates.
func V(x, y float64) Vec {
	return Vec(complex(x, y))
}

// String returns the string representation of a vector u.
//
//   u := pixel.V(4.5, -1.3)
//   u.String()     // returns "Vec(4.5, -1.3)"
//   fmt.Println(u) // Vec(4.5, -1.3)
func (u Vec) String() string {
	return fmt.Sprintf("Vec(%v, %v)", u.X(), u.Y())
}

// X returns the x coordinate of a vector u.
func (u Vec) X() float64 {
	return real(u)
}

// Y returns the y coordinate of a vector u.
func (u Vec) Y() float64 {
	return imag(u)
}

// Len returns the length of a vector u.
func (u Vec) Len() float64 {
	return cmplx.Abs(complex128(u))
}

// Angle returns the angle between a vector u and the x-axis. The result is in the range [-Pi, Pi].
func (u Vec) Angle() float64 {
	return cmplx.Phase(complex128(u))
}

// Unit returns a vector of length 1 with the same angle as u.
func (u Vec) Unit() Vec {
	return u / V(u.Len(), 0)
}

// Scaled returns a vector u multiplied by c.
func (u Vec) Scaled(c float64) Vec {
	return u * V(c, 0)
}

// Rotated returns a vector u rotated by the given angle in radians.
func (u Vec) Rotated(angle float64) Vec {
	return u * V(math.Cos(angle), math.Sin(angle))
}

// Dot returns the dot product of vectors u and v.
func (u Vec) Dot(v Vec) float64 {
	return u.X()*v.X() + u.Y()*v.Y()
}

// Cross return the cross product of vectors u and v.
func (u Vec) Cross(v Vec) float64 {
	return u.X()*v.Y() - v.X()*u.Y()
}
<|endoftext|>


<commit_before>package digitalocean

import (
	"github.com/mitchellh/packer/packer"
	"os"
	"strconv"
	"testing"
)

func init() {
	// Clear out the credential env vars
	os.Setenv("DIGITALOCEAN_API_KEY", "")
	os.Setenv("DIGITALOCEAN_CLIENT_ID", "")
}

func testConfig() map[string]interface{} {
	return map[string]interface{}{
		"client_id": "foo",
		"api_key":   "bar",
	}
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilder_Prepare_BadType(t *testing.T) {
	b := &Builder{}
	c := map[string]interface{}{
		"api_key": []string{},
	}

	warnings, err := b.Prepare(c)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatalf("prepare should fail")
	}
}

func TestBuilderPrepare_APIKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["api_key"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.APIKey != "foo" {
		t.Errorf("access key invalid: %s", b.config.APIKey)
	}

	// Test bad
	delete(config, "api_key")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test env variable
	delete(config, "api_key")
	os.Setenv("DIGITALOCEAN_API_KEY", "foo")
	defer os.Setenv("DIGITALOCEAN_API_KEY", "")
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_ClientID(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["client_id"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.ClientID != "foo" {
		t.Errorf("invalid: %s", b.config.ClientID)
	}

	// Test bad
	delete(config, "client_id")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test env variable
	delete(config, "client_id")
	os.Setenv("DIGITALOCEAN_CLIENT_ID", "foo")
	defer os.Setenv("DIGITALOCEAN_CLIENT_ID", "")
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_InvalidKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Add a random key
	config["i_should_not_be_valid"] = true
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_Region(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Region != DefaultRegion {
		t.Errorf("found %s, expected %s", b.config.Region, DefaultRegion)
	}

	expected := "sfo1"

	// Test set
	config["region_id"] = 0
	config["region"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Region != expected {
		t.Errorf("found %s, expected %s", b.config.Region, expected)
	}
}

func TestBuilderPrepare_Size(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Size != DefaultSize {
		t.Errorf("found %s, expected %s", b.config.Size, DefaultSize)
	}

	expected := "1024mb"

	// Test set
	config["size_id"] = 0
	config["size"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Size != expected {
		t.Errorf("found %s, expected %s", b.config.Size, expected)
	}
}

func TestBuilderPrepare_Image(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Image != DefaultImage {
		t.Errorf("found %s, expected %s", b.config.Image, DefaultImage)
	}

	expected := "ubuntu-14-04-x64"

	// Test set
	config["image_id"] = 0
	config["image"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Image != expected {
		t.Errorf("found %s, expected %s", b.config.Image, expected)
	}
}

func TestBuilderPrepare_SSHUsername(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SSHUsername != "root" {
		t.Errorf("invalid: %d", b.config.SSHUsername)
	}

	// Test set
	config["ssh_username"] = "foo"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SSHUsername != "foo" {
		t.Errorf("invalid: %s", b.config.SSHUsername)
	}
}

func TestBuilderPrepare_SSHTimeout(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.RawSSHTimeout != "1m" {
		t.Errorf("invalid: %d", b.config.RawSSHTimeout)
	}

	// Test set
	config["ssh_timeout"] = "30s"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["ssh_timeout"] = "tubes"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}

func TestBuilderPrepare_StateTimeout(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.RawStateTimeout != "6m" {
		t.Errorf("invalid: %d", b.config.RawStateTimeout)
	}

	// Test set
	config["state_timeout"] = "5m"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["state_timeout"] = "tubes"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}

func TestBuilderPrepare_PrivateNetworking(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.PrivateNetworking != false {
		t.Errorf("invalid: %s", b.config.PrivateNetworking)
	}

	// Test set
	config["private_networking"] = true
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.PrivateNetworking != true {
		t.Errorf("invalid: %s", b.config.PrivateNetworking)
	}
}

func TestBuilderPrepare_SnapshotName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SnapshotName == "" {
		t.Errorf("invalid: %s", b.config.SnapshotName)
	}

	// Test set
	config["snapshot_name"] = "foobarbaz"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test set with template
	config["snapshot_name"] = "{{timestamp}}"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	_, err = strconv.ParseInt(b.config.SnapshotName, 0, 0)
	if err != nil {
		t.Fatalf("failed to parse int in template: %s", err)
	}

}

func TestBuilderPrepare_DropletName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.DropletName == "" {
		t.Errorf("invalid: %s", b.config.DropletName)
	}

	// Test normal set
	config["droplet_name"] = "foobar"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test with template
	config["droplet_name"] = "foobar-{{timestamp}}"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test with bad template
	config["droplet_name"] = "foobar-{{"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}
<commit_msg>builder/digitalocean: fix incorrect printf verb types<commit_after>package digitalocean

import (
	"github.com/mitchellh/packer/packer"
	"os"
	"strconv"
	"testing"
)

func init() {
	// Clear out the credential env vars
	os.Setenv("DIGITALOCEAN_API_KEY", "")
	os.Setenv("DIGITALOCEAN_CLIENT_ID", "")
}

func testConfig() map[string]interface{} {
	return map[string]interface{}{
		"client_id": "foo",
		"api_key":   "bar",
	}
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilder_Prepare_BadType(t *testing.T) {
	b := &Builder{}
	c := map[string]interface{}{
		"api_key": []string{},
	}

	warnings, err := b.Prepare(c)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatalf("prepare should fail")
	}
}

func TestBuilderPrepare_APIKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["api_key"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.APIKey != "foo" {
		t.Errorf("access key invalid: %s", b.config.APIKey)
	}

	// Test bad
	delete(config, "api_key")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test env variable
	delete(config, "api_key")
	os.Setenv("DIGITALOCEAN_API_KEY", "foo")
	defer os.Setenv("DIGITALOCEAN_API_KEY", "")
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_ClientID(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["client_id"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.ClientID != "foo" {
		t.Errorf("invalid: %s", b.config.ClientID)
	}

	// Test bad
	delete(config, "client_id")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test env variable
	delete(config, "client_id")
	os.Setenv("DIGITALOCEAN_CLIENT_ID", "foo")
	defer os.Setenv("DIGITALOCEAN_CLIENT_ID", "")
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_InvalidKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Add a random key
	config["i_should_not_be_valid"] = true
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_Region(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Region != DefaultRegion {
		t.Errorf("found %s, expected %s", b.config.Region, DefaultRegion)
	}

	expected := "sfo1"

	// Test set
	config["region_id"] = 0
	config["region"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Region != expected {
		t.Errorf("found %s, expected %s", b.config.Region, expected)
	}
}

func TestBuilderPrepare_Size(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Size != DefaultSize {
		t.Errorf("found %s, expected %s", b.config.Size, DefaultSize)
	}

	expected := "1024mb"

	// Test set
	config["size_id"] = 0
	config["size"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Size != expected {
		t.Errorf("found %s, expected %s", b.config.Size, expected)
	}
}

func TestBuilderPrepare_Image(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Image != DefaultImage {
		t.Errorf("found %s, expected %s", b.config.Image, DefaultImage)
	}

	expected := "ubuntu-14-04-x64"

	// Test set
	config["image_id"] = 0
	config["image"] = expected
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.Image != expected {
		t.Errorf("found %s, expected %s", b.config.Image, expected)
	}
}

func TestBuilderPrepare_SSHUsername(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SSHUsername != "root" {
		t.Errorf("invalid: %s", b.config.SSHUsername)
	}

	// Test set
	config["ssh_username"] = "foo"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SSHUsername != "foo" {
		t.Errorf("invalid: %s", b.config.SSHUsername)
	}
}

func TestBuilderPrepare_SSHTimeout(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.RawSSHTimeout != "1m" {
		t.Errorf("invalid: %s", b.config.RawSSHTimeout)
	}

	// Test set
	config["ssh_timeout"] = "30s"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["ssh_timeout"] = "tubes"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}

func TestBuilderPrepare_StateTimeout(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.RawStateTimeout != "6m" {
		t.Errorf("invalid: %s", b.config.RawStateTimeout)
	}

	// Test set
	config["state_timeout"] = "5m"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["state_timeout"] = "tubes"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}

func TestBuilderPrepare_PrivateNetworking(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.PrivateNetworking != false {
		t.Errorf("invalid: %t", b.config.PrivateNetworking)
	}

	// Test set
	config["private_networking"] = true
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.PrivateNetworking != true {
		t.Errorf("invalid: %t", b.config.PrivateNetworking)
	}
}

func TestBuilderPrepare_SnapshotName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.SnapshotName == "" {
		t.Errorf("invalid: %s", b.config.SnapshotName)
	}

	// Test set
	config["snapshot_name"] = "foobarbaz"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test set with template
	config["snapshot_name"] = "{{timestamp}}"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	_, err = strconv.ParseInt(b.config.SnapshotName, 0, 0)
	if err != nil {
		t.Fatalf("failed to parse int in template: %s", err)
	}

}

func TestBuilderPrepare_DropletName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test default
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	if b.config.DropletName == "" {
		t.Errorf("invalid: %s", b.config.DropletName)
	}

	// Test normal set
	config["droplet_name"] = "foobar"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test with template
	config["droplet_name"] = "foobar-{{timestamp}}"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test with bad template
	config["droplet_name"] = "foobar-{{"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
)

// This is the common builder ID to all of these artifacts.
const BuilderId = "packer.xenserver"

type LocalArtifact struct {
	dir string
	f   []string
}

func NewArtifact(dir string) (packer.Artifact, error) {
	files := make([]string, 0, 1)
	visit := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			files = append(files, path)
		}
		return err
	}
	if err := filepath.Walk(dir, visit); err != nil {
		return nil, err
	}

	return &LocalArtifact{
		dir: dir,
		f:   files,
	}, nil
}

func (*LocalArtifact) BuilderId() string {
	return BuilderId
}

func (a *LocalArtifact) Files() []string {
	return a.f
}

func (*LocalArtifact) Id() string {
	return "VM"
}

func (a *LocalArtifact) String() string {
	return fmt.Sprintf("VM files in directory: %s", a.dir)
}

func (a *LocalArtifact) State(name string) interface{} {
	return nil
}

func (a *LocalArtifact) Destroy() error {
	return os.RemoveAll(a.dir)
}
<commit_msg>Added state to pass properties between builder and post-processor<commit_after>package common

import (
	"fmt"
	"github.com/mitchellh/packer/packer"
	"os"
)

// This is the common builder ID to all of these artifacts.
const BuilderId = "packer.xenserver"

type LocalArtifact struct {
	dir string
	f   []string
	state map[string]interface{}
}

func NewArtifact(dir string, state map[string]interface{}, files []string) (packer.Artifact, error) {
	return &LocalArtifact{
		dir: dir,
		f:   files,
		state: state,
	}, nil
}

func (*LocalArtifact) BuilderId() string {
	return BuilderId
}

func (a *LocalArtifact) Files() []string {
	return a.f
}

func (*LocalArtifact) Id() string {
	return "VM"
}

func (a *LocalArtifact) String() string {
	return fmt.Sprintf("VM files in directory: %s", a.dir)
}

func (a *LocalArtifact) State(name string) interface{} {
	return a.state[name]
}

func (a *LocalArtifact) Destroy() error {
	return os.RemoveAll(a.dir)
}
<|endoftext|>


<commit_before>package main

import (
	"path"

	"gnd.la/app"
	"gnd.la/apps/docs"
	"gnd.la/net/urlutil"
)

const (
	//gondolaURL = "http://www.gondolaweb.com"
	gondolaURL = "ssh://abra.rm-fr.net/home/fiam/git/gondola.git"
)

func gndlaHandler(ctx *app.Context) {
	if ctx.FormValue("go-get") == "1" {
		ctx.MustExecute("goget.html", nil)
		return
	}
	// Check if the request path is a pkg name
	var p string
	pkg := path.Join("gnd.la", ctx.R.URL.Path)
	if _, err := docs.DefaultContext.Import(pkg, "", 0); err == nil {
		p = ctx.MustReverse(docs.PackageHandlerName, pkg)
	}
	redir, err := urlutil.Join(gondolaURL, p)
	if err != nil {
		panic(err)
	}
	ctx.Redirect(redir, false)
}
<commit_msg>Update path to Gondola repository<commit_after>package main

import (
	"path"

	"gnd.la/app"
	"gnd.la/apps/docs"
	"gnd.la/net/urlutil"
)

const (
	gondolaURL = "http://www.gondolaweb.com"
)

func gndlaHandler(ctx *app.Context) {
	if ctx.FormValue("go-get") == "1" {
		ctx.MustExecute("goget.html", nil)
		return
	}
	// Check if the request path is a pkg name
	var p string
	pkg := path.Join("gnd.la", ctx.R.URL.Path)
	if _, err := docs.DefaultContext.Import(pkg, "", 0); err == nil {
		p = ctx.MustReverse(docs.PackageHandlerName, pkg)
	}
	redir, err := urlutil.Join(gondolaURL, p)
	if err != nil {
		panic(err)
	}
	ctx.Redirect(redir, false)
}
<|endoftext|>