<commit_before>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/Tinker-Ware/gh-service/domain"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
)

const htmlIndex = `
Logged in with GitHub
`

const htmlCloseWindow = `
Logged in with GitHub
`

type repoRequest struct {
	Owner   string `json:"owner"`
	Name    string `json:"name"`
	Private bool   `json:"private"`
	Org     string `json:"org"`
}

type fileRequest struct {
	domain.Author
	domain.File
}

type multipleFilesRequest struct {
	Author domain.Author `json:"author"`
	Files  []domain.File `json:"files"`
}

type repoResponse struct {
	Repository *domain.Repository `json:"repository"`
}

type GHInteractor interface {
	GHCallback(code, state, incomingState string) (*domain.User, error)
	GHLogin() (string, string)
	ShowUser(username string) (*domain.User, error)
	ShowRepos(username string) ([]domain.Repository, error)
	CreateRepo(username, reponame, org string, private bool) (*domain.Repository, error)
	ShowRepo(username, repo string) (*domain.Repository, error)
	ShowKeys(username string) ([]domain.Key, error)
	CreateKey(username string, key *domain.Key) error
	ShowKey(username string, id int) (*domain.Key, error)
	CreateFile(file domain.File, author domain.Author, username, repo string) error
	AddFiles(files []domain.File, author domain.Author, username, repo string) error
}

type WebServiceHandler struct {
	GHInteractor GHInteractor
	Sessions     *sessions.CookieStore
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url, state := handler.GHInteractor.GHLogin()

	fmt.Println("State login " + state)

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)

}

func (handler WebServiceHandler) Callback(res http.ResponseWriter, req *http.Request) {

	incomingState := req.FormValue("state")
	code := req.FormValue("code")

	state := ""
	user, err := handler.GHInteractor.GHCallback(code, state, incomingState)
	if err != nil {
		return
	}

	usrB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(usrB)

}

func (handler WebServiceHandler) Root(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))
}

func (handler WebServiceHandler) GetCurrentUser(res http.ResponseWriter, req *http.Request) {
	session, err := handler.Sessions.Get(req, "user")
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}

	usr := session.Values["user"]

	userS := usr.(string)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userS))

}

func (handler WebServiceHandler) ShowUser(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	user, err := handler.GHInteractor.ShowUser(username)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusNotFound)
		return
	}

	userB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userB))
}

func (handler WebServiceHandler) ShowRepos(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	repos, err := handler.GHInteractor.ShowRepos(username)

	if err != nil {
		res.WriteHeader(http.StatusNotFound)
		return
	}

	reposB, _ := json.Marshal(repos)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(reposB))
}

func (handler WebServiceHandler) CreateRepo(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	repo := repoRequest{}
	err := decoder.Decode(&repo)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	r, err := handler.GHInteractor.CreateRepo(repo.Owner, repo.Name, repo.Org, repo.Private)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	repoB, _ := json.Marshal(r)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowRepo(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	repo, err := handler.GHInteractor.ShowRepo(username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	repoR := repoResponse{
		Repository: repo,
	}

	repoB, _ := json.Marshal(repoR)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	keys, err := handler.GHInteractor.ShowKeys(username)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keysB))

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	key := domain.Key{}
	err := decoder.Decode(&key)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	vars := mux.Vars(req)
	username := vars["username"]

	err = handler.GHInteractor.CreateKey(username, &key)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))
}

func (handler WebServiceHandler) ShowKey(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	idStr := vars["id"]

	id, err := strconv.Atoi(idStr)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	key, err := handler.GHInteractor.ShowKey(username, id)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))

}

func (handler WebServiceHandler) AddFileToRepository(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)
	file := fileRequest{}
	err := decoder.Decode(&file)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	err = handler.GHInteractor.CreateFile(file.File, file.Author, username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func (handler WebServiceHandler) AddMultipleFilesToRepository(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)

	request := multipleFilesRequest{}

	err := decoder.Decode(&request)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	err = handler.GHInteractor.AddFiles(request.Files, request.Author, username, repoName)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func tokenToJSON(token *oauth2.Token) (string, error) {
	d, err := json.Marshal(token)
	if err != nil {
		return "", err
	}
	return string(d), nil

}

func tokenFromJSON(jsonStr string) (*oauth2.Token, error) {
	var token oauth2.Token
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<commit_msg>Change response to comply with the blueprint<commit_after>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/Tinker-Ware/gh-service/domain"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
)

const htmlIndex = `
Logged in with GitHub
`

const htmlCloseWindow = `
Logged in with GitHub
`

type repoRequest struct {
	Owner   string `json:"owner"`
	Name    string `json:"name"`
	Private bool   `json:"private"`
	Org     string `json:"org"`
}

type fileRequest struct {
	domain.Author
	domain.File
}

type multipleFilesRequest struct {
	Author domain.Author `json:"author"`
	Files  []domain.File `json:"files"`
}

type repositoryResponse struct {
	Repository *domain.Repository `json:"repository"`
}

type repositoriesResponse struct {
	Repositories []domain.Repository `json:"repositories"`
}

type GHInteractor interface {
	GHCallback(code, state, incomingState string) (*domain.User, error)
	GHLogin() (string, string)
	ShowUser(username string) (*domain.User, error)
	ShowRepos(username string) ([]domain.Repository, error)
	CreateRepo(username, reponame, org string, private bool) (*domain.Repository, error)
	ShowRepo(username, repo string) (*domain.Repository, error)
	ShowKeys(username string) ([]domain.Key, error)
	CreateKey(username string, key *domain.Key) error
	ShowKey(username string, id int) (*domain.Key, error)
	CreateFile(file domain.File, author domain.Author, username, repo string) error
	AddFiles(files []domain.File, author domain.Author, username, repo string) error
}

type WebServiceHandler struct {
	GHInteractor GHInteractor
	Sessions     *sessions.CookieStore
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url, state := handler.GHInteractor.GHLogin()

	fmt.Println("State login " + state)

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)

}

func (handler WebServiceHandler) Callback(res http.ResponseWriter, req *http.Request) {

	incomingState := req.FormValue("state")
	code := req.FormValue("code")

	state := ""
	user, err := handler.GHInteractor.GHCallback(code, state, incomingState)
	if err != nil {
		return
	}

	usrB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(usrB)

}

func (handler WebServiceHandler) Root(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))
}

func (handler WebServiceHandler) GetCurrentUser(res http.ResponseWriter, req *http.Request) {
	session, err := handler.Sessions.Get(req, "user")
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}

	usr := session.Values["user"]

	userS := usr.(string)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userS))

}

func (handler WebServiceHandler) ShowUser(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	user, err := handler.GHInteractor.ShowUser(username)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusNotFound)
		return
	}

	userB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userB))
}

func (handler WebServiceHandler) ShowRepos(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	repos, err := handler.GHInteractor.ShowRepos(username)

	if err != nil {
		res.WriteHeader(http.StatusNotFound)
		return
	}

	reposR := repositoriesResponse{
		Repositories: repos,
	}

	reposB, _ := json.Marshal(reposR)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(reposB))
}

func (handler WebServiceHandler) CreateRepo(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	repo := repoRequest{}
	err := decoder.Decode(&repo)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	r, err := handler.GHInteractor.CreateRepo(repo.Owner, repo.Name, repo.Org, repo.Private)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	repoB, _ := json.Marshal(r)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowRepo(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	repo, err := handler.GHInteractor.ShowRepo(username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	repoR := repositoryResponse{
		Repository: repo,
	}

	repoB, _ := json.Marshal(repoR)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	keys, err := handler.GHInteractor.ShowKeys(username)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keysB))

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	key := domain.Key{}
	err := decoder.Decode(&key)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	vars := mux.Vars(req)
	username := vars["username"]

	err = handler.GHInteractor.CreateKey(username, &key)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))
}

func (handler WebServiceHandler) ShowKey(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	idStr := vars["id"]

	id, err := strconv.Atoi(idStr)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	key, err := handler.GHInteractor.ShowKey(username, id)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))

}

func (handler WebServiceHandler) AddFileToRepository(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)
	file := fileRequest{}
	err := decoder.Decode(&file)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	err = handler.GHInteractor.CreateFile(file.File, file.Author, username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func (handler WebServiceHandler) AddMultipleFilesToRepository(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)

	request := multipleFilesRequest{}

	err := decoder.Decode(&request)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	err = handler.GHInteractor.AddFiles(request.Files, request.Author, username, repoName)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func tokenToJSON(token *oauth2.Token) (string, error) {
	d, err := json.Marshal(token)
	if err != nil {
		return "", err
	}
	return string(d), nil

}

func tokenFromJSON(jsonStr string) (*oauth2.Token, error) {
	var token oauth2.Token
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<|endoftext|>


<commit_before>package generator

import (
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/golang/protobuf/protoc-gen-go/plugin"
	"github.com/tcncloud/protoc-gen-persist/persist"
)

type Generator struct {
	Files           []*string
	OriginalRequest *plugin_go.CodeGeneratorRequest
}

func NewGenerator(request *plugin_go.CodeGeneratorRequest) *Generator {
	ret := new(Generator)
	ret.OriginalRequest = request
	return ret
}

// check if a service has at least one method that has the persist.ql extension defined
func IsServicePersistEnabled(service *descriptor.ServiceDescriptorProto) bool {
	if service.Method != nil {
		for _, method := range service.Method {
			if method.GetOptions() != nil {
				if proto.HasExtension(method.Options, persist.E_Ql) {
					// at least one method implement persist.ql
					return true
				}
			}
		}
	}
	return false
}

// Process the request
func (g *Generator) ProcessRequest() {
	for _, file := range g.OriginalRequest.ProtoFile {
		for _, service := range file.Service {
			for _, method := range service.Method {
				method.GetOptions()
			}
		}
	}
}
<commit_msg>added license<commit_after>// Copyright 2017, TCN Inc.
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of TCN Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package generator

import (
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/golang/protobuf/protoc-gen-go/plugin"
	"github.com/tcncloud/protoc-gen-persist/persist"
)

type Generator struct {
	Files           []*string
	OriginalRequest *plugin_go.CodeGeneratorRequest
}

func NewGenerator(request *plugin_go.CodeGeneratorRequest) *Generator {
	ret := new(Generator)
	ret.OriginalRequest = request
	return ret
}

// check if a service has at least one method that has the persist.ql extension defined
func IsServicePersistEnabled(service *descriptor.ServiceDescriptorProto) bool {
	if service.Method != nil {
		for _, method := range service.Method {
			if method.GetOptions() != nil {
				if proto.HasExtension(method.Options, persist.E_Ql) {
					// at least one method implement persist.ql
					return true
				}
			}
		}
	}
	return false
}

// Process the request
func (g *Generator) ProcessRequest() {
	for _, file := range g.OriginalRequest.ProtoFile {
		for _, service := range file.Service {
			for _, method := range service.Method {
				method.GetOptions()
			}
		}
	}
}
<|endoftext|>


<commit_before>package xorm

import (
	"fmt"
	"reflect"
	"time"

	"github.com/xormplus/xorm/core"
	"github.com/xormplus/xorm/schemas"
)

func reflect2objectWithDateFormat(rawValue *reflect.Value, dateFormat string) (value interface{}, err error) {
	aa := reflect.TypeOf((*rawValue).Interface())
	vv := reflect.ValueOf((*rawValue).Interface())
	switch aa.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		value = vv.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		value = vv.Uint()
	case reflect.Float32, reflect.Float64:
		value = vv.Float()
	case reflect.String:
		value = vv.String()
	case reflect.Array, reflect.Slice:
		switch aa.Elem().Kind() {
		case reflect.Uint8:
			data := rawValue.Interface().([]byte)
			value = string(data)
		default:
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	// time type
	case reflect.Struct:
		if aa.ConvertibleTo(schemas.TimeType) {
			value = vv.Convert(schemas.TimeType).Interface().(time.Time).Format(dateFormat)
		} else {
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	case reflect.Bool:
		value = vv.Bool()
	case reflect.Complex128, reflect.Complex64:
		value = vv.Complex()
	/* TODO: unsupported types below
	   case reflect.Map:
	   case reflect.Ptr:
	   case reflect.Uintptr:
	   case reflect.UnsafePointer:
	   case reflect.Chan, reflect.Func, reflect.Interface:
	*/
	default:
		err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
	}
	return
}

func value2ObjectWithDateFormat(rawValue *reflect.Value, dateFormat string) (data interface{}, err error) {
	data, err = reflect2objectWithDateFormat(rawValue, dateFormat)
	if err != nil {
		return
	}
	return
}

func rows2mapObjectsWithDateFormat(rows *core.Rows, dateFormat string) (resultsSlice []map[string]interface{}, err error) {
	fields, err := rows.Columns()
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		result, err := rows2mapObjectWithDateFormat(rows, dateFormat, fields)
		if err != nil {
			return nil, err
		}
		resultsSlice = append(resultsSlice, result)
	}

	return resultsSlice, nil
}

func rows2mapObjectWithDateFormat(rows *core.Rows, dateFormat string, fields []string) (resultsMap map[string]interface{}, err error) {
	result := make(map[string]interface{})
	scanResultContainers := make([]interface{}, len(fields))
	for i := 0; i < len(fields); i++ {
		var scanResultContainer interface{}
		scanResultContainers[i] = &scanResultContainer
	}
	if err := rows.Scan(scanResultContainers...); err != nil {
		return nil, err
	}

	for ii, key := range fields {
		rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
		//if row is null then ignore
		if rawValue.Interface() == nil {
			continue
		}

		if data, err := value2ObjectWithDateFormat(&rawValue, dateFormat); err == nil {
			result[key] = data
		} else {
			return nil, err // !nashtsai! REVIEW, should return err or just error log?
		}

	}
	return result, nil
}

func txQueryByMap(tx *core.Tx, sqlStr string, params interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.QueryMap(sqlStr, params)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return rows2mapObjects(rows)
}

func txQuery3WithDateFormat(tx *core.Tx, dateFormat string, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.Query(sqlStr, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return rows2mapObjectsWithDateFormat(rows, dateFormat)
}

func queryByMap(db *core.DB, sqlStr string, params interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()

	rows, err := s.QueryMap(params)

	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}

func query3WithDateFormat(db *core.DB, dateFormat string, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()
	rows, err := s.Query(params...)

	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjectsWithDateFormat(rows, dateFormat)
}

func reflect2object(rawValue *reflect.Value) (value interface{}, err error) {
	aa := reflect.TypeOf((*rawValue).Interface())
	vv := reflect.ValueOf((*rawValue).Interface())
	switch aa.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		value = vv.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		value = vv.Uint()
	case reflect.Float32, reflect.Float64:
		value = vv.Float()
	case reflect.String:
		value = vv.String()
	case reflect.Array, reflect.Slice:
		switch aa.Elem().Kind() {
		case reflect.Uint8:
			data := rawValue.Interface().([]byte)
			value = string(data)
		default:
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	// time type
	case reflect.Struct:
		if aa.ConvertibleTo(schemas.TimeType) {
			value = vv.Convert(schemas.TimeType).Interface().(time.Time)
		} else {
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	case reflect.Bool:
		value = vv.Bool()
	case reflect.Complex128, reflect.Complex64:
		value = vv.Complex()
	/* TODO: unsupported types below
	   case reflect.Map:
	   case reflect.Ptr:
	   case reflect.Uintptr:
	   case reflect.UnsafePointer:
	   case reflect.Chan, reflect.Func, reflect.Interface:
	*/
	default:
		err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
	}
	return
}

func value2Object(rawValue *reflect.Value) (data interface{}, err error) {
	data, err = reflect2object(rawValue)
	if err != nil {
		return
	}
	return
}

func rows2mapObjects(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
	fields, err := rows.Columns()
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		result, err := rows2mapObject(rows, fields)
		if err != nil {
			return nil, err
		}
		resultsSlice = append(resultsSlice, result)
	}

	return resultsSlice, nil
}

func rows2mapObject(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) {
	result := make(map[string]interface{})
	scanResultContainers := make([]interface{}, len(fields))
	for i := 0; i < len(fields); i++ {
		var scanResultContainer interface{}
		scanResultContainers[i] = &scanResultContainer
	}
	if err := rows.Scan(scanResultContainers...); err != nil {
		return nil, err
	}

	for ii, key := range fields {
		rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
		//if row is null then ignore
		if rawValue.Interface() == nil {
			continue
		}

		if data, err := value2Object(&rawValue); err == nil {
			result[key] = data
		} else {
			return nil, err // !nashtsai! REVIEW, should return err or just error log?
		}

	}
	return result, nil
}

func txQuery3(tx *core.Tx, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.Query(sqlStr, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}

func query3(db *core.DB, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()
	rows, err := s.Query(params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}
<commit_msg>bug fix #104 float32 to float64 error<commit_after>package xorm

import (
	"fmt"
	"reflect"
	"strconv"
	"time"

	"github.com/xormplus/xorm/core"
	"github.com/xormplus/xorm/schemas"
)

func reflect2objectWithDateFormat(rawValue *reflect.Value, dateFormat string) (value interface{}, err error) {
	aa := reflect.TypeOf((*rawValue).Interface())
	vv := reflect.ValueOf((*rawValue).Interface())
	switch aa.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		value = vv.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		value = vv.Uint()
	case reflect.Float32, reflect.Float64:
		value = vv.Float()
	case reflect.String:
		value = vv.String()
	case reflect.Array, reflect.Slice:
		switch aa.Elem().Kind() {
		case reflect.Uint8:
			data := rawValue.Interface().([]byte)
			value = string(data)
		default:
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	// time type
	case reflect.Struct:
		if aa.ConvertibleTo(schemas.TimeType) {
			value = vv.Convert(schemas.TimeType).Interface().(time.Time).Format(dateFormat)
		} else {
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	case reflect.Bool:
		value = vv.Bool()
	case reflect.Complex128, reflect.Complex64:
		value = vv.Complex()
	/* TODO: unsupported types below
	   case reflect.Map:
	   case reflect.Ptr:
	   case reflect.Uintptr:
	   case reflect.UnsafePointer:
	   case reflect.Chan, reflect.Func, reflect.Interface:
	*/
	default:
		err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
	}
	return
}

func value2ObjectWithDateFormat(rawValue *reflect.Value, dateFormat string) (data interface{}, err error) {
	data, err = reflect2objectWithDateFormat(rawValue, dateFormat)
	if err != nil {
		return
	}
	return
}

func rows2mapObjectsWithDateFormat(rows *core.Rows, dateFormat string) (resultsSlice []map[string]interface{}, err error) {
	fields, err := rows.Columns()
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		result, err := rows2mapObjectWithDateFormat(rows, dateFormat, fields)
		if err != nil {
			return nil, err
		}
		resultsSlice = append(resultsSlice, result)
	}

	return resultsSlice, nil
}

func rows2mapObjectWithDateFormat(rows *core.Rows, dateFormat string, fields []string) (resultsMap map[string]interface{}, err error) {
	result := make(map[string]interface{})
	scanResultContainers := make([]interface{}, len(fields))
	for i := 0; i < len(fields); i++ {
		var scanResultContainer interface{}
		scanResultContainers[i] = &scanResultContainer
	}
	if err := rows.Scan(scanResultContainers...); err != nil {
		return nil, err
	}

	for ii, key := range fields {
		rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
		//if row is null then ignore
		if rawValue.Interface() == nil {
			continue
		}

		if data, err := value2ObjectWithDateFormat(&rawValue, dateFormat); err == nil {
			result[key] = data
		} else {
			return nil, err // !nashtsai! REVIEW, should return err or just error log?
		}

	}
	return result, nil
}

func txQueryByMap(tx *core.Tx, sqlStr string, params interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.QueryMap(sqlStr, params)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return rows2mapObjects(rows)
}

func txQuery3WithDateFormat(tx *core.Tx, dateFormat string, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.Query(sqlStr, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return rows2mapObjectsWithDateFormat(rows, dateFormat)
}

func queryByMap(db *core.DB, sqlStr string, params interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()

	rows, err := s.QueryMap(params)

	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}

func query3WithDateFormat(db *core.DB, dateFormat string, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()
	rows, err := s.Query(params...)

	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjectsWithDateFormat(rows, dateFormat)
}

func reflect2object(rawValue *reflect.Value) (value interface{}, err error) {
	aa := reflect.TypeOf((*rawValue).Interface())
	vv := reflect.ValueOf((*rawValue).Interface())
	switch aa.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		value = vv.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		value = vv.Uint()
	case reflect.Float32:
		value, _ = strconv.ParseFloat(fmt.Sprint(vv.Interface()), 61)
	case reflect.Float64:
		value = vv.Float()
	case reflect.String:
		value = vv.String()
	case reflect.Array, reflect.Slice:
		switch aa.Elem().Kind() {
		case reflect.Uint8:
			data := rawValue.Interface().([]byte)
			value = string(data)
		default:
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	// time type
	case reflect.Struct:
		if aa.ConvertibleTo(schemas.TimeType) {
			value = vv.Convert(schemas.TimeType).Interface().(time.Time)
		} else {
			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
		}
	case reflect.Bool:
		value = vv.Bool()
	case reflect.Complex128, reflect.Complex64:
		value = vv.Complex()
	/* TODO: unsupported types below
	   case reflect.Map:
	   case reflect.Ptr:
	   case reflect.Uintptr:
	   case reflect.UnsafePointer:
	   case reflect.Chan, reflect.Func, reflect.Interface:
	*/
	default:
		err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
	}
	return
}

func value2Object(rawValue *reflect.Value) (data interface{}, err error) {
	data, err = reflect2object(rawValue)
	if err != nil {
		return
	}
	return
}

func rows2mapObjects(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
	fields, err := rows.Columns()
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		result, err := rows2mapObject(rows, fields)
		if err != nil {
			return nil, err
		}
		resultsSlice = append(resultsSlice, result)
	}

	return resultsSlice, nil
}

func rows2mapObject(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) {
	result := make(map[string]interface{})
	scanResultContainers := make([]interface{}, len(fields))
	for i := 0; i < len(fields); i++ {
		var scanResultContainer interface{}
		scanResultContainers[i] = &scanResultContainer
	}
	if err := rows.Scan(scanResultContainers...); err != nil {
		return nil, err
	}

	for ii, key := range fields {
		rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
		//if row is null then ignore
		if rawValue.Interface() == nil {
			continue
		}

		if data, err := value2Object(&rawValue); err == nil {
			result[key] = data
		} else {
			return nil, err // !nashtsai! REVIEW, should return err or just error log?
		}

	}
	return result, nil
}

func txQuery3(tx *core.Tx, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	rows, err := tx.Query(sqlStr, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}

func query3(db *core.DB, sqlStr string, params ...interface{}) (resultsSlice []map[string]interface{}, err error) {
	s, err := db.Prepare(sqlStr)
	if err != nil {
		return nil, err
	}
	defer s.Close()
	rows, err := s.Query(params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return rows2mapObjects(rows)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/tappleby/slack-auth-proxy/slack"
)

func NewValidator() func(*slack.Auth, *UpstreamConfiguration) bool {
	validator := func(auth *slack.Auth, upstream *UpstreamConfiguration) bool {
		return upstream.FindUsername(auth.Username) != ""
	}
	return validator
}
<commit_msg>If upstream users list is empty, all users will be valid.<commit_after>package main

import (
	"github.com/tappleby/slack-auth-proxy/slack"
)

func NewValidator() func(*slack.Auth, *UpstreamConfiguration) bool {
	validator := func(auth *slack.Auth, upstream *UpstreamConfiguration) bool {
		return len(upstream.Users) == 0 || upstream.FindUsername(auth.Username) != ""
	}
	return validator
}
<|endoftext|>


<commit_before>/**
 * Package validator
 *
 * MISC:
 * - anonymous structs - they don't have names so expect the Struct name within StructErrors to be blank
 *
 */

package validator

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

const (
	utf8HexComma      = "0x2C"
	utf8Pipe          = "0x7C"
	tagSeparator      = ","
	orSeparator       = "|"
	tagKeySeparator   = "="
	structOnlyTag     = "structonly"
	omitempty         = "omitempty"
	skipValidationTag = "-"
	diveTag           = "dive"
	fieldErrMsg       = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag"
	invaldField       = "Invalid field passed to traverseField"
)

var (
	timeType    = reflect.TypeOf(time.Time{})
	timePtrType = reflect.TypeOf(&time.Time{})
)

// Validate implements the Validate Struct
// NOTE: Fields within are not thread safe and that is on purpose
// Functions and Tags should all be predifined before use, so subscribe to the philosiphy
// or make it thread safe on your end
type Validate struct {
	config Config
}

// Config contains the options that Validator with use
// passed to the New function
type Config struct {
	TagName         string
	ValidationFuncs map[string]Func
}

// Func accepts all values needed for file and cross field validation
// topStruct     = top level struct when validating by struct otherwise nil
// currentStruct = current level struct when validating by struct otherwise optional comparison value
// field         = field value for validation
// param         = parameter used in validation i.e. gt=0 param would be 0
type Func func(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool

// ValidationErrors is a type of map[string]*FieldError
// it exists to allow for multiple errors passed from this library
// and yet still comply to the error interface
type ValidationErrors map[string]*FieldError

// This is intended for use in development + debugging and not intended to be a production error message.
// It allows ValidationErrors to subscribe to the Error interface.
// All information to create an error message specific to your application is contained within
// the FieldError found in the ValidationErrors
func (ve ValidationErrors) Error() string {

	buff := bytes.NewBufferString("")

	for key, err := range ve {
		buff.WriteString(fmt.Sprintf(fieldErrMsg, key, err.Field, err.Tag))
	}

	return strings.TrimSpace(buff.String())
}

// FieldError contains a single field's validation error along
// with other properties that may be needed for error message creation
type FieldError struct {
	Field string
	Tag   string
	Kind  reflect.Kind
	Type  reflect.Type
	Param string
	Value interface{}
	// IsPlaceholderErr bool
	// IsSliceOrArray   bool
	// IsMap            bool
	// SliceOrArrayErrs map[int]error         // counld be FieldError, StructErrors
	// MapErrs          map[interface{}]error // counld be FieldError, StructErrors
}

// New creates a new Validate instance for use.
func New(config Config) *Validate {

	// structPool = &sync.Pool{New: newStructErrors}

	return &Validate{config: config}
}

// Field allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validate) Field(field interface{}, tag string) ValidationErrors {

	errs := map[string]*FieldError{}
	fieldVal := reflect.ValueOf(field)

	v.traverseField(fieldVal, fieldVal, fieldVal, "", errs, false, tag, "")

	return errs
}

// FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors {

	errs := map[string]*FieldError{}
	topVal := reflect.ValueOf(val)

	v.traverseField(topVal, topVal, reflect.ValueOf(field), "", errs, false, tag, "")

	return errs
}

// Struct validates a struct, even it's nested structs, and returns a struct containing the errors
// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
// the Array or Map.
func (v *Validate) Struct(current interface{}) ValidationErrors {

	errs := map[string]*FieldError{}
	sv := reflect.ValueOf(current)

	v.tranverseStruct(sv, sv, sv, "", errs)

	if len(errs) == 0 {
		return nil
	}

	return errs
}

func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors) {

	if current.Kind() == reflect.Ptr && !current.IsNil() {
		current = current.Elem()
	}

	if current.Kind() != reflect.Struct && current.Kind() != reflect.Interface {
		panic("value passed for validation is not a struct")
	}

	typ := current.Type()
	errPrefix += typ.Name() + "."
	numFields := current.NumField()

	var fld reflect.StructField

	for i := 0; i < numFields; i++ {
		fld = typ.Field(i)
		v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, errs, true, fld.Tag.Get(v.config.TagName), fld.Name)
	}
}

func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, isStructField bool, tag string, name string) {

	if tag == skipValidationTag {
		return
	}

	kind := current.Kind()

	if kind == reflect.Ptr && !current.IsNil() {
		current = current.Elem()
		kind = current.Kind()
	}

	typ := current.Type()

	// this also allows for tags 'required' and 'omitempty' to be used on
	// nested struct fields because when len(tags) > 0 below and the value is nil
	// then required failes and we check for omitempty just before that
	if (kind == reflect.Ptr || kind == reflect.Interface) && current.IsNil() {

		if strings.Contains(tag, omitempty) {
			return
		}

		tags := strings.Split(tag, tagSeparator)

		if len(tags) > 0 {

			var param string
			vals := strings.SplitN(tags[0], tagKeySeparator, 2)

			if len(vals) > 1 {
				param = vals[1]
			}

			errs[errPrefix+name] = &FieldError{
				Field: name,
				Tag:   vals[0],
				Param: param,
				Value: current.Interface(),
				Kind:  kind,
				Type:  typ,
			}

			return
		}
	}

	switch kind {

	case reflect.Invalid:
		panic(invaldField)
	case reflect.Struct, reflect.Interface:

		if kind == reflect.Interface {

			current = current.Elem()
			kind = current.Kind()

			if kind == reflect.Ptr && !current.IsNil() {
				current = current.Elem()
				kind = current.Kind()
			}

			// changed current, so have to get inner type again
			typ = current.Type()

			if kind != reflect.Struct {
				goto FALLTHROUGH
			}
		}

		if typ != timeType && typ != timePtrType {

			if isStructField {

				// required passed validationa above so stop here
				// if only validating the structs existance.
				if strings.Contains(tag, structOnlyTag) {
					return
				}

				v.tranverseStruct(topStruct, current, current, errPrefix, errs)
				return
			}

			panic(invaldField)
		}
	FALLTHROUGH:
		fallthrough
	default:
		if len(tag) == 0 {
			return
		}
	}

	var dive bool
	var diveSubTag string

	for _, t := range strings.Split(tag, tagSeparator) {

		if t == diveTag {

			dive = true
			diveSubTag = strings.TrimLeft(strings.SplitN(tag, diveTag, 2)[1], ",")
			break
		}

		// no use in checking tags if it's empty and is ok to be
		// omitempty needs to be the first tag if you wish to use it
		if t == omitempty {

			if !hasValue(topStruct, currentStruct, current, typ, kind, "") {
				return
			}
			continue
		}

		var key string
		var param string

		// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
		if strings.Index(t, orSeparator) == -1 {
			vals := strings.SplitN(t, tagKeySeparator, 2)
			key = vals[0]

			if len(key) == 0 {
				panic(fmt.Sprintf("Invalid validation tag on field %s", name))
			}

			if len(vals) > 1 {
				param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
			}
		} else {
			key = t
		}

		if v.validateField(topStruct, currentStruct, current, typ, kind, errPrefix, errs, key, param, name) {
			return
		}
	}

	if dive {
		// traverse slice or map here
		// or panic ;)
		switch kind {
		case reflect.Slice, reflect.Array:

		case reflect.Map:
			v.traverseSlice(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name)
		}
	}
}

// func (v *Validate) traverseSlice(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[int]error {
func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) {

	for i := 0; i < current.Len(); i++ {

		idxField := current.Index(i)

		if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
			idxField = idxField.Elem()
		}

		v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, name+"["+strconv.Itoa(i)+"]")
	}
}

// validateField validates a field based on the provided key tag and param and return true if there is an error false if all ok
func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, currentType reflect.Type, currentKind reflect.Kind, errPrefix string, errs ValidationErrors, key string, param string, name string) bool {

	// check if key is orVals, it could be!
	orVals := strings.Split(key, orSeparator)

	if len(orVals) > 1 {

		var errTag string

		for _, val := range orVals {
			vals := strings.SplitN(val, tagKeySeparator, 2)

			if len(vals[0]) == 0 {
				panic(fmt.Sprintf("Invalid validation tag on field %s", name))
			}

			param := ""
			if len(vals) > 1 {
				param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
			}

			// validate and keep track!
			valFunc, ok := v.config.ValidationFuncs[vals[0]]
			if !ok {
				panic(fmt.Sprintf("Undefined validation function on field %s", name))
			}

			if valFunc(topStruct, currentStruct, current, currentType, currentKind, param) {
				return false
			}

			errTag += orSeparator + vals[0]
		}

		errs[errPrefix+name] = &FieldError{
			Field: name,
			Tag:   errTag[1:],
			Value: current.Interface(),
			Param: param,
			Type:  currentType,
			Kind:  currentKind,
		}

		return true
	}

	valFunc, ok := v.config.ValidationFuncs[key]
	if !ok {
		panic(fmt.Sprintf("Undefined validation function on field %s", name))
	}

	if valFunc(topStruct, currentStruct, current, currentType, currentKind, param) {
		return false
	}

	errs[errPrefix+name] = &FieldError{
		Field: name,
		Tag:   key,
		Value: current.Interface(),
		Param: param,
		Type:  currentType,
		Kind:  currentKind,
	}

	return true
}
<commit_msg>Add traverseMap function<commit_after>/**
 * Package validator
 *
 * MISC:
 * - anonymous structs - they don't have names so expect the Struct name within StructErrors to be blank
 *
 */

package validator

import (
	"bytes"
	"fmt"
	"reflect"
	"strings"
	"time"
)

const (
	utf8HexComma        = "0x2C"
	utf8Pipe            = "0x7C"
	tagSeparator        = ","
	orSeparator         = "|"
	tagKeySeparator     = "="
	structOnlyTag       = "structonly"
	omitempty           = "omitempty"
	skipValidationTag   = "-"
	diveTag             = "dive"
	fieldErrMsg         = "Key: \"%s\" Error:Field validation for \"%s\" failed on the \"%s\" tag"
	invaldField         = "Invalid field passed to traverseField"
	arrayIndexFieldName = "%s[%d]"
	mapIndexFieldName   = "%s[%v]"
)

var (
	timeType    = reflect.TypeOf(time.Time{})
	timePtrType = reflect.TypeOf(&time.Time{})
)

// Validate implements the Validate Struct
// NOTE: Fields within are not thread safe and that is on purpose
// Functions and Tags should all be predifined before use, so subscribe to the philosiphy
// or make it thread safe on your end
type Validate struct {
	config Config
}

// Config contains the options that Validator with use
// passed to the New function
type Config struct {
	TagName         string
	ValidationFuncs map[string]Func
}

// Func accepts all values needed for file and cross field validation
// topStruct     = top level struct when validating by struct otherwise nil
// currentStruct = current level struct when validating by struct otherwise optional comparison value
// field         = field value for validation
// param         = parameter used in validation i.e. gt=0 param would be 0
type Func func(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool

// ValidationErrors is a type of map[string]*FieldError
// it exists to allow for multiple errors passed from this library
// and yet still comply to the error interface
type ValidationErrors map[string]*FieldError

// This is intended for use in development + debugging and not intended to be a production error message.
// It allows ValidationErrors to subscribe to the Error interface.
// All information to create an error message specific to your application is contained within
// the FieldError found in the ValidationErrors
func (ve ValidationErrors) Error() string {

	buff := bytes.NewBufferString("")

	for key, err := range ve {
		buff.WriteString(fmt.Sprintf(fieldErrMsg, key, err.Field, err.Tag))
	}

	return strings.TrimSpace(buff.String())
}

// FieldError contains a single field's validation error along
// with other properties that may be needed for error message creation
type FieldError struct {
	Field string
	Tag   string
	Kind  reflect.Kind
	Type  reflect.Type
	Param string
	Value interface{}
	// IsPlaceholderErr bool
	// IsSliceOrArray   bool
	// IsMap            bool
	// SliceOrArrayErrs map[int]error         // counld be FieldError, StructErrors
	// MapErrs          map[interface{}]error // counld be FieldError, StructErrors
}

// New creates a new Validate instance for use.
func New(config Config) *Validate {

	// structPool = &sync.Pool{New: newStructErrors}

	return &Validate{config: config}
}

// Field allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validate) Field(field interface{}, tag string) ValidationErrors {

	errs := map[string]*FieldError{}
	fieldVal := reflect.ValueOf(field)

	v.traverseField(fieldVal, fieldVal, fieldVal, "", errs, false, tag, "")

	return errs
}

// FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors {

	errs := map[string]*FieldError{}
	topVal := reflect.ValueOf(val)

	v.traverseField(topVal, topVal, reflect.ValueOf(field), "", errs, false, tag, "")

	return errs
}

// Struct validates a struct, even it's nested structs, and returns a struct containing the errors
// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
// the Array or Map.
func (v *Validate) Struct(current interface{}) ValidationErrors {

	errs := map[string]*FieldError{}
	sv := reflect.ValueOf(current)

	v.tranverseStruct(sv, sv, sv, "", errs, true)

	if len(errs) == 0 {
		return nil
	}

	return errs
}

func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, useStructName bool) {

	if current.Kind() == reflect.Ptr && !current.IsNil() {
		current = current.Elem()
	}

	if current.Kind() != reflect.Struct && current.Kind() != reflect.Interface {
		panic("value passed for validation is not a struct")
	}

	typ := current.Type()

	if useStructName {
		errPrefix += typ.Name() + "."
	}

	numFields := current.NumField()

	var fld reflect.StructField

	for i := 0; i < numFields; i++ {
		fld = typ.Field(i)
		v.traverseField(topStruct, currentStruct, current.Field(i), errPrefix, errs, true, fld.Tag.Get(v.config.TagName), fld.Name)
	}
}

func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, isStructField bool, tag string, name string) {

	if tag == skipValidationTag {
		return
	}

	kind := current.Kind()

	if kind == reflect.Ptr && !current.IsNil() {
		current = current.Elem()
		kind = current.Kind()
	}

	typ := current.Type()

	// this also allows for tags 'required' and 'omitempty' to be used on
	// nested struct fields because when len(tags) > 0 below and the value is nil
	// then required failes and we check for omitempty just before that
	if (kind == reflect.Ptr || kind == reflect.Interface) && current.IsNil() {

		if strings.Contains(tag, omitempty) {
			return
		}

		tags := strings.Split(tag, tagSeparator)

		if len(tags) > 0 {

			var param string
			vals := strings.SplitN(tags[0], tagKeySeparator, 2)

			if len(vals) > 1 {
				param = vals[1]
			}

			errs[errPrefix+name] = &FieldError{
				Field: name,
				Tag:   vals[0],
				Param: param,
				Value: current.Interface(),
				Kind:  kind,
				Type:  typ,
			}

			return
		}
	}

	switch kind {

	case reflect.Invalid:
		panic(invaldField)
	case reflect.Struct, reflect.Interface:

		if kind == reflect.Interface {

			current = current.Elem()
			kind = current.Kind()

			if kind == reflect.Ptr && !current.IsNil() {
				current = current.Elem()
				kind = current.Kind()
			}

			// changed current, so have to get inner type again
			typ = current.Type()

			if kind != reflect.Struct {
				goto FALLTHROUGH
			}
		}

		if typ != timeType && typ != timePtrType {

			if isStructField {

				// required passed validationa above so stop here
				// if only validating the structs existance.
				if strings.Contains(tag, structOnlyTag) {
					return
				}

				v.tranverseStruct(topStruct, current, current, errPrefix+name+".", errs, false)
				return
			}

			panic(invaldField)
		}
	FALLTHROUGH:
		fallthrough
	default:
		if len(tag) == 0 {
			return
		}
	}

	var dive bool
	var diveSubTag string

	for _, t := range strings.Split(tag, tagSeparator) {

		if t == diveTag {

			dive = true
			diveSubTag = strings.TrimLeft(strings.SplitN(tag, diveTag, 2)[1], ",")
			break
		}

		// no use in checking tags if it's empty and is ok to be
		// omitempty needs to be the first tag if you wish to use it
		if t == omitempty {

			if !hasValue(topStruct, currentStruct, current, typ, kind, "") {
				return
			}
			continue
		}

		var key string
		var param string

		// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
		if strings.Index(t, orSeparator) == -1 {
			vals := strings.SplitN(t, tagKeySeparator, 2)
			key = vals[0]

			if len(key) == 0 {
				panic(fmt.Sprintf("Invalid validation tag on field %s", name))
			}

			if len(vals) > 1 {
				param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
			}
		} else {
			key = t
		}

		if v.validateField(topStruct, currentStruct, current, typ, kind, errPrefix, errs, key, param, name) {
			return
		}
	}

	if dive {
		// traverse slice or map here
		// or panic ;)
		switch kind {
		case reflect.Slice, reflect.Array:
			v.traverseSlice(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name)
		case reflect.Map:
			v.traverseMap(topStruct, currentStruct, current, errPrefix, errs, diveSubTag, name)
		default:
			// throw error, if not a slice or map then should not have gotten here
			// bad dive tag usage
			panic("dive error! can't dive on a non slice or map")
		}
	}
}

func (v *Validate) traverseSlice(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) {

	for i := 0; i < current.Len(); i++ {

		idxField := current.Index(i)

		if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
			idxField = idxField.Elem()
		}

		v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, fmt.Sprintf(arrayIndexFieldName, name, i))
	}
}

func (v *Validate) traverseMap(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, tag string, name string) {

	for _, key := range current.MapKeys() {

		idxField := current.MapIndex(key)

		if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
			idxField = idxField.Elem()
		}

		v.traverseField(topStruct, currentStruct, current, errPrefix, errs, false, tag, fmt.Sprintf(mapIndexFieldName, name, key.Interface()))
	}
}

// validateField validates a field based on the provided key tag and param and return true if there is an error false if all ok
func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, currentType reflect.Type, currentKind reflect.Kind, errPrefix string, errs ValidationErrors, key string, param string, name string) bool {

	// check if key is orVals, it could be!
	orVals := strings.Split(key, orSeparator)

	if len(orVals) > 1 {

		var errTag string

		for _, val := range orVals {
			vals := strings.SplitN(val, tagKeySeparator, 2)

			if len(vals[0]) == 0 {
				panic(fmt.Sprintf("Invalid validation tag on field %s", name))
			}

			param := ""
			if len(vals) > 1 {
				param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
			}

			// validate and keep track!
			valFunc, ok := v.config.ValidationFuncs[vals[0]]
			if !ok {
				panic(fmt.Sprintf("Undefined validation function on field %s", name))
			}

			if valFunc(topStruct, currentStruct, current, currentType, currentKind, param) {
				return false
			}

			errTag += orSeparator + vals[0]
		}

		errs[errPrefix+name] = &FieldError{
			Field: name,
			Tag:   errTag[1:],
			Value: current.Interface(),
			Param: param,
			Type:  currentType,
			Kind:  currentKind,
		}

		return true
	}

	valFunc, ok := v.config.ValidationFuncs[key]
	if !ok {
		panic(fmt.Sprintf("Undefined validation function on field %s", name))
	}

	if valFunc(topStruct, currentStruct, current, currentType, currentKind, param) {
		return false
	}

	errs[errPrefix+name] = &FieldError{
		Field: name,
		Tag:   key,
		Value: current.Interface(),
		Param: param,
		Type:  currentType,
		Kind:  currentKind,
	}

	return true
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/stealthycoin/rhynock"
	"net/http"
)

type Router struct {
	// Kind of sorta keep track of who is connected
	connections map[*rhynock.Connection]bool

	// Channel to recieve bottles through
	bottle     chan *rhynock.Bottle
}

// Satisfy the BottleDst interface
func (r *Router) GetBottleChan() (chan *rhynock.Bottle) {
	return r.bottle
}

// Satisfy the BottleDst interface
func (r *Router) ConnectionClosed(c *rhynock.Connection) {
	delete(r.connections, c)
}

// Satisfy the BottleDst interface
func (r *Router) ConnectionOpened(c *rhynock.Connection) {
	// This should put the connection into an authenticating mode
	// and then upon authentication the connection is added to a map
	// where the value points at some kind of profile object
	// can all c.Close() upon failing to authenticate
	r.connections[c] = true
}

func main() {
	router := &Router{
		connections: make(map[*rhynock.Connection]bool),
		bottle: make(chan *rhynock.Bottle),
	}

	// Register the route to rhynock handler function and pass in our BottleDst
	http.HandleFunc("/socket/", func (w http.ResponseWriter, r *http.Request) {
		rhynock.ConnectionHandler(w, r, router)
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "index.html")
	})

	// Start router listening routine
	go func() {
		for {
			// Listen for a bottle
			btl := <- router.bottle

			// Loop through all active connections
			for c, _ := range router.connections {
				// Send everyone the message
				c.Send <- btl.Message
			}
		}
	}()

	http.ListenAndServe("127.0.0.1:8002", nil)
}
<commit_msg>User port 8000<commit_after>package main

import (
	"github.com/stealthycoin/rhynock"
	"net/http"
)

type Router struct {
	// Kind of sorta keep track of who is connected
	connections map[*rhynock.Connection]bool

	// Channel to recieve bottles through
	bottle     chan *rhynock.Bottle
}

// Satisfy the BottleDst interface
func (r *Router) GetBottleChan() (chan *rhynock.Bottle) {
	return r.bottle
}

// Satisfy the BottleDst interface
func (r *Router) ConnectionClosed(c *rhynock.Connection) {
	delete(r.connections, c)
}

// Satisfy the BottleDst interface
func (r *Router) ConnectionOpened(c *rhynock.Connection) {
	// This should put the connection into an authenticating mode
	// and then upon authentication the connection is added to a map
	// where the value points at some kind of profile object
	// can all c.Close() upon failing to authenticate
	r.connections[c] = true
}

func main() {
	router := &Router{
		connections: make(map[*rhynock.Connection]bool),
		bottle: make(chan *rhynock.Bottle),
	}

	// Register the route to rhynock handler function and pass in our BottleDst
	http.HandleFunc("/socket/", func (w http.ResponseWriter, r *http.Request) {
		rhynock.ConnectionHandler(w, r, router)
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "index.html")
	})

	// Start router listening routine
	go func() {
		for {
			// Listen for a bottle
			btl := <- router.bottle

			// Loop through all active connections
			for c, _ := range router.connections {
				// Send everyone the message
				c.Send <- btl.Message
			}
		}
	}()

	http.ListenAndServe("127.0.0.1:8000", nil)
}
<|endoftext|>


<commit_before>package sitemap

import (
	"encoding/xml"
	"errors"
	"io/ioutil"
	"net/http"
	"time"
)

// Index is a structure of <sitemapindex>
type Index struct {
	XMLName xml.Name `xml:"sitemapindex"`
	Sitemap []parts  `xml:"sitemap"`
}

// Parts is a structure of <sitemap> in <sitemapindex>
type parts struct {
	Loc     string `xml:"loc"`
	LastMod string `xml:"lastmod"`
}

// Sitemap is a structure of <sitemap>
type Sitemap struct {
	XMLName xml.Name `xml:"urlset"`
	URL     []URL    `xml:"url"`
}

// URL is a structure of <url> in <sitemap>
type URL struct {
	Loc        string  `xml:"loc"`
	LastMod    string  `xml:"lastmod"`
	ChangeFreq string  `xml:"changefreq"`
	Priority   float32 `xml:"priority"`
}

// fetch is page acquisition function
var fetch = func(url string) ([]byte, error) {
	var body []byte

	res, err := http.Get(url)
	if err != nil {
		return body, err
	}
	defer res.Body.Close()

	body, err = ioutil.ReadAll(res.Body)
	if err != nil {
		return body, err
	}

	return body, err
}

// Time interval to be used in Index.get
var interval = time.Second

// Get sitemap data from URL
func Get(url string) (Sitemap, error) {
	data, err := fetch(url)
	if err != nil {
		return Sitemap{}, err
	}

	index, indexErr := ParseIndex(data)
	sitemap, sitemapErr := Parse(data)

	if indexErr != nil && sitemapErr != nil {
		err = errors.New("URL is not a sitemap or sitemapindex")
		return Sitemap{}, err
	}

	if indexErr == nil {
		sitemap, err = index.get(data)
		if err != nil {
			return Sitemap{}, err
		}
	}

	return sitemap, err
}

// Get Sitemap data from sitemapindex file
func (s *Index) get(data []byte) (Sitemap, error) {
	index, err := ParseIndex(data)
	if err != nil {
		return Sitemap{}, err
	}

	var sitemap Sitemap
	for _, s := range index.Sitemap {
		time.Sleep(interval)
		data, err := fetch(s.Loc)
		if err != nil {
			return sitemap, err
		}

		err = xml.Unmarshal(data, &sitemap)
		if err != nil {
			return sitemap, err
		}
	}

	return sitemap, err
}

// Parse create Sitemap data from text
func Parse(data []byte) (Sitemap, error) {
	var sitemap Sitemap
	err := xml.Unmarshal(data, &sitemap)

	return sitemap, err
}

// ParseIndex create Index data from text
func ParseIndex(data []byte) (Index, error) {
	var index Index
	err := xml.Unmarshal(data, &index)

	return index, err
}

// SetInterval change Time interval to be used in Index.get
func SetInterval(time time.Duration) {
	interval = time
}

// SetFetch change fetch closure
func SetFetch(f func(url string) ([]byte, error)) {
	fetch = f
}
<commit_msg>fix incorrect comment<commit_after>package sitemap

import (
	"encoding/xml"
	"errors"
	"io/ioutil"
	"net/http"
	"time"
)

// Index is a structure of <sitemapindex>
type Index struct {
	XMLName xml.Name `xml:"sitemapindex"`
	Sitemap []parts  `xml:"sitemap"`
}

// parts is a structure of <sitemap> in <sitemapindex>
type parts struct {
	Loc     string `xml:"loc"`
	LastMod string `xml:"lastmod"`
}

// Sitemap is a structure of <sitemap>
type Sitemap struct {
	XMLName xml.Name `xml:"urlset"`
	URL     []URL    `xml:"url"`
}

// URL is a structure of <url> in <sitemap>
type URL struct {
	Loc        string  `xml:"loc"`
	LastMod    string  `xml:"lastmod"`
	ChangeFreq string  `xml:"changefreq"`
	Priority   float32 `xml:"priority"`
}

// fetch is page acquisition function
var fetch = func(url string) ([]byte, error) {
	var body []byte

	res, err := http.Get(url)
	if err != nil {
		return body, err
	}
	defer res.Body.Close()

	body, err = ioutil.ReadAll(res.Body)
	if err != nil {
		return body, err
	}

	return body, err
}

// Time interval to be used in Index.get
var interval = time.Second

// Get sitemap data from URL
func Get(url string) (Sitemap, error) {
	data, err := fetch(url)
	if err != nil {
		return Sitemap{}, err
	}

	index, indexErr := ParseIndex(data)
	sitemap, sitemapErr := Parse(data)

	if indexErr != nil && sitemapErr != nil {
		err = errors.New("URL is not a sitemap or sitemapindex")
		return Sitemap{}, err
	}

	if indexErr == nil {
		sitemap, err = index.get(data)
		if err != nil {
			return Sitemap{}, err
		}
	}

	return sitemap, err
}

// Get Sitemap data from sitemapindex file
func (s *Index) get(data []byte) (Sitemap, error) {
	index, err := ParseIndex(data)
	if err != nil {
		return Sitemap{}, err
	}

	var sitemap Sitemap
	for _, s := range index.Sitemap {
		time.Sleep(interval)
		data, err := fetch(s.Loc)
		if err != nil {
			return sitemap, err
		}

		err = xml.Unmarshal(data, &sitemap)
		if err != nil {
			return sitemap, err
		}
	}

	return sitemap, err
}

// Parse create Sitemap data from text
func Parse(data []byte) (Sitemap, error) {
	var sitemap Sitemap
	err := xml.Unmarshal(data, &sitemap)

	return sitemap, err
}

// ParseIndex create Index data from text
func ParseIndex(data []byte) (Index, error) {
	var index Index
	err := xml.Unmarshal(data, &index)

	return index, err
}

// SetInterval change Time interval to be used in Index.get
func SetInterval(time time.Duration) {
	interval = time
}

// SetFetch change fetch closure
func SetFetch(f func(url string) ([]byte, error)) {
	fetch = f
}
<|endoftext|>


<commit_before>package ray

import (
	"io"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
)

const (
	bufferSize = 128
)

// NewRay creates a new Ray for direct traffic transport.
func NewRay() Ray {
	return &directRay{
		Input:  NewStream(),
		Output: NewStream(),
	}
}

type directRay struct {
	Input  *Stream
	Output *Stream
}

func (this *directRay) OutboundInput() InputStream {
	return this.Input
}

func (this *directRay) OutboundOutput() OutputStream {
	return this.Output
}

func (this *directRay) InboundInput() OutputStream {
	return this.Input
}

func (this *directRay) InboundOutput() InputStream {
	return this.Output
}

type Stream struct {
	access sync.RWMutex
	closed bool
	buffer chan *alloc.Buffer
}

func NewStream() *Stream {
	return &Stream{
		buffer: make(chan *alloc.Buffer, bufferSize),
	}
}

func (this *Stream) Read() (*alloc.Buffer, error) {
	if this.buffer == nil {
		return nil, io.EOF
	}
	this.access.RLock()
	defer this.access.RUnlock()
	if this.buffer == nil {
		return nil, io.EOF
	}
	result, open := <-this.buffer
	if !open {
		return nil, io.EOF
	}
	return result, nil
}

func (this *Stream) Write(data *alloc.Buffer) error {
	if this.closed {
		return io.EOF
	}
	if this.buffer == nil {
		return io.EOF
	}
	this.access.RLock()
	defer this.access.RUnlock()
	if this.closed {
		return io.EOF
	}
	if this.buffer == nil {
		return io.EOF
	}
	this.buffer <- data
	return nil
}

func (this *Stream) Close() {
	if this.closed {
		return
	}
	this.access.RLock()
	defer this.access.RUnlock()
	if this.closed {
		return
	}
	this.closed = true
	close(this.buffer)
}

func (this *Stream) Release() {
	if this.buffer == nil {
		return
	}
	this.Close()
	this.access.Lock()
	defer this.access.Unlock()
	if this.buffer == nil {
		return
	}
	for data := range this.buffer {
		data.Release()
	}
	this.buffer = nil
}
<commit_msg>fix again the race condition issue<commit_after>package ray

import (
	"io"
	"sync"

	"github.com/v2ray/v2ray-core/common/alloc"
)

const (
	bufferSize = 128
)

// NewRay creates a new Ray for direct traffic transport.
func NewRay() Ray {
	return &directRay{
		Input:  NewStream(),
		Output: NewStream(),
	}
}

type directRay struct {
	Input  *Stream
	Output *Stream
}

func (this *directRay) OutboundInput() InputStream {
	return this.Input
}

func (this *directRay) OutboundOutput() OutputStream {
	return this.Output
}

func (this *directRay) InboundInput() OutputStream {
	return this.Input
}

func (this *directRay) InboundOutput() InputStream {
	return this.Output
}

type Stream struct {
	access sync.RWMutex
	closed bool
	buffer chan *alloc.Buffer
}

func NewStream() *Stream {
	return &Stream{
		buffer: make(chan *alloc.Buffer, bufferSize),
	}
}

func (this *Stream) Read() (*alloc.Buffer, error) {
	if this.buffer == nil {
		return nil, io.EOF
	}
	this.access.RLock()
	if this.buffer == nil {
		this.access.RUnlock()
		return nil, io.EOF
	}
	channel := this.buffer
	this.access.RUnlock()
	result, open := <-channel
	if !open {
		return nil, io.EOF
	}
	return result, nil
}

func (this *Stream) Write(data *alloc.Buffer) error {
	if this.closed {
		return io.EOF
	}
	this.access.RLock()
	defer this.access.RUnlock()
	if this.closed {
		return io.EOF
	}
	this.buffer <- data
	return nil
}

func (this *Stream) Close() {
	if this.closed {
		return
	}
	this.access.Lock()
	defer this.access.Unlock()
	if this.closed {
		return
	}
	this.closed = true
	close(this.buffer)
}

func (this *Stream) Release() {
	if this.buffer == nil {
		return
	}
	this.Close()
	this.access.Lock()
	defer this.access.Unlock()
	if this.buffer == nil {
		return
	}
	for data := range this.buffer {
		data.Release()
	}
	this.buffer = nil
}
<|endoftext|>


<commit_before>/*
    DNS-over-HTTPS
    Copyright (C) 2017 Star Brilliant <m13253@hotmail.com>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strconv"
	"strings"
	"time"
	"github.com/miekg/dns"
	"../json-dns"
)

type Client struct {
	addr			string
	upstream		string
	bootstraps		[]string
	timeout			uint
	noECS			bool
	verbose			bool
	udpServer		*dns.Server
	tcpServer		*dns.Server
	httpClient		*http.Client
}

func NewClient(addr, upstream string, bootstraps []string, timeout uint, noECS, verbose bool) (c *Client, err error) {
	c = &Client {
		addr: addr,
		upstream: upstream,
		bootstraps: bootstraps,
		timeout: timeout,
		noECS: noECS,
		verbose: verbose,
	}
	c.udpServer = &dns.Server {
		Addr: addr,
		Net: "udp",
		Handler: dns.HandlerFunc(c.udpHandlerFunc),
		UDPSize: 4096,
	}
	c.tcpServer = &dns.Server {
		Addr: addr,
		Net: "tcp",
		Handler: dns.HandlerFunc(c.tcpHandlerFunc),
	}
	bootResolver := net.DefaultResolver
	if len(c.bootstraps) != 0 {
		for i, bootstrap := range c.bootstraps {
			bootstrapAddr, err := net.ResolveUDPAddr("udp", bootstrap)
			if err != nil {
				bootstrapAddr, err = net.ResolveUDPAddr("udp", "[" + bootstrap + "]:53")
			}
			if err != nil { return nil, err }
			c.bootstraps[i] = bootstrapAddr.String()
		}
		bootResolver = &net.Resolver {
			PreferGo: true,
			Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
				var d net.Dialer
				num_servers := len(c.bootstraps)
				bootstrap := c.bootstraps[rand.Intn(num_servers)]
				conn, err := d.DialContext(ctx, network, bootstrap)
				return conn, err
			},
		}
	}
	httpTransport := *http.DefaultTransport.(*http.Transport)
	httpTransport.DialContext = (&net.Dialer {
		Timeout: time.Duration(c.timeout) * time.Second,
		KeepAlive: 30 * time.Second,
		DualStack: true,
		Resolver: bootResolver,
	}).DialContext
	// Most CDNs require Cookie support to prevent DDoS attack
	cookieJar, err := cookiejar.New(nil)
	if err != nil { return nil, err }
	c.httpClient = &http.Client {
		Transport: &httpTransport,
		Jar: cookieJar,
	}
	return c, nil
}

func (c *Client) Start() error {
	result := make(chan error)
	go func() {
		err := c.udpServer.ListenAndServe()
		if err != nil {
			log.Println(err)
		}
		result <- err
	} ()
	go func() {
		err := c.tcpServer.ListenAndServe()
		if err != nil {
			log.Println(err)
		}
		result <- err
	} ()
	err := <-result
	if err != nil {
		return err
	}
	err = <-result
	return err
}

func (c *Client) handlerFunc(w dns.ResponseWriter, r *dns.Msg, isTCP bool) {
	if r.Response == true {
		log.Println("Received a response packet")
		return
	}

	reply := jsonDNS.PrepareReply(r)

	if len(r.Question) != 1 {
		log.Println("Number of questions is not 1")
		reply.Rcode = dns.RcodeFormatError
		w.WriteMsg(reply)
		return
	}
	question := r.Question[0]
	questionName := strings.ToLower(question.Name)
	questionType := ""
	if qtype, ok := dns.TypeToString[question.Qtype]; ok {
		questionType = qtype
	} else {
		questionType = strconv.Itoa(int(question.Qtype))
	}

	if c.verbose{
		fmt.Printf("%s - - [%s] \"%s IN %s\"\n", w.RemoteAddr(), time.Now().Format("02/Jan/2006:15:04:05 -0700"), questionName, questionType)
	}

	requestURL := fmt.Sprintf("%s?name=%s&type=%s", c.upstream, url.QueryEscape(questionName), url.QueryEscape(questionType))

	if r.CheckingDisabled {
		requestURL += "&cd=1"
	}

	udpSize := uint16(512)
	if opt := r.IsEdns0(); opt != nil {
		udpSize = opt.UDPSize()
	}

	ednsClientAddress, ednsClientNetmask := c.findClientIP(w, r)
	if ednsClientAddress != nil {
		requestURL += fmt.Sprintf("&edns_client_subnet=%s/%d", ednsClientAddress.String(), ednsClientNetmask)
	}

	req, err := http.NewRequest("GET", requestURL, nil)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	req.Header.Set("User-Agent", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)")
	resp, err := c.httpClient.Do(req)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	if resp.StatusCode != 200 {
		log.Printf("HTTP error: %s\n", resp.Status)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	var respJson jsonDNS.Response
	err = json.Unmarshal(body, &respJson)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	fullReply := jsonDNS.Unmarshal(reply, &respJson, udpSize, ednsClientNetmask)
	buf, err := fullReply.Pack()
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	if !isTCP && len(buf) > int(udpSize) {
		fullReply.Truncated = true
		buf, err = fullReply.Pack()
		if err != nil {
			log.Println(err)
			return
		}
		buf = buf[:udpSize]
	}
	w.Write(buf)
}

func (c *Client) udpHandlerFunc(w dns.ResponseWriter, r *dns.Msg) {
	c.handlerFunc(w, r, false)
}

func (c *Client) tcpHandlerFunc(w dns.ResponseWriter, r *dns.Msg) {
	c.handlerFunc(w, r, true)
}

var (
	ipv4Mask24	net.IPMask = net.IPMask { 255, 255, 255, 0 }
	ipv6Mask48	net.IPMask = net.CIDRMask(48, 128)
)

func (c *Client) findClientIP(w dns.ResponseWriter, r *dns.Msg) (ednsClientAddress net.IP, ednsClientNetmask uint8) {
	ednsClientNetmask = 255
	if c.noECS {
		return net.IPv4(0, 0, 0, 0), 0
	}
	if opt := r.IsEdns0(); opt != nil {
		for _, option := range opt.Option {
			if option.Option() == dns.EDNS0SUBNET {
				edns0Subnet := option.(*dns.EDNS0_SUBNET)
				ednsClientAddress = edns0Subnet.Address
				ednsClientNetmask = edns0Subnet.SourceNetmask
				return
			}
		}
	}
	remoteAddr, err := net.ResolveUDPAddr("udp", w.RemoteAddr().String())
	if err != nil {
		return
	}
	if ip := remoteAddr.IP; jsonDNS.IsGlobalIP(ip) {
		if ipv4 := ip.To4(); ipv4 != nil {
			ednsClientAddress = ipv4.Mask(ipv4Mask24)
			ednsClientNetmask = 24
		} else {
			ednsClientAddress = ip.Mask(ipv6Mask48)
			ednsClientNetmask = 48
		}
	}
	return
}
<commit_msg>Add ResponseHeaderTimeout<commit_after>/*
    DNS-over-HTTPS
    Copyright (C) 2017 Star Brilliant <m13253@hotmail.com>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strconv"
	"strings"
	"time"
	"github.com/miekg/dns"
	"../json-dns"
)

type Client struct {
	addr			string
	upstream		string
	bootstraps		[]string
	timeout			uint
	noECS			bool
	verbose			bool
	udpServer		*dns.Server
	tcpServer		*dns.Server
	httpClient		*http.Client
}

func NewClient(addr, upstream string, bootstraps []string, timeout uint, noECS, verbose bool) (c *Client, err error) {
	c = &Client {
		addr: addr,
		upstream: upstream,
		bootstraps: bootstraps,
		timeout: timeout,
		noECS: noECS,
		verbose: verbose,
	}
	c.udpServer = &dns.Server {
		Addr: addr,
		Net: "udp",
		Handler: dns.HandlerFunc(c.udpHandlerFunc),
		UDPSize: 4096,
	}
	c.tcpServer = &dns.Server {
		Addr: addr,
		Net: "tcp",
		Handler: dns.HandlerFunc(c.tcpHandlerFunc),
	}
	bootResolver := net.DefaultResolver
	if len(c.bootstraps) != 0 {
		for i, bootstrap := range c.bootstraps {
			bootstrapAddr, err := net.ResolveUDPAddr("udp", bootstrap)
			if err != nil {
				bootstrapAddr, err = net.ResolveUDPAddr("udp", "[" + bootstrap + "]:53")
			}
			if err != nil { return nil, err }
			c.bootstraps[i] = bootstrapAddr.String()
		}
		bootResolver = &net.Resolver {
			PreferGo: true,
			Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
				var d net.Dialer
				num_servers := len(c.bootstraps)
				bootstrap := c.bootstraps[rand.Intn(num_servers)]
				conn, err := d.DialContext(ctx, network, bootstrap)
				return conn, err
			},
		}
	}
	httpTransport := *http.DefaultTransport.(*http.Transport)
	httpTransport.DialContext = (&net.Dialer {
		Timeout: time.Duration(c.timeout) * time.Second,
		KeepAlive: 30 * time.Second,
		DualStack: true,
		Resolver: bootResolver,
	}).DialContext
	httpTransport.ResponseHeaderTimeout = time.Duration(c.timeout) * time.Second
	// Most CDNs require Cookie support to prevent DDoS attack
	cookieJar, err := cookiejar.New(nil)
	if err != nil { return nil, err }
	c.httpClient = &http.Client {
		Transport: &httpTransport,
		Jar: cookieJar,
	}
	return c, nil
}

func (c *Client) Start() error {
	result := make(chan error)
	go func() {
		err := c.udpServer.ListenAndServe()
		if err != nil {
			log.Println(err)
		}
		result <- err
	} ()
	go func() {
		err := c.tcpServer.ListenAndServe()
		if err != nil {
			log.Println(err)
		}
		result <- err
	} ()
	err := <-result
	if err != nil {
		return err
	}
	err = <-result
	return err
}

func (c *Client) handlerFunc(w dns.ResponseWriter, r *dns.Msg, isTCP bool) {
	if r.Response == true {
		log.Println("Received a response packet")
		return
	}

	reply := jsonDNS.PrepareReply(r)

	if len(r.Question) != 1 {
		log.Println("Number of questions is not 1")
		reply.Rcode = dns.RcodeFormatError
		w.WriteMsg(reply)
		return
	}
	question := r.Question[0]
	questionName := strings.ToLower(question.Name)
	questionType := ""
	if qtype, ok := dns.TypeToString[question.Qtype]; ok {
		questionType = qtype
	} else {
		questionType = strconv.Itoa(int(question.Qtype))
	}

	if c.verbose{
		fmt.Printf("%s - - [%s] \"%s IN %s\"\n", w.RemoteAddr(), time.Now().Format("02/Jan/2006:15:04:05 -0700"), questionName, questionType)
	}

	requestURL := fmt.Sprintf("%s?name=%s&type=%s", c.upstream, url.QueryEscape(questionName), url.QueryEscape(questionType))

	if r.CheckingDisabled {
		requestURL += "&cd=1"
	}

	udpSize := uint16(512)
	if opt := r.IsEdns0(); opt != nil {
		udpSize = opt.UDPSize()
	}

	ednsClientAddress, ednsClientNetmask := c.findClientIP(w, r)
	if ednsClientAddress != nil {
		requestURL += fmt.Sprintf("&edns_client_subnet=%s/%d", ednsClientAddress.String(), ednsClientNetmask)
	}

	req, err := http.NewRequest("GET", requestURL, nil)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	req.Header.Set("User-Agent", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)")
	resp, err := c.httpClient.Do(req)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	if resp.StatusCode != 200 {
		log.Printf("HTTP error: %s\n", resp.Status)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	var respJson jsonDNS.Response
	err = json.Unmarshal(body, &respJson)
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}

	fullReply := jsonDNS.Unmarshal(reply, &respJson, udpSize, ednsClientNetmask)
	buf, err := fullReply.Pack()
	if err != nil {
		log.Println(err)
		reply.Rcode = dns.RcodeServerFailure
		w.WriteMsg(reply)
		return
	}
	if !isTCP && len(buf) > int(udpSize) {
		fullReply.Truncated = true
		buf, err = fullReply.Pack()
		if err != nil {
			log.Println(err)
			return
		}
		buf = buf[:udpSize]
	}
	w.Write(buf)
}

func (c *Client) udpHandlerFunc(w dns.ResponseWriter, r *dns.Msg) {
	c.handlerFunc(w, r, false)
}

func (c *Client) tcpHandlerFunc(w dns.ResponseWriter, r *dns.Msg) {
	c.handlerFunc(w, r, true)
}

var (
	ipv4Mask24	net.IPMask = net.IPMask { 255, 255, 255, 0 }
	ipv6Mask48	net.IPMask = net.CIDRMask(48, 128)
)

func (c *Client) findClientIP(w dns.ResponseWriter, r *dns.Msg) (ednsClientAddress net.IP, ednsClientNetmask uint8) {
	ednsClientNetmask = 255
	if c.noECS {
		return net.IPv4(0, 0, 0, 0), 0
	}
	if opt := r.IsEdns0(); opt != nil {
		for _, option := range opt.Option {
			if option.Option() == dns.EDNS0SUBNET {
				edns0Subnet := option.(*dns.EDNS0_SUBNET)
				ednsClientAddress = edns0Subnet.Address
				ednsClientNetmask = edns0Subnet.SourceNetmask
				return
			}
		}
	}
	remoteAddr, err := net.ResolveUDPAddr("udp", w.RemoteAddr().String())
	if err != nil {
		return
	}
	if ip := remoteAddr.IP; jsonDNS.IsGlobalIP(ip) {
		if ipv4 := ip.To4(); ipv4 != nil {
			ednsClientAddress = ipv4.Mask(ipv4Mask24)
			ednsClientNetmask = 24
		} else {
			ednsClientAddress = ip.Mask(ipv6Mask48)
			ednsClientNetmask = 48
		}
	}
	return
}
<|endoftext|>


<commit_before><commit_msg>max retention allow increase 1week -> 3week<commit_after><|endoftext|>