<commit_before>/*

LICENSE:  MIT
Author:   sine
Email:    sinerwr@gmail.com

*/

package controller

import (
	"encoding/json"
	"github.com/getsentry/raven-go"
	"golang.org/x/net/context"
	"io/ioutil"
	"net/http"

	"github.com/SiCo-Ops/Pb"
	"github.com/SiCo-Ops/dao/grpc"
	// "github.com/SiCo-Ops/dao/mongo"
)

var (
	cloudTokenID  string
	cloudTokenKey string
	cloudRegion   string
	cloudService  string
)

type ThirdToken struct {
	PrivateToken AuthenticationToken `json:"token"`
	Cloud        string              `json:"cloud"`
	Name         string              `json:"name"`
	ID           string              `json:"id"`
	Key          string              `json:"key"`
}

type CloudAPIRequest struct {
	PrivateToken   AuthenticationToken `json:"token"`
	CloudTokenName string              `json:"name"`
	Region         string              `json:"region"`
	Action         string              `json:"action"`
	Param          map[string]string   `json:"params"`
}

type CloudAPIRawRequest struct {
	Token         string            `json:"token"`
	CloudTokenID  string            `json:"cloudid"`
	CloudTokenKey string            `json:"cloudkey"`
	Region        string            `json:"region"`
	Action        string            `json:"action"`
	Param         map[string]string `json:"params"`
}

type CloudAPIResponse struct {
	Code int64  `json:"code"`
	Msg  string `json:"msg"`
	Data string `json:"data"`
}

func CloudTokenRegistry(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
		if rcv := recover(); rcv != nil {
			raven.CaptureMessage("controller.CloudTokenRegistry", nil)
		}
	}()
	data, ok := ValidatePostData(rw, req)
	v := &ThirdToken{}
	if ok {
		json.Unmarshal(data, v)
	} else {
		return
	}
	if v.Name == "" || v.Cloud == "" || v.ID == "" {
		rsp, _ := json.Marshal(ResponseErrmsg(2))
		httprsp(rw, rsp)
		return
	}
	if config.AAAEnable && !AAAValidateToken(v.PrivateToken.ID, v.PrivateToken.Signature) {
		rsp, _ := json.Marshal(ResponseErrmsg(1))
		httprsp(rw, rsp)
		return
	}
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudTokenServiceClient(cc)
	in := &pb.CloudTokenCall{}
	in.Cloud = v.Cloud
	in.Name = v.Name
	in.Id = v.ID
	in.Key = v.Key
	in.AAATokenID = v.PrivateToken.ID
	r, err := c.TokenSet(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if r.Id != "" {
		rsp, _ := json.Marshal(&ResponseData{0, "Success"})
		httprsp(rw, rsp)
		return
	}
	rsp, _ := json.Marshal(ResponseErrmsg(2))
	httprsp(rw, rsp)
}

func CloudTokenGet(id string, cloud string, name string) (string, string) {
	in := &pb.CloudTokenCall{}
	in.AAATokenID = id
	in.Cloud = cloud
	in.Name = name
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudTokenServiceClient(cc)
	res, err := c.TokenGet(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if res.Id != "" {
		return res.Id, res.Key
	}
	return "", ""
}

func CloudServiceIsSupport(cloud string, service string) bool {
	d, err := ioutil.ReadFile("cloud.json")
	if err != nil {
		raven.CaptureError(err, nil)
		return false
	}
	var v map[string][]string
	json.Unmarshal(d, &v)
	if value, ok := v[cloud]; ok {
		for _, v := range value {
			if v == service {
				return true
			}
		}
		return false
	}
	return false
}

func CloudAPICall(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
	}()
	data, ok := ValidatePostData(rw, req)
	if !ok {
		return
	}
	v := &CloudAPIRequest{}
	json.Unmarshal(data, v)

	if !AAAValidateToken(v.PrivateToken.ID, v.PrivateToken.Signature) {
		rsp, _ := json.Marshal(ResponseErrmsg(2))
		httprsp(rw, rsp)
		return
	}

	cloud := getRouteName(req, "cloud")
	service := getRouteName(req, "service")
	action, ok := actionMap(cloud, service, v.Action)
	if !ok {
		rsp, _ := json.Marshal(ResponseErrmsg(4))
		httprsp(rw, rsp)
		return
	}

	cloudTokenID, cloudTokenKey = CloudTokenGet(v.PrivateToken.ID, cloud, v.CloudTokenName)

	in := &pb.CloudAPICall{Cloud: cloud, Service: service, Action: action, Region: v.Region, CloudId: cloudTokenID, CloudKey: cloudTokenKey}
	in.Params = v.Param
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudAPIServiceClient(cc)
	var res *pb.CloudAPIBack
	res, _ = c.RequestRPC(context.Background(), in)
	if res.Code == 0 {
		rsp := res.Data
		httprsp(rw, rsp)
		return
	}
	rsp, _ := json.Marshal(res)
	httprsp(rw, rsp)
}

func CloudAPICallRaw(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
	}()
	data, ok := ValidatePostData(rw, req)
	if !ok {
		return
	}
	v := &CloudAPIRawRequest{}
	json.Unmarshal(data, v)
	if !ValidateOpenToken(v.Token) {
		rsp, _ := json.Marshal(ResponseErrmsg(5))
		httprsp(rw, rsp)
		return
	}

	cloud := getRouteName(req, "cloud")
	service := getRouteName(req, "service")

	in := &pb.CloudAPICall{Cloud: cloud, Service: service, Action: v.Action, Region: v.Region, CloudId: v.CloudTokenID, CloudKey: v.CloudTokenKey}
	in.Params = v.Param
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudAPIServiceClient(cc)
	res, err := c.RequestRPC(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if res.Code == 0 {
		httprsp(rw, res.Data)
		return
	}
	rsp, _ := json.Marshal(res)
	httprsp(rw, rsp)

}
<commit_msg>Call_httpResponse_to_devide_contentType_xml_or_json<commit_after>/*

LICENSE:  MIT
Author:   sine
Email:    sinerwr@gmail.com

*/

package controller

import (
	"encoding/json"
	"github.com/getsentry/raven-go"
	"golang.org/x/net/context"
	"io/ioutil"
	"net/http"

	"github.com/SiCo-Ops/Pb"
	"github.com/SiCo-Ops/dao/grpc"
	// "github.com/SiCo-Ops/dao/mongo"
)

var (
	cloudTokenID  string
	cloudTokenKey string
	cloudRegion   string
	cloudService  string
)

type ThirdToken struct {
	PrivateToken AuthenticationToken `json:"token"`
	Cloud        string              `json:"cloud"`
	Name         string              `json:"name"`
	ID           string              `json:"id"`
	Key          string              `json:"key"`
}

type CloudAPIRequest struct {
	PrivateToken   AuthenticationToken `json:"token"`
	CloudTokenName string              `json:"name"`
	Region         string              `json:"region"`
	Action         string              `json:"action"`
	Param          map[string]string   `json:"params"`
}

type CloudAPIRawRequest struct {
	Token         string            `json:"token"`
	CloudTokenID  string            `json:"cloudid"`
	CloudTokenKey string            `json:"cloudkey"`
	Region        string            `json:"region"`
	Action        string            `json:"action"`
	Param         map[string]string `json:"params"`
}

type CloudAPIResponse struct {
	Code int64  `json:"code"`
	Msg  string `json:"msg"`
	Data string `json:"data"`
}

func CloudTokenRegistry(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
		if rcv := recover(); rcv != nil {
			raven.CaptureMessage("controller.CloudTokenRegistry", nil)
		}
	}()
	data, ok := ValidatePostData(rw, req)
	v := &ThirdToken{}
	if ok {
		json.Unmarshal(data, v)
	} else {
		return
	}
	if v.Name == "" || v.Cloud == "" || v.ID == "" {
		rsp, _ := json.Marshal(ResponseErrmsg(2))
		httprsp(rw, rsp)
		return
	}
	if config.AAAEnable && !AAAValidateToken(v.PrivateToken.ID, v.PrivateToken.Signature) {
		rsp, _ := json.Marshal(ResponseErrmsg(1))
		httprsp(rw, rsp)
		return
	}
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudTokenServiceClient(cc)
	in := &pb.CloudTokenCall{}
	in.Cloud = v.Cloud
	in.Name = v.Name
	in.Id = v.ID
	in.Key = v.Key
	in.AAATokenID = v.PrivateToken.ID
	r, err := c.TokenSet(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if r.Id != "" {
		rsp, _ := json.Marshal(&ResponseData{0, "Success"})
		httprsp(rw, rsp)
		return
	}
	rsp, _ := json.Marshal(ResponseErrmsg(2))
	httprsp(rw, rsp)
}

func CloudTokenGet(id string, cloud string, name string) (string, string) {
	in := &pb.CloudTokenCall{}
	in.AAATokenID = id
	in.Cloud = cloud
	in.Name = name
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudTokenServiceClient(cc)
	res, err := c.TokenGet(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if res.Id != "" {
		return res.Id, res.Key
	}
	return "", ""
}

func CloudServiceIsSupport(cloud string, service string) bool {
	d, err := ioutil.ReadFile("cloud.json")
	if err != nil {
		raven.CaptureError(err, nil)
		return false
	}
	var v map[string][]string
	json.Unmarshal(d, &v)
	if value, ok := v[cloud]; ok {
		for _, v := range value {
			if v == service {
				return true
			}
		}
		return false
	}
	return false
}

func CloudAPICall(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
	}()
	data, ok := ValidatePostData(rw, req)
	if !ok {
		return
	}
	v := &CloudAPIRequest{}
	json.Unmarshal(data, v)

	if !AAAValidateToken(v.PrivateToken.ID, v.PrivateToken.Signature) {
		rsp, _ := json.Marshal(ResponseErrmsg(2))
		httprsp(rw, rsp)
		return
	}

	cloud := getRouteName(req, "cloud")
	service := getRouteName(req, "service")
	action, ok := actionMap(cloud, service, v.Action)
	if !ok {
		rsp, _ := json.Marshal(ResponseErrmsg(4))
		httprsp(rw, rsp)
		return
	}

	cloudTokenID, cloudTokenKey = CloudTokenGet(v.PrivateToken.ID, cloud, v.CloudTokenName)

	in := &pb.CloudAPICall{Cloud: cloud, Service: service, Action: action, Region: v.Region, CloudId: cloudTokenID, CloudKey: cloudTokenKey}
	in.Params = v.Param
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudAPIServiceClient(cc)
	var res *pb.CloudAPIBack
	res, _ = c.RequestRPC(context.Background(), in)
	if res.Code == 0 {
		rsp := res.Data
		httprsp(rw, rsp)
		return
	}
	rsp, _ := json.Marshal(res)
	httprsp(rw, rsp)
}

func CloudAPICallRaw(rw http.ResponseWriter, req *http.Request) {
	defer func() {
		recover()
	}()
	data, ok := ValidatePostData(rw, req)
	if !ok {
		return
	}
	v := &CloudAPIRawRequest{}
	json.Unmarshal(data, v)
	if !ValidateOpenToken(v.Token) {
		rsp, _ := json.Marshal(ResponseErrmsg(5))
		httprsp(rw, rsp)
		return
	}

	cloud := getRouteName(req, "cloud")
	service := getRouteName(req, "service")

	in := &pb.CloudAPICall{Cloud: cloud, Service: service, Action: v.Action, Region: v.Region, CloudId: v.CloudTokenID, CloudKey: v.CloudTokenKey}
	in.Params = v.Param
	cc := rpc.RPCConn(RPCAddr["Li"])
	defer cc.Close()
	c := pb.NewCloudAPIServiceClient(cc)
	res, err := c.RequestRPC(context.Background(), in)
	if err != nil {
		raven.CaptureError(err, nil)
	}
	if res.Code == 0 {
		if cloud == "aws" {
			httpResponse("xml", rw, res.Data)
		} else {
			httpResponse("json", rw, res.Data)
		}
		return
	}
	rsp, _ := json.Marshal(res)
	httprsp(rw, rsp)

}
<|endoftext|>


<commit_before>package controllers

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

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/prest/prest/config"
)

// Response representation
type Response struct {
	LoggedUser interface{} `json:"user_info"`
	Token      string      `json:"token"`
}

// RavensRequest representation
type RavensRequest struct {
	Type       string   `json:"type_of"`
	Subject    string   `json:"subject"`
	Recipients []string `json:"recipients"`
	Sender     string   `json:"sender"`
	SenderName string   `json:"sender_name"`
	Content    string   `json:"content"`
}

// AuthClaims JWT
type AuthClaims struct {
	jwt.StandardClaims
}

// Token for user
func Token(u User) (t string, err error) {
	// add expiry time in configuration (in minute format, so we support the maximum need)
	expireToken := time.Now().Add(time.Hour * 6).Unix()
	claims := AuthClaims{
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireToken,
			Id:        strconv.Itoa(u.ID),
			IssuedAt:  time.Now().Unix(),
			Issuer:    strconv.Itoa(u.CustomerID),
		},
	}
	tok := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return tok.SignedString([]byte(config.PrestConf.JWTKey))
}

const unf = "user not found"

// Auth controller
func Auth(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok {
		http.Error(w, unf, http.StatusBadRequest)
		return
	}
	loggedUser, err := basicPasswordCheck(strings.ToLower(user), password)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	token, err := Token(loggedUser)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	resp := Response{
		LoggedUser: loggedUser,
		Token:      token,
	}
	err = json.NewEncoder(w).Encode(resp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// basicPasswordCheck
func basicPasswordCheck(user, password string) (obj interface{}, err error) {
	/**
	table name, fields (user and password) and encryption must be defined in
	the configuration file (toml)
	by default this endpoint will not be available, it is necessary to activate
	in the configuration file
	*/
	query := `SELECT * FROM users WHERE user=$1 AND password=$2 LIMIT 1`
	sc := config.Get.DBAdapter.Query(query, user, password)
	if sc.Err() != nil {
		err = sc.Err()
		return
	}
	n, err := sc.Scan(&obj)
	if err != nil {
		return
	}
	if n != 1 {
		err = fmt.Errorf(unf)
		return
	}
	return
}
<commit_msg>feat(controlers): implement basic authentication<commit_after>package controllers

import (
	"crypto/md5"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/prest/prest/config"
)

// Response representation
type Response struct {
	LoggedUser interface{} `json:"user_info"`
	Token      string      `json:"token"`
}

// RavensRequest representation
type RavensRequest struct {
	Type       string   `json:"type_of"`
	Subject    string   `json:"subject"`
	Recipients []string `json:"recipients"`
	Sender     string   `json:"sender"`
	SenderName string   `json:"sender_name"`
	Content    string   `json:"content"`
}

// AuthClaims JWT
type AuthClaims struct {
	jwt.StandardClaims
}

type User struct {
	ID         int
	CustomerID int
}

// Token for user
func Token(u User) (t string, err error) {
	// add expiry time in configuration (in minute format, so we support the maximum need)
	expireToken := time.Now().Add(time.Hour * 6).Unix()
	claims := AuthClaims{
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireToken,
			Id:        strconv.Itoa(u.ID),
			IssuedAt:  time.Now().Unix(),
			Issuer:    strconv.Itoa(u.CustomerID),
		},
	}
	tok := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return tok.SignedString([]byte(config.PrestConf.JWTKey))
}

const unf = "user not found"

// Auth controller
func Auth(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok {
		http.Error(w, unf, http.StatusBadRequest)
		return
	}
	loggedUser, err := basicPasswordCheck(strings.ToLower(user), password)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	token, err := Token(loggedUser)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	resp := Response{
		LoggedUser: loggedUser,
		Token:      token,
	}
	err = json.NewEncoder(w).Encode(resp)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// basicPasswordCheck
func basicPasswordCheck(user, password string) (obj User, err error) {
	/**
	table name, fields (user and password) and encryption must be defined in
	the configuration file (toml)
	by default this endpoint will not be available, it is necessary to activate
	in the configuration file
	*/
	sc := config.PrestConf.Adapter.Query(getSelectQuery(), user, encrypt(password))
	if sc.Err() != nil {
		err = sc.Err()
		return
	}
	n, err := sc.Scan(&obj)
	if err != nil {
		return
	}
	if n != 1 {
		err = fmt.Errorf(unf)
	}

	return
}

// getSelectQuery create the query to authenticate the user
func getSelectQuery() (query string) {
	query = fmt.Sprintf(`SELECT * FROM %s WHERE %s=$1 AND %s=$2 LIMIT 1`, config.PrestConf.AuthTable, config.PrestConf.AuthUsername, config.PrestConf.AuthPassword)

	return
}

// encrypt will apply the encryption algorithm to the password
func encrypt(password string) (encrypted string) {
	switch config.PrestConf.AuthEncrypt {
	case "MD5":
		encrypted = fmt.Sprintf("%x", md5.Sum([]byte(password)))
		break

	case "SHA1":
		encrypted = fmt.Sprintf("%x", sha1.Sum([]byte(password)))
		break

	}
	return
}
<|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	"net/http"
	"text/template"
	"encoding/json"
	"bytes"
	"mime/multipart"
	"sync"
	"path/filepath"
)

var indexTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/index.html", "views/footer.html"))

func IndexHandler(w http.ResponseWriter, r *http.Request) {
	err := indexTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var liveTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/live.html", "views/footer.html"))

func LiveHandler(w http.ResponseWriter, r *http.Request) {
	err := liveTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var historyTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/history.html", "views/footer.html"))

func HistoryHandler(w http.ResponseWriter, r *http.Request) {
	err := historyTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var uploadTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/upload.html", "views/footer.html"))

func UploadHandler(w http.ResponseWriter, r *http.Request) {
	err := uploadTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

type FileInfo struct {
	Filename 		string
	Size 				int64
	ContentType string
	Contents 		string
}

type PostResponse struct {
	StatusCode 	int
	Filename 	 	string
}

func sendFile(fh *multipart.FileHeader, c chan PostResponse, wg *sync.WaitGroup) {

	defer wg.Done()
	f, err := fh.Open()
  if err != nil {
		fmt.Println(err)
	}

	var buf bytes.Buffer
	fileSize, err := buf.ReadFrom(f)
	if err != nil {
		fmt.Println(err)
	}

	// url := "http://localhost:8080/api/upload"
	url := "https://luft-184208.appspot.com/api/upload"

	fi := FileInfo {

		Filename: filepath.Base(fh.Filename),
		Size: fileSize,
		ContentType: fh.Header["Content-Type"][0],
		Contents: buf.String(),
	}

	file, err := json.Marshal(fi)
	if err != nil {
		fmt.Println(err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(file))
  req.Header.Set("X-Custom-Header", "myvalue")
  req.Header.Set("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    panic(err)
  }

	response := PostResponse{
		StatusCode: resp.StatusCode,
		Filename: fh.Filename,
	}

	c <- response
}

func PostFileHandler(w http.ResponseWriter, r *http.Request) {

	if r.Method == "POST" {
		c := make(chan PostResponse, 10)
		var wg sync.WaitGroup
		var succResponses []string
		var failResponses []string

		r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile
		fhs := r.MultipartForm.File["uploadFile"]

		for _, fh := range fhs {
			wg.Add(1)
			go sendFile(fh, c, &wg)
		}

		wg.Wait()
		for i := 0; i < len(fhs); i++ {
			response := <- c
			if (response.StatusCode == 200) {
				succResponses = append(succResponses, response.Filename)
			} else {
				failResponses = append(failResponses, response.Filename)
			}
		}
		close(c)

		if (len(failResponses) == 0) {
			fmt.Fprintf(w, "Opplasting vellykket!")
			return
		}	else {
			fmt.Fprintf(w, "Følgene filer ble ikke lastet opp: ")
			return
		}
 	}
}
<commit_msg>Remove filepath approach to anonymizing filenames<commit_after>package controllers

import (
	"fmt"
	"net/http"
	"text/template"
	"encoding/json"
	"bytes"
	"mime/multipart"
	"sync"
)

var indexTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/index.html", "views/footer.html"))

func IndexHandler(w http.ResponseWriter, r *http.Request) {
	err := indexTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var liveTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/live.html", "views/footer.html"))

func LiveHandler(w http.ResponseWriter, r *http.Request) {
	err := liveTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var historyTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/history.html", "views/footer.html"))

func HistoryHandler(w http.ResponseWriter, r *http.Request) {
	err := historyTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

var uploadTemplate = template.Must(template.ParseFiles("views/base.html",
	"views/header.html", "views/navbar.html",
	"views/upload.html", "views/footer.html"))

func UploadHandler(w http.ResponseWriter, r *http.Request) {
	err := uploadTemplate.Execute(w, nil)
	if err != nil {
		fmt.Println(err)
	}
}

type FileInfo struct {
	Filename 		string
	Size 				int64
	ContentType string
	Contents 		string
}

type PostResponse struct {
	StatusCode 	int
	Filename 	 	string
}

func sendFile(fh *multipart.FileHeader, c chan PostResponse, wg *sync.WaitGroup) {

	defer wg.Done()
	f, err := fh.Open()
  if err != nil {
		fmt.Println(err)
	}

	var buf bytes.Buffer
	fileSize, err := buf.ReadFrom(f)
	if err != nil {
		fmt.Println(err)
	}

	// url := "http://localhost:8080/api/upload"
	url := "https://luft-184208.appspot.com/api/upload"

	fi := FileInfo {

		Filename: fh.Filename,
		Size: fileSize,
		ContentType: fh.Header["Content-Type"][0],
		Contents: buf.String(),
	}

	file, err := json.Marshal(fi)
	if err != nil {
		fmt.Println(err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(file))
  req.Header.Set("X-Custom-Header", "myvalue")
  req.Header.Set("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    panic(err)
  }

	response := PostResponse{
		StatusCode: resp.StatusCode,
		Filename: fh.Filename,
	}

	c <- response
}

func PostFileHandler(w http.ResponseWriter, r *http.Request) {

	if r.Method == "POST" {
		c := make(chan PostResponse, 10)
		var wg sync.WaitGroup
		var succResponses []string
		var failResponses []string

		r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile
		fhs := r.MultipartForm.File["uploadFile"]

		for _, fh := range fhs {
			wg.Add(1)
			go sendFile(fh, c, &wg)
		}

		wg.Wait()
		for i := 0; i < len(fhs); i++ {
			response := <- c
			if (response.StatusCode == 200) {
				succResponses = append(succResponses, response.Filename)
			} else {
				failResponses = append(failResponses, response.Filename)
			}
		}
		close(c)

		if (len(failResponses) == 0) {
			fmt.Fprintf(w, "Opplasting vellykket!")
			return
		}	else {
			fmt.Fprintf(w, "Følgene filer ble ikke lastet opp: ")
			return
		}
 	}
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"

	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/github.com/gin-gonic/gin"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/github.com/shwoodard/jsonapi"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/gopkg.in/mgo.v2"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/gopkg.in/mgo.v2/bson"
	"github.com/pasangsherpa/memenshare/models"
)

type (
	MemeController struct {
		collection *mgo.Collection
	}
)

// NewMemeController provides a reference to a MemeController
// with provided mongo collection
func NewMemeController(c *mgo.Collection) *MemeController {
	return &MemeController{c}
}

func (mc MemeController) GetMemes(c *gin.Context) {
	// stub meme collection
	// models := make([]interface{}, 0)
	var models []models.Meme

	// fetch meme collection
	if err := mc.collection.Find(nil).All(&models); err != nil {
		c.JSON(http.StatusNotFound, err)
		return
	}

	// fmt.Printf("Models %+v\n", models)

	c.Writer.Header().Set("Content-Type", "application/vnd.api+json")
	if err := jsonapi.MarshalManyPayload(c.Writer, models); err != nil {
		c.JSON(http.StatusInternalServerError, err)
		return
	}

	// c.JSON(http.StatusOK, models)
}

func (mc MemeController) GetMeme(c *gin.Context) {
	// grab id from url param
	id := c.Params.ByName("id")

	// verify id is ObjectId, otherwise bail
	if !bson.IsObjectIdHex(id) {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    "INVALID_ID",
			"message": "Invalid id",
		})
		return
	}

	// stub meme
	model := new(models.Meme)

	// fetch meme
	if err := mc.collection.FindId(bson.ObjectIdHex(id)).One(&model); err != nil {
		c.JSON(http.StatusNotFound, err)
		return
	}

	// set primary id value to use bson id
	model.Id = model.Bid.Hex()

	c.Writer.Header().Set("Content-Type", "application/vnd.api+json")
	if err := jsonapi.MarshalOnePayload(c.Writer, model); err != nil {
		c.JSON(http.StatusInternalServerError, err)
	}
}
<commit_msg>remove jsonapi marshal<commit_after>package controllers

import (
	"net/http"

	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/github.com/gin-gonic/gin"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/github.com/shwoodard/jsonapi"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/gopkg.in/mgo.v2"
	"github.com/pasangsherpa/memenshare/Godeps/_workspace/src/gopkg.in/mgo.v2/bson"
	"github.com/pasangsherpa/memenshare/models"
)

type (
	MemeController struct {
		collection *mgo.Collection
	}
)

// NewMemeController provides a reference to a MemeController
// with provided mongo collection
func NewMemeController(c *mgo.Collection) *MemeController {
	return &MemeController{c}
}

func (mc MemeController) GetMemes(c *gin.Context) {
	// stub meme collection
	// models := make([]interface{}, 0)
	var models []models.Meme

	// fetch meme collection
	if err := mc.collection.Find(nil).All(&models); err != nil {
		c.JSON(http.StatusNotFound, err)
		return
	}

	// fmt.Printf("Models %+v\n", models)

	c.Writer.Header().Set("Content-Type", "application/vnd.api+json")
	// if err := jsonapi.MarshalManyPayload(c.Writer, models); err != nil {
	// 	c.JSON(http.StatusInternalServerError, err)
	// 	return
	// }

	c.JSON(http.StatusOK, models)
}

func (mc MemeController) GetMeme(c *gin.Context) {
	// grab id from url param
	id := c.Params.ByName("id")

	// verify id is ObjectId, otherwise bail
	if !bson.IsObjectIdHex(id) {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    "INVALID_ID",
			"message": "Invalid id",
		})
		return
	}

	// stub meme
	model := new(models.Meme)

	// fetch meme
	if err := mc.collection.FindId(bson.ObjectIdHex(id)).One(&model); err != nil {
		c.JSON(http.StatusNotFound, err)
		return
	}

	// set primary id value to use bson id
	model.Id = model.Bid.Hex()

	c.Writer.Header().Set("Content-Type", "application/vnd.api+json")
	if err := jsonapi.MarshalOnePayload(c.Writer, model); err != nil {
		c.JSON(http.StatusInternalServerError, err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

func checkErr(e error) {
	if e != nil {
		fmt.Println("Error: ", e)
		os.Exit(1)
	}
}

// Removes non-directory elements of any []os.FileInfo
func onlyDirectories(inLs []os.FileInfo) (outLs []os.FileInfo) {
	for _, fd := range inLs {
		if fd.IsDir() {
			outLs = append(outLs, fd)
		}
	}
	return
}

// Extend "records" matrix to have rows until time "desiredTime"
// Return: Extended version of record
func extendRecordsToTime(records [][]string, desiredTime int, recordCols int) [][]string {
	lenr := len(records)
	// records[1] stores cycle [1], as records[0] is column names
	for j := lenr; j < desiredTime+1; j++ {
		records = append(records, make([]string, recordCols))
		records[j][0] = strconv.Itoa(j)
	}
	return records
}

// Handles the CSV Reader for a single trial, and updates records[][] accordingly. Returns the updated records
func handleTrialCSV(trialReader *csv.Reader, records [][]string, colName string, totalCols int, trialNum int) [][]string {
	// Read whole CSV to an array
	trialRecords, err := trialReader.ReadAll()
	checkErr(err)
	// Add the name of this new column to records[0]
	records[0] = append(records[0], colName)

	finalTime, err := strconv.Atoi(trialRecords[len(trialRecords)-1][0])
	checkErr(err)
	//If this test went longer than all of the others, so far
	if len(records) < finalTime+1 {
		records = extendRecordsToTime(records, finalTime, totalCols)
	}
	for _, row := range trialRecords {
		// row[0] is time, on the x-axis; row[1] is value, on the y-axis
		time, err := strconv.Atoi(row[0])
		checkErr(err)
		records[time][trialNum+1] = row[1]
	}
	return records
}

func handleFEngine(fengine os.FileInfo, bmarkPath string, finalReportFName string) [][]string {
	// Create matrix, to eventually become a CSV
	records := [][]string{{"time"}}

	// Enter sub-directories
	fenginePath := path.Join(bmarkPath, fengine.Name())
	ls, err := ioutil.ReadDir(fenginePath)
	checkErr(err)
	trials := onlyDirectories(ls)

	totalCols := len(trials) + 1
	for j, trial := range trials {
		// Create fds
		trialCSV, err := os.Open(path.Join(fenginePath, trial.Name(), finalReportFName))
		checkErr(err)
		trialReader := csv.NewReader(trialCSV)

		records = handleTrialCSV(trialReader, records, fengine.Name()+"-"+trial.Name(), totalCols, j)
		trialCSV.Close()
	}

	fengineCSV, err := os.Create(path.Join(fenginePath, finalReportFName))
	checkErr(err)
	fengineWriter := csv.NewWriter(fengineCSV)
	fengineWriter.WriteAll(records)
	fengineCSV.Close()
	return records
}

func appendAllTrials(aggregateRecords [][]string, records [][]string) [][]string {
	if len(aggregateRecords) < len(records) {
		aggregateRecords = extendRecordsToTime(aggregateRecords, len(records)-1, len(aggregateRecords[0]))
	}
	for r, row := range records {
		aggregateRecords[r] = append(aggregateRecords[r], row[1:]...)
	}
	return aggregateRecords
}

// Identify the fastest trial column in records and add it to aggregateRecords
func appendFastestTrial(aggregateRecords [][]string, records [][]string) [][]string {
	// Initialized to false: track whether this trial has lasted a long time
	trials := make([]bool, len(records[0]))
	// Use int for faster comparisons
	finishedTrials := len(trials) - 1
	// Rows in Fastest Trial
	var rowsInFT int
	var fastestTrial int

	// Find the fastest trial by working backwards, since data points are sometimes dropped
	for r := len(records) - 1; r > 0; r-- {
		for c := 1; c < len(records[r]); c++ {
			if !trials[c] && (len(records[r][c]) > 0) {
				trials[c] = true
				finishedTrials--
				if finishedTrials == 0 {
					fastestTrial = c
					rowsInFT = r
					break
				}
			}
		}
		if finishedTrials == 0 {
			break
		}
	}

	// Update aggregateRecords
	if len(aggregateRecords) < rowsInFT+1 {
		aggregateRecords = extendRecordsToTime(aggregateRecords, rowsInFT, len(aggregateRecords[0]))
	}
	for j := 0; j <= rowsInFT; j++ {
		aggregateRecords[j] = append(aggregateRecords[j], records[j][fastestTrial])
	}
	return aggregateRecords
}

// Call handleFEngine() for each fengine, then compose all fengine data into a single CSV for comparison
func handleBmark(bmark os.FileInfo, recordsPath string, finalReportFName string) {
	bmarkRecords := [][]string{{"time"}}
	bmarkPath := path.Join(recordsPath, bmark.Name())
	ls, err := ioutil.ReadDir(bmarkPath)
	checkErr(err)
	fengines := onlyDirectories(ls)

	for _, fengine := range fengines {
		fengineRecords := handleFEngine(fengine, bmarkPath, finalReportFName)
		//bmarkRecords = appendFastestTrial(bmarkRecords, fengineRecords)
		bmarkRecords = appendAllTrials(bmarkRecords, fengineRecords)
	}
	bmCSV, err := os.Create(path.Join(bmarkPath, finalReportFName))
	checkErr(err)
	bmWriter := csv.NewWriter(bmCSV)
	bmWriter.WriteAll(bmarkRecords)
	bmCSV.Close()
}

// Enters all report subdirectories, from benchmark to fengine to trial;
// composes individual CSVs (only two columns) into larger CSVs
func composeAllNamed(finalReportFName string) {
	reportsPath := "./reports"
	bmarks, err := ioutil.ReadDir(reportsPath)
	checkErr(err)
	for _, bmark := range bmarks {
		handleBmark(bmark, reportsPath, finalReportFName)
	}
}

func main() {
	composeAllNamed("coverage-graph.csv")
	composeAllNamed("corpus-size-graph.csv")
	composeAllNamed("corpus-elems-graph.csv")
	// createIFramesFor("setOfFrames.html")
	//
}
<commit_msg>Ensure tables have same number of rows before merging.<commit_after>package main

import (
	"encoding/csv"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strconv"
)

func checkErr(e error) {
	if e != nil {
		fmt.Println("Error: ", e)
		os.Exit(1)
	}
}

// Removes non-directory elements of any []os.FileInfo
func onlyDirectories(inLs []os.FileInfo) (outLs []os.FileInfo) {
	for _, fd := range inLs {
		if fd.IsDir() {
			outLs = append(outLs, fd)
		}
	}
	return
}

// Extend "records" matrix to have rows until time "desiredTime"
// Return: Extended version of record
func extendRecordsToTime(records [][]string, desiredTime int, recordCols int) [][]string {
	lenr := len(records)
	// records[1] stores cycle [1], as records[0] is column names
	for j := lenr; j < desiredTime+1; j++ {
		records = append(records, make([]string, recordCols))
		records[j][0] = strconv.Itoa(j)
	}
	return records
}

// Handles the CSV Reader for a single trial, and updates records[][] accordingly. Returns the updated records
func handleTrialCSV(trialReader *csv.Reader, records [][]string, colName string, totalCols int, trialNum int) [][]string {
	// Read whole CSV to an array
	trialRecords, err := trialReader.ReadAll()
	checkErr(err)
	// Add the name of this new column to records[0]
	records[0] = append(records[0], colName)

	finalTime, err := strconv.Atoi(trialRecords[len(trialRecords)-1][0])
	checkErr(err)
	//If this test went longer than all of the others, so far
	if len(records) < finalTime+1 {
		records = extendRecordsToTime(records, finalTime, totalCols)
	}
	for _, row := range trialRecords {
		// row[0] is time, on the x-axis; row[1] is value, on the y-axis
		time, err := strconv.Atoi(row[0])
		checkErr(err)
		records[time][trialNum+1] = row[1]
	}
	return records
}

func handleFEngine(fengine os.FileInfo, bmarkPath string, finalReportFName string) [][]string {
	// Create matrix, to eventually become a CSV
	records := [][]string{{"time"}}

	// Enter sub-directories
	fenginePath := path.Join(bmarkPath, fengine.Name())
	ls, err := ioutil.ReadDir(fenginePath)
	checkErr(err)
	trials := onlyDirectories(ls)

	totalCols := len(trials) + 1
	for j, trial := range trials {
		// Create fds
		trialCSV, err := os.Open(path.Join(fenginePath, trial.Name(), finalReportFName))
		checkErr(err)
		trialReader := csv.NewReader(trialCSV)

		records = handleTrialCSV(trialReader, records, fengine.Name()+"-"+trial.Name(), totalCols, j)
		trialCSV.Close()
	}

	fengineCSV, err := os.Create(path.Join(fenginePath, finalReportFName))
	checkErr(err)
	fengineWriter := csv.NewWriter(fengineCSV)
	fengineWriter.WriteAll(records)
	fengineCSV.Close()
	return records
}

func appendAllTrials(aggregateRecords [][]string, records [][]string) [][]string {
	records = extendRecordsToTime(records, len(aggregateRecords)-1, len(records[0]))
	aggregateRecords = extendRecordsToTime(aggregateRecords, len(records)-1, len(aggregateRecords[0]))
	for r, row := range records {
		aggregateRecords[r] = append(aggregateRecords[r], row[1:]...)
	}
	return aggregateRecords
}

// Identify the fastest trial column in records and add it to aggregateRecords
func appendFastestTrial(aggregateRecords [][]string, records [][]string) [][]string {
	// Initialized to false: track whether this trial has lasted a long time
	trials := make([]bool, len(records[0]))
	// Use int for faster comparisons
	finishedTrials := len(trials) - 1
	// Rows in Fastest Trial
	var rowsInFT int
	var fastestTrial int

	// Find the fastest trial by working backwards, since data points are sometimes dropped
	for r := len(records) - 1; r > 0; r-- {
		for c := 1; c < len(records[r]); c++ {
			if !trials[c] && (len(records[r][c]) > 0) {
				trials[c] = true
				finishedTrials--
				if finishedTrials == 0 {
					fastestTrial = c
					rowsInFT = r
					break
				}
			}
		}
		if finishedTrials == 0 {
			break
		}
	}

	// Update aggregateRecords
	if len(aggregateRecords) < rowsInFT+1 {
		aggregateRecords = extendRecordsToTime(aggregateRecords, rowsInFT, len(aggregateRecords[0]))
	}
	for j := 0; j <= rowsInFT; j++ {
		aggregateRecords[j] = append(aggregateRecords[j], records[j][fastestTrial])
	}
	return aggregateRecords
}

// Call handleFEngine() for each fengine, then compose all fengine data into a single CSV for comparison
func handleBmark(bmark os.FileInfo, recordsPath string, finalReportFName string) {
	bmarkRecords := [][]string{{"time"}}
	bmarkPath := path.Join(recordsPath, bmark.Name())
	ls, err := ioutil.ReadDir(bmarkPath)
	checkErr(err)
	fengines := onlyDirectories(ls)

	for _, fengine := range fengines {
		fengineRecords := handleFEngine(fengine, bmarkPath, finalReportFName)
		//bmarkRecords = appendFastestTrial(bmarkRecords, fengineRecords)
		bmarkRecords = appendAllTrials(bmarkRecords, fengineRecords)
	}
	bmCSV, err := os.Create(path.Join(bmarkPath, finalReportFName))
	checkErr(err)
	bmWriter := csv.NewWriter(bmCSV)
	bmWriter.WriteAll(bmarkRecords)
	bmCSV.Close()
}

// Enters all report subdirectories, from benchmark to fengine to trial;
// composes individual CSVs (only two columns) into larger CSVs
func composeAllNamed(finalReportFName string) {
	reportsPath := "./reports"
	bmarks, err := ioutil.ReadDir(reportsPath)
	checkErr(err)
	for _, bmark := range bmarks {
		handleBmark(bmark, reportsPath, finalReportFName)
	}
}

func main() {
	composeAllNamed("coverage-graph.csv")
	composeAllNamed("corpus-size-graph.csv")
	composeAllNamed("corpus-elems-graph.csv")
	// createIFramesFor("setOfFrames.html")
	//
}
<|endoftext|>


<commit_before>package controllers

import (
	"regexp"
)

func IsEmail(email string) bool {
	const email_regex = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
	if m, _ := regexp.MatchString(email_regex, email); !m {
		return false
	}

	return true
}
<commit_msg>Moved the generateSlug function into controllers/util.go file<commit_after>package controllers

import (
	"regexp"
	"strings"
)

func IsEmail(email string) bool {
	const email_regex = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
	if m, _ := regexp.MatchString(email_regex, email); !m {
		return false
	}

	return true
}

func generateSlug(title string) string {
	re := regexp.MustCompile("[^a-z0-9]+")
	return strings.Trim(re.ReplaceAllString(strings.ToLower(title), "-"), "-")
}
<|endoftext|>


<commit_before>package smtp

// http://www.rfc-editor.org/rfc/rfc5321.txt

import (
	"crypto/tls"
	"io"
	"log"
	"net"
	"strings"

	"github.com/mailhog/MailHog-MTA/backend"
	"github.com/mailhog/data"
	"github.com/mailhog/smtp"
)

// Session represents a SMTP session using net.TCPConn
type Session struct {
	server *Server

	conn          io.ReadWriteCloser
	proto         *smtp.Protocol
	remoteAddress string
	isTLS         bool
	line          string
	identity      *backend.Identity
}

// Accept starts a new SMTP session using io.ReadWriteCloser
func (s *Server) Accept(remoteAddress string, conn io.ReadWriteCloser) {
	proto := smtp.NewProtocol()
	proto.Hostname = s.Hostname

	session := &Session{
		server:        s,
		conn:          conn,
		proto:         proto,
		remoteAddress: remoteAddress,
		isTLS:         false,
		line:          "",
		identity:      nil,
	}

	// FIXME this all feels nasty
	proto.LogHandler = session.logf
	proto.MessageReceivedHandler = session.acceptMessage
	proto.ValidateSenderHandler = session.validateSender
	proto.ValidateRecipientHandler = session.validateRecipient
	proto.ValidateAuthenticationHandler = session.validateAuthentication
	if session.server != nil && session.server.AuthBackend != nil {
		proto.GetAuthenticationMechanismsHandler = session.server.AuthBackend.Mechanisms
	}
	proto.SMTPVerbFilter = session.verbFilter
	proto.MaximumRecipients = session.server.PolicySet.MaximumRecipients
	proto.MaximumLineLength = session.server.PolicySet.MaximumLineLength

	if session.server.PolicySet.EnableTLS {
		proto.TLSHandler = session.tlsHandler
		proto.RequireTLS = session.server.PolicySet.RequireTLS
	}

	session.logf("Starting session")
	session.Write(proto.Start())
	for session.Read() == true {
	}
	session.logf("Session ended")
}

func (c *Session) validateAuthentication(mechanism string, args ...string) (errorReply *smtp.Reply, ok bool) {
	if c.server.AuthBackend == nil {
		return smtp.ReplyInvalidAuth(), false
	}
	i, e, ok := c.server.AuthBackend.Authenticate(mechanism, args...)
	if e != nil || !ok {
		return smtp.ReplyInvalidAuth(), false
	}
	c.identity = i
	return nil, true
}

func (c *Session) validateRecipient(to string) bool {
	if c.server.DeliveryBackend == nil {
		return false
	}
	maxRecipients := c.server.DeliveryBackend.MaxRecipients(c.identity)
	if maxRecipients > -1 && len(c.proto.Message.To) > maxRecipients {
		return false
	}
	if c.server.PolicySet.RequireLocalDelivery {
		r := c.server.ResolverBackend.Resolve(to)
		if r != backend.ResolvedPrimaryLocal && r != backend.ResolvedSecondaryLocal {
			return false
		}
	}
	return c.server.DeliveryBackend.WillDeliver(to, c.proto.Message.From, c.identity)
}

func (c *Session) validateSender(from string) bool {
	// FIXME better policy for this?
	if c.server.PolicySet.RequireAuthentication {
		if c.identity == nil {
			return false
		}
		return (*c.identity).IsValidSender(from)
	}
	return true
}

func (c *Session) verbFilter(verb string, args ...string) (errorReply *smtp.Reply) {
	// FIXME consider moving this to smtp proto? since STARTTLS is there anyway...
	if c.server.PolicySet.RequireAuthentication && c.proto.State == smtp.MAIL && c.identity == nil {
		verb = strings.ToUpper(verb)
		if verb == "RSET" || verb == "QUIT" || verb == "NOOP" ||
			verb == "EHLO" || verb == "HELO" || verb == "AUTH" {
			return nil
		}
		// FIXME more appropriate error
		return smtp.ReplyUnrecognisedCommand()
	}
	return nil
}

// tlsHandler handles the STARTTLS command
func (c *Session) tlsHandler(done func(ok bool)) (errorReply *smtp.Reply, callback func(), ok bool) {
	return nil, func() {
		c.logf("Upgrading session to TLS")
		c.conn = tls.Server(c.conn.(net.Conn), c.server.getTLSConfig())
		c.isTLS = true
		c.logf("Session upgrade complete")
		done(true)
	}, true
}

func (c *Session) acceptMessage(msg *data.Message) (id string, err error) {
	c.logf("Storing message %s", msg.ID)
	return c.server.DeliveryBackend.Deliver(msg)
}

func (c *Session) logf(message string, args ...interface{}) {
	message = strings.Join([]string{"[SMTP %s]", message}, " ")
	args = append([]interface{}{c.remoteAddress}, args...)
	log.Printf(message, args...)
}

// Read reads from the underlying io.Reader
func (c *Session) Read() bool {
	buf := make([]byte, 1024)
	n, err := io.Reader(c.conn).Read(buf)

	if n == 0 {
		c.logf("Connection closed by remote host\n")
		io.Closer(c.conn).Close() // not sure this is necessary?
		return false
	}

	if err != nil {
		c.logf("Error reading from socket: %s\n", err)
		return false
	}

	text := string(buf[0:n])
	logText := strings.Replace(text, "\n", "\\n", -1)
	logText = strings.Replace(logText, "\r", "\\r", -1)
	c.logf("Received %d bytes: '%s'\n", n, logText)

	c.line += text

	for strings.Contains(c.line, "\r\n") {
		line, reply := c.proto.Parse(c.line)
		c.line = line

		if reply != nil {
			c.Write(reply)
			if reply.Status == 221 {
				io.Closer(c.conn).Close()
				return false
			}
		}
	}

	return true
}

// Write writes a reply to the underlying io.Writer
func (c *Session) Write(reply *smtp.Reply) {
	lines := reply.Lines()
	for _, l := range lines {
		logText := strings.Replace(l, "\n", "\\n", -1)
		logText = strings.Replace(logText, "\r", "\\r", -1)
		c.logf("Sent %d bytes: '%s'", len(l), logText)
		io.Writer(c.conn).Write([]byte(l))
	}
	if reply.Done != nil {
		reply.Done()
	}
}
<commit_msg>Prevent excessively long lines before it reaches proto<commit_after>package smtp

// http://www.rfc-editor.org/rfc/rfc5321.txt

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net"
	"strings"

	"github.com/mailhog/MailHog-MTA/backend"
	"github.com/mailhog/data"
	"github.com/mailhog/smtp"
)

// Session represents a SMTP session using net.TCPConn
type Session struct {
	server *Server

	conn          io.ReadWriteCloser
	proto         *smtp.Protocol
	remoteAddress string
	isTLS         bool
	line          string
	identity      *backend.Identity

	maximumBufferLength int
}

// Accept starts a new SMTP session using io.ReadWriteCloser
func (s *Server) Accept(remoteAddress string, conn io.ReadWriteCloser) {
	proto := smtp.NewProtocol()
	proto.Hostname = s.Hostname

	session := &Session{
		server:              s,
		conn:                conn,
		proto:               proto,
		remoteAddress:       remoteAddress,
		isTLS:               false,
		line:                "",
		identity:            nil,
		maximumBufferLength: 2048000,
	}

	// FIXME this all feels nasty
	proto.LogHandler = session.logf
	proto.MessageReceivedHandler = session.acceptMessage
	proto.ValidateSenderHandler = session.validateSender
	proto.ValidateRecipientHandler = session.validateRecipient
	proto.ValidateAuthenticationHandler = session.validateAuthentication
	if session.server != nil && session.server.AuthBackend != nil {
		proto.GetAuthenticationMechanismsHandler = session.server.AuthBackend.Mechanisms
	}
	proto.SMTPVerbFilter = session.verbFilter
	proto.MaximumRecipients = session.server.PolicySet.MaximumRecipients
	proto.MaximumLineLength = session.server.PolicySet.MaximumLineLength

	if session.server.PolicySet.EnableTLS {
		proto.TLSHandler = session.tlsHandler
		proto.RequireTLS = session.server.PolicySet.RequireTLS
	}

	session.logf("Starting session")
	session.Write(proto.Start())
	for session.Read() == true {
	}
	session.logf("Session ended")
}

func (c *Session) validateAuthentication(mechanism string, args ...string) (errorReply *smtp.Reply, ok bool) {
	if c.server.AuthBackend == nil {
		return smtp.ReplyInvalidAuth(), false
	}
	i, e, ok := c.server.AuthBackend.Authenticate(mechanism, args...)
	if e != nil || !ok {
		return smtp.ReplyInvalidAuth(), false
	}
	c.identity = i
	return nil, true
}

func (c *Session) validateRecipient(to string) bool {
	if c.server.DeliveryBackend == nil {
		return false
	}
	maxRecipients := c.server.DeliveryBackend.MaxRecipients(c.identity)
	if maxRecipients > -1 && len(c.proto.Message.To) > maxRecipients {
		return false
	}
	if c.server.PolicySet.RequireLocalDelivery {
		r := c.server.ResolverBackend.Resolve(to)
		if r != backend.ResolvedPrimaryLocal && r != backend.ResolvedSecondaryLocal {
			return false
		}
	}
	return c.server.DeliveryBackend.WillDeliver(to, c.proto.Message.From, c.identity)
}

func (c *Session) validateSender(from string) bool {
	// FIXME better policy for this?
	if c.server.PolicySet.RequireAuthentication {
		if c.identity == nil {
			return false
		}
		return (*c.identity).IsValidSender(from)
	}
	return true
}

func (c *Session) verbFilter(verb string, args ...string) (errorReply *smtp.Reply) {
	// FIXME consider moving this to smtp proto? since STARTTLS is there anyway...
	if c.server.PolicySet.RequireAuthentication && c.proto.State == smtp.MAIL && c.identity == nil {
		verb = strings.ToUpper(verb)
		if verb == "RSET" || verb == "QUIT" || verb == "NOOP" ||
			verb == "EHLO" || verb == "HELO" || verb == "AUTH" {
			return nil
		}
		// FIXME more appropriate error
		return smtp.ReplyUnrecognisedCommand()
	}
	return nil
}

// tlsHandler handles the STARTTLS command
func (c *Session) tlsHandler(done func(ok bool)) (errorReply *smtp.Reply, callback func(), ok bool) {
	return nil, func() {
		c.logf("Upgrading session to TLS")
		c.conn = tls.Server(c.conn.(net.Conn), c.server.getTLSConfig())
		c.isTLS = true
		c.logf("Session upgrade complete")
		done(true)
	}, true
}

func (c *Session) acceptMessage(msg *data.Message) (id string, err error) {
	c.logf("Storing message %s", msg.ID)
	return c.server.DeliveryBackend.Deliver(msg)
}

func (c *Session) logf(message string, args ...interface{}) {
	message = strings.Join([]string{"[SMTP %s]", message}, " ")
	args = append([]interface{}{c.remoteAddress}, args...)
	log.Printf(message, args...)
}

// Read reads from the underlying io.Reader
func (c *Session) Read() bool {
	buf := make([]byte, 1024)
	n, err := io.Reader(c.conn).Read(buf)

	if n == 0 {
		c.logf("Connection closed by remote host\n")
		io.Closer(c.conn).Close() // not sure this is necessary?
		return false
	}

	if err != nil {
		c.logf("Error reading from socket: %s\n", err)
		return false
	}

	text := string(buf[0:n])
	logText := strings.Replace(text, "\n", "\\n", -1)
	logText = strings.Replace(logText, "\r", "\\r", -1)
	c.logf("Received %d bytes: '%s'\n", n, logText)

	if c.maximumBufferLength > -1 && len(c.line+text) > c.maximumBufferLength {
		// FIXME what is the "expected" behaviour for this?
		c.Write(smtp.ReplyError(fmt.Errorf("Maximum buffer length exceeded")))
		io.Closer(c.conn).Close()
		return false
	}

	c.line += text

	for strings.Contains(c.line, "\r\n") {
		line, reply := c.proto.Parse(c.line)
		c.line = line

		if reply != nil {
			c.Write(reply)
			if reply.Status == 221 {
				io.Closer(c.conn).Close()
				return false
			}
		}
	}

	return true
}

// Write writes a reply to the underlying io.Writer
func (c *Session) Write(reply *smtp.Reply) {
	lines := reply.Lines()
	for _, l := range lines {
		logText := strings.Replace(l, "\n", "\\n", -1)
		logText = strings.Replace(logText, "\r", "\\r", -1)
		c.logf("Sent %d bytes: '%s'", len(l), logText)
		io.Writer(c.conn).Write([]byte(l))
	}
	if reply.Done != nil {
		reply.Done()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/datasource/configdrive"
	"github.com/coreos/coreos-cloudinit/datasource/file"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/digitalocean"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/ec2"
	"github.com/coreos/coreos-cloudinit/datasource/proc_cmdline"
	"github.com/coreos/coreos-cloudinit/datasource/url"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.10.0+git"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	flags = struct {
		printVersion  bool
		ignoreFailure bool
		sources       struct {
			file                        string
			configDrive                 string
			metadataService             bool
			ec2MetadataService          string
			cloudSigmaMetadataService   bool
			digitalOceanMetadataService string
			url                         string
			procCmdLine                 bool
		}
		convertNetconf string
		workspace      string
		sshKeyName     string
		oem            string
	}{}
)

func init() {
	flag.BoolVar(&flags.printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&flags.ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&flags.sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&flags.sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&flags.sources.metadataService, "from-metadata-service", false, "[DEPRECATED - Use -from-ec2-metadata] Download data from metadata service")
	flag.StringVar(&flags.sources.ec2MetadataService, "from-ec2-metadata", "", "Download EC2 data from the provided url")
	flag.BoolVar(&flags.sources.cloudSigmaMetadataService, "from-cloudsigma-metadata", false, "Download data from CloudSigma server context")
	flag.StringVar(&flags.sources.digitalOceanMetadataService, "from-digitalocean-metadata", "", "Download DigitalOcean data from the provided url")
	flag.StringVar(&flags.sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&flags.sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", proc_cmdline.ProcCmdlineLocation, proc_cmdline.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&flags.oem, "oem", "", "Use the settings specific to the provided OEM")
	flag.StringVar(&flags.convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files")
	flag.StringVar(&flags.workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&flags.sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

type oemConfig map[string]string

var (
	oemConfigs = map[string]oemConfig{
		"digitalocean": oemConfig{
			"from-digitalocean-metadata": "http://169.254.169.254/",
			"convert-netconf":            "digitalocean",
		},
		"ec2-compat": oemConfig{
			"from-ec2-metadata": "http://169.254.169.254/",
			"from-configdrive":  "/media/configdrive",
		},
		"rackspace-onmetal": oemConfig{
			"from-configdrive": "/media/configdrive",
			"convert-netconf":  "debian",
		},
	}
)

func main() {
	failure := false

	flag.Parse()

	if c, ok := oemConfigs[flags.oem]; ok {
		for k, v := range c {
			flag.Set(k, v)
		}
	} else if flags.oem != "" {
		oems := make([]string, 0, len(oemConfigs))
		for k := range oemConfigs {
			oems = append(oems, k)
		}
		fmt.Printf("Invalid option to --oem: %q. Supported options: %q\n", flags.oem, oems)
		os.Exit(2)
	}

	if flags.printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	switch flags.convertNetconf {
	case "":
	case "debian":
	case "digitalocean":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, digitalocean'\n", flags.convertNetconf)
		os.Exit(2)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-cloudsigma-metadata, --from-url or --from-proc-cmdline")
		os.Exit(2)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		os.Exit(1)
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\nContinuing...\n", err)
		failure = true
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		os.Exit(1)
	}

	// Extract IPv4 addresses from metadata if possible
	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			os.Exit(1)
		}
	}

	// Apply environment to user-data
	env := initialize.NewEnvironment("/", ds.ConfigRoot(), flags.workspace, flags.convertNetconf, flags.sshKeyName, subs)
	userdata := env.Apply(string(userdataBytes))

	var ccm, ccu *initialize.CloudConfig
	var script *system.Script
	if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil {
		fmt.Printf("Failed to parse meta-data: %v\n", err)
		os.Exit(1)
	}

	if ccm != nil && ccm.NetworkConfigPath != "" {
		fmt.Printf("Fetching network config from datasource of type %q\n", ds.Type())
		netconfBytes, err := ds.FetchNetworkConfig(ccm.NetworkConfigPath)
		if err != nil {
			fmt.Printf("Failed fetching network config from datasource: %v\n", err)
			os.Exit(1)
		}
		ccm.NetworkConfig = string(netconfBytes)
	}

	if ud, err := initialize.ParseUserData(userdata); err != nil {
		fmt.Printf("Failed to parse user-data: %v\nContinuing...\n", err)
		failure = true
	} else {
		switch t := ud.(type) {
		case *initialize.CloudConfig:
			ccu = t
		case system.Script:
			script = &t
		}
	}

	var cc *initialize.CloudConfig
	if ccm != nil && ccu != nil {
		fmt.Println("Merging cloud-config from meta-data and user-data")
		merged := mergeCloudConfig(*ccm, *ccu)
		cc = &merged
	} else if ccm != nil && ccu == nil {
		fmt.Println("Processing cloud-config from meta-data")
		cc = ccm
	} else if ccm == nil && ccu != nil {
		fmt.Println("Processing cloud-config from user-data")
		cc = ccu
	} else {
		fmt.Println("No cloud-config data to handle.")
	}

	if cc != nil {
		if err = initialize.Apply(*cc, env); err != nil {
			fmt.Printf("Failed to apply cloud-config: %v\n", err)
			os.Exit(1)
		}
	}

	if script != nil {
		if err = runScript(*script, env); err != nil {
			fmt.Printf("Failed to run script: %v\n", err)
			os.Exit(1)
		}
	}

	if failure && !flags.ignoreFailure {
		os.Exit(1)
	}
}

// mergeCloudConfig merges certain options from mdcc (a CloudConfig derived from
// meta-data) onto udcc (a CloudConfig derived from user-data), if they are
// not already set on udcc (i.e. user-data always takes precedence)
// NB: This needs to be kept in sync with ParseMetadata so that it tracks all
// elements of a CloudConfig which that function can populate.
func mergeCloudConfig(mdcc, udcc initialize.CloudConfig) (cc initialize.CloudConfig) {
	if mdcc.Hostname != "" {
		if udcc.Hostname != "" {
			fmt.Printf("Warning: user-data hostname (%s) overrides metadata hostname (%s)\n", udcc.Hostname, mdcc.Hostname)
		} else {
			udcc.Hostname = mdcc.Hostname
		}

	}
	for _, key := range mdcc.SSHAuthorizedKeys {
		udcc.SSHAuthorizedKeys = append(udcc.SSHAuthorizedKeys, key)
	}
	if mdcc.NetworkConfigPath != "" {
		if udcc.NetworkConfigPath != "" {
			fmt.Printf("Warning: user-data NetworkConfigPath %s overrides metadata NetworkConfigPath %s\n", udcc.NetworkConfigPath, mdcc.NetworkConfigPath)
		} else {
			udcc.NetworkConfigPath = mdcc.NetworkConfigPath
		}
	}
	if mdcc.NetworkConfig != "" {
		if udcc.NetworkConfig != "" {
			fmt.Printf("Warning: user-data NetworkConfig %s overrides metadata NetworkConfig %s\n", udcc.NetworkConfig, mdcc.NetworkConfig)
		} else {
			udcc.NetworkConfig = mdcc.NetworkConfig
		}
	}
	return udcc
}

// getDatasources creates a slice of possible Datasources for cloudinit based
// on the different source command-line flags.
func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if flags.sources.file != "" {
		dss = append(dss, file.NewDatasource(flags.sources.file))
	}
	if flags.sources.url != "" {
		dss = append(dss, url.NewDatasource(flags.sources.url))
	}
	if flags.sources.configDrive != "" {
		dss = append(dss, configdrive.NewDatasource(flags.sources.configDrive))
	}
	if flags.sources.metadataService {
		dss = append(dss, ec2.NewDatasource(ec2.DefaultAddress))
	}
	if flags.sources.ec2MetadataService != "" {
		dss = append(dss, ec2.NewDatasource(flags.sources.ec2MetadataService))
	}
	if flags.sources.cloudSigmaMetadataService {
		dss = append(dss, cloudsigma.NewServerContextService())
	}
	if flags.sources.digitalOceanMetadataService != "" {
		dss = append(dss, digitalocean.NewDatasource(flags.sources.digitalOceanMetadataService))
	}
	if flags.sources.procCmdLine {
		dss = append(dss, proc_cmdline.NewDatasource())
	}
	return dss
}

// selectDatasource attempts to choose a valid Datasource to use based on its
// current availability. The first Datasource to report to be available is
// returned. Datasources will be retried if possible if they are not
// immediately available. If all Datasources are permanently unavailable or
// datasourceTimeout is reached before one becomes available, nil is returned.
func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.After(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.After(datasourceTimeout):
	}

	close(stop)
	return s
}

// TODO(jonboulle): this should probably be refactored and moved into a different module
func runScript(script system.Script, env *initialize.Environment) error {
	err := initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}
	path, err := initialize.PersistScriptInWorkspace(script, env.Workspace())
	if err == nil {
		var name string
		name, err = system.ExecuteScript(path)
		initialize.PersistUnitNameInWorkspace(name, env.Workspace())
	}
	return err
}
<commit_msg>coreos-cloudinit: bump to 0.10.1<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/datasource/configdrive"
	"github.com/coreos/coreos-cloudinit/datasource/file"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/cloudsigma"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/digitalocean"
	"github.com/coreos/coreos-cloudinit/datasource/metadata/ec2"
	"github.com/coreos/coreos-cloudinit/datasource/proc_cmdline"
	"github.com/coreos/coreos-cloudinit/datasource/url"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.10.1"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	flags = struct {
		printVersion  bool
		ignoreFailure bool
		sources       struct {
			file                        string
			configDrive                 string
			metadataService             bool
			ec2MetadataService          string
			cloudSigmaMetadataService   bool
			digitalOceanMetadataService string
			url                         string
			procCmdLine                 bool
		}
		convertNetconf string
		workspace      string
		sshKeyName     string
		oem            string
	}{}
)

func init() {
	flag.BoolVar(&flags.printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&flags.ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&flags.sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&flags.sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&flags.sources.metadataService, "from-metadata-service", false, "[DEPRECATED - Use -from-ec2-metadata] Download data from metadata service")
	flag.StringVar(&flags.sources.ec2MetadataService, "from-ec2-metadata", "", "Download EC2 data from the provided url")
	flag.BoolVar(&flags.sources.cloudSigmaMetadataService, "from-cloudsigma-metadata", false, "Download data from CloudSigma server context")
	flag.StringVar(&flags.sources.digitalOceanMetadataService, "from-digitalocean-metadata", "", "Download DigitalOcean data from the provided url")
	flag.StringVar(&flags.sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&flags.sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", proc_cmdline.ProcCmdlineLocation, proc_cmdline.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&flags.oem, "oem", "", "Use the settings specific to the provided OEM")
	flag.StringVar(&flags.convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files")
	flag.StringVar(&flags.workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&flags.sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

type oemConfig map[string]string

var (
	oemConfigs = map[string]oemConfig{
		"digitalocean": oemConfig{
			"from-digitalocean-metadata": "http://169.254.169.254/",
			"convert-netconf":            "digitalocean",
		},
		"ec2-compat": oemConfig{
			"from-ec2-metadata": "http://169.254.169.254/",
			"from-configdrive":  "/media/configdrive",
		},
		"rackspace-onmetal": oemConfig{
			"from-configdrive": "/media/configdrive",
			"convert-netconf":  "debian",
		},
	}
)

func main() {
	failure := false

	flag.Parse()

	if c, ok := oemConfigs[flags.oem]; ok {
		for k, v := range c {
			flag.Set(k, v)
		}
	} else if flags.oem != "" {
		oems := make([]string, 0, len(oemConfigs))
		for k := range oemConfigs {
			oems = append(oems, k)
		}
		fmt.Printf("Invalid option to --oem: %q. Supported options: %q\n", flags.oem, oems)
		os.Exit(2)
	}

	if flags.printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	switch flags.convertNetconf {
	case "":
	case "debian":
	case "digitalocean":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, digitalocean'\n", flags.convertNetconf)
		os.Exit(2)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-ec2-metadata, --from-cloudsigma-metadata, --from-url or --from-proc-cmdline")
		os.Exit(2)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		os.Exit(1)
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\nContinuing...\n", err)
		failure = true
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		os.Exit(1)
	}

	// Extract IPv4 addresses from metadata if possible
	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			os.Exit(1)
		}
	}

	// Apply environment to user-data
	env := initialize.NewEnvironment("/", ds.ConfigRoot(), flags.workspace, flags.convertNetconf, flags.sshKeyName, subs)
	userdata := env.Apply(string(userdataBytes))

	var ccm, ccu *initialize.CloudConfig
	var script *system.Script
	if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil {
		fmt.Printf("Failed to parse meta-data: %v\n", err)
		os.Exit(1)
	}

	if ccm != nil && ccm.NetworkConfigPath != "" {
		fmt.Printf("Fetching network config from datasource of type %q\n", ds.Type())
		netconfBytes, err := ds.FetchNetworkConfig(ccm.NetworkConfigPath)
		if err != nil {
			fmt.Printf("Failed fetching network config from datasource: %v\n", err)
			os.Exit(1)
		}
		ccm.NetworkConfig = string(netconfBytes)
	}

	if ud, err := initialize.ParseUserData(userdata); err != nil {
		fmt.Printf("Failed to parse user-data: %v\nContinuing...\n", err)
		failure = true
	} else {
		switch t := ud.(type) {
		case *initialize.CloudConfig:
			ccu = t
		case system.Script:
			script = &t
		}
	}

	var cc *initialize.CloudConfig
	if ccm != nil && ccu != nil {
		fmt.Println("Merging cloud-config from meta-data and user-data")
		merged := mergeCloudConfig(*ccm, *ccu)
		cc = &merged
	} else if ccm != nil && ccu == nil {
		fmt.Println("Processing cloud-config from meta-data")
		cc = ccm
	} else if ccm == nil && ccu != nil {
		fmt.Println("Processing cloud-config from user-data")
		cc = ccu
	} else {
		fmt.Println("No cloud-config data to handle.")
	}

	if cc != nil {
		if err = initialize.Apply(*cc, env); err != nil {
			fmt.Printf("Failed to apply cloud-config: %v\n", err)
			os.Exit(1)
		}
	}

	if script != nil {
		if err = runScript(*script, env); err != nil {
			fmt.Printf("Failed to run script: %v\n", err)
			os.Exit(1)
		}
	}

	if failure && !flags.ignoreFailure {
		os.Exit(1)
	}
}

// mergeCloudConfig merges certain options from mdcc (a CloudConfig derived from
// meta-data) onto udcc (a CloudConfig derived from user-data), if they are
// not already set on udcc (i.e. user-data always takes precedence)
// NB: This needs to be kept in sync with ParseMetadata so that it tracks all
// elements of a CloudConfig which that function can populate.
func mergeCloudConfig(mdcc, udcc initialize.CloudConfig) (cc initialize.CloudConfig) {
	if mdcc.Hostname != "" {
		if udcc.Hostname != "" {
			fmt.Printf("Warning: user-data hostname (%s) overrides metadata hostname (%s)\n", udcc.Hostname, mdcc.Hostname)
		} else {
			udcc.Hostname = mdcc.Hostname
		}

	}
	for _, key := range mdcc.SSHAuthorizedKeys {
		udcc.SSHAuthorizedKeys = append(udcc.SSHAuthorizedKeys, key)
	}
	if mdcc.NetworkConfigPath != "" {
		if udcc.NetworkConfigPath != "" {
			fmt.Printf("Warning: user-data NetworkConfigPath %s overrides metadata NetworkConfigPath %s\n", udcc.NetworkConfigPath, mdcc.NetworkConfigPath)
		} else {
			udcc.NetworkConfigPath = mdcc.NetworkConfigPath
		}
	}
	if mdcc.NetworkConfig != "" {
		if udcc.NetworkConfig != "" {
			fmt.Printf("Warning: user-data NetworkConfig %s overrides metadata NetworkConfig %s\n", udcc.NetworkConfig, mdcc.NetworkConfig)
		} else {
			udcc.NetworkConfig = mdcc.NetworkConfig
		}
	}
	return udcc
}

// getDatasources creates a slice of possible Datasources for cloudinit based
// on the different source command-line flags.
func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if flags.sources.file != "" {
		dss = append(dss, file.NewDatasource(flags.sources.file))
	}
	if flags.sources.url != "" {
		dss = append(dss, url.NewDatasource(flags.sources.url))
	}
	if flags.sources.configDrive != "" {
		dss = append(dss, configdrive.NewDatasource(flags.sources.configDrive))
	}
	if flags.sources.metadataService {
		dss = append(dss, ec2.NewDatasource(ec2.DefaultAddress))
	}
	if flags.sources.ec2MetadataService != "" {
		dss = append(dss, ec2.NewDatasource(flags.sources.ec2MetadataService))
	}
	if flags.sources.cloudSigmaMetadataService {
		dss = append(dss, cloudsigma.NewServerContextService())
	}
	if flags.sources.digitalOceanMetadataService != "" {
		dss = append(dss, digitalocean.NewDatasource(flags.sources.digitalOceanMetadataService))
	}
	if flags.sources.procCmdLine {
		dss = append(dss, proc_cmdline.NewDatasource())
	}
	return dss
}

// selectDatasource attempts to choose a valid Datasource to use based on its
// current availability. The first Datasource to report to be available is
// returned. Datasources will be retried if possible if they are not
// immediately available. If all Datasources are permanently unavailable or
// datasourceTimeout is reached before one becomes available, nil is returned.
func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.After(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.After(datasourceTimeout):
	}

	close(stop)
	return s
}

// TODO(jonboulle): this should probably be refactored and moved into a different module
func runScript(script system.Script, env *initialize.Environment) error {
	err := initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}
	path, err := initialize.PersistScriptInWorkspace(script, env.Workspace())
	if err == nil {
		var name string
		name, err = system.ExecuteScript(path)
		initialize.PersistUnitNameInWorkspace(name, env.Workspace())
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/system"
)

const version = "0.7.1"

func main() {
	var printVersion bool
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")

	var ignoreFailure bool
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")

	var file string
	flag.StringVar(&file, "from-file", "", "Read user-data from provided file")

	var url string
	flag.StringVar(&url, "from-url", "", "Download user-data from provided url")

	var useProcCmdline bool
	flag.BoolVar(&useProcCmdline, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))

	var workspace string
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")

	var sshKeyName string
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")

	flag.Parse()

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	var ds datasource.Datasource
	if file != "" {
		ds = datasource.NewLocalFile(file)
	} else if url != "" {
		ds = datasource.NewMetadataService(url)
	} else if useProcCmdline {
		ds = datasource.NewProcCmdline()
	} else {
		fmt.Println("Provide one of --from-file, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	log.Printf("Fetching user-data from datasource of type %q", ds.Type())
	userdataBytes, err := ds.Fetch()
	if err != nil {
		log.Printf("Failed fetching user-data from datasource: %v", err)
		if ignoreFailure {
			os.Exit(0)
		} else {
			os.Exit(1)
		}
	}

	if len(userdataBytes) == 0 {
		log.Printf("No user data to handle, exiting.")
		os.Exit(0)
	}

	env := initialize.NewEnvironment("/", workspace)

	userdata := string(userdataBytes)
	userdata = env.Apply(userdata)

	parsed, err := initialize.ParseUserData(userdata)
	if err != nil {
		log.Printf("Failed parsing user-data: %v", err)
		if ignoreFailure {
			os.Exit(0)
		} else {
			os.Exit(1)
		}
	}

	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		log.Fatalf("Failed preparing workspace: %v", err)
	}

	switch t := parsed.(type) {
	case initialize.CloudConfig:
		err = initialize.Apply(t, env)
	case system.Script:
		var path string
		path, err = initialize.PersistScriptInWorkspace(t, env.Workspace())
		if err == nil {
			var name string
			name, err = system.ExecuteScript(path)
			initialize.PersistUnitNameInWorkspace(name, workspace)
		}
	}

	if err != nil {
		log.Fatalf("Failed resolving user-data: %v", err)
	}
}
<commit_msg>chore(coreos-cloudinit): bump to 0.7.1+git<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/system"
)

const version = "0.7.1+git"

func main() {
	var printVersion bool
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")

	var ignoreFailure bool
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")

	var file string
	flag.StringVar(&file, "from-file", "", "Read user-data from provided file")

	var url string
	flag.StringVar(&url, "from-url", "", "Download user-data from provided url")

	var useProcCmdline bool
	flag.BoolVar(&useProcCmdline, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))

	var workspace string
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")

	var sshKeyName string
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")

	flag.Parse()

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	var ds datasource.Datasource
	if file != "" {
		ds = datasource.NewLocalFile(file)
	} else if url != "" {
		ds = datasource.NewMetadataService(url)
	} else if useProcCmdline {
		ds = datasource.NewProcCmdline()
	} else {
		fmt.Println("Provide one of --from-file, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	log.Printf("Fetching user-data from datasource of type %q", ds.Type())
	userdataBytes, err := ds.Fetch()
	if err != nil {
		log.Printf("Failed fetching user-data from datasource: %v", err)
		if ignoreFailure {
			os.Exit(0)
		} else {
			os.Exit(1)
		}
	}

	if len(userdataBytes) == 0 {
		log.Printf("No user data to handle, exiting.")
		os.Exit(0)
	}

	env := initialize.NewEnvironment("/", workspace)

	userdata := string(userdataBytes)
	userdata = env.Apply(userdata)

	parsed, err := initialize.ParseUserData(userdata)
	if err != nil {
		log.Printf("Failed parsing user-data: %v", err)
		if ignoreFailure {
			os.Exit(0)
		} else {
			os.Exit(1)
		}
	}

	err = initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		log.Fatalf("Failed preparing workspace: %v", err)
	}

	switch t := parsed.(type) {
	case initialize.CloudConfig:
		err = initialize.Apply(t, env)
	case system.Script:
		var path string
		path, err = initialize.PersistScriptInWorkspace(t, env.Workspace())
		if err == nil {
			var name string
			name, err = system.ExecuteScript(path)
			initialize.PersistUnitNameInWorkspace(name, workspace)
		}
	}

	if err != nil {
		log.Fatalf("Failed resolving user-data: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	_ "github.com/mattn/go-oci8"
)

func main() {
	nlsLang := os.Getenv("NLS_LANG")
	if !strings.HasSuffix(nlsLang, "UTF8") {
		i := strings.LastIndex(nlsLang, ".")
		if i < 0 {
			nlsLang = "AMERICAN_AMERICA.AL32UTF8"
		} else {
			nlsLang = nlsLang[:i+1] + "AL32UTF8"
		}
		fmt.Fprintf(os.Stderr, "NLS_LANG error: should be %s, not %s!\n",
			nlsLang, os.Getenv("NLS_LANG"))
	}

	db, err := sql.Open("oci8", getDSN())
	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()

	if err = testSelect(db); err != nil {
		fmt.Println(err)
		return
	}

	if err = testI18n(db); err != nil {
		fmt.Println(err)
		return
	}
}

func getDSN() string {
	var dsn string
	if len(os.Args) > 1 {
		dsn = os.Args[1]
		if dsn != "" {
			return dsn
		}
	}
	dsn = os.Getenv("GO_OCI8_CONNECT_STRING")
	if dsn != "" {
		return dsn
	}
	fmt.Fprintln(os.Stderr, `Please specifiy connection parameter in GO_OCI8_CONNECT_STRING environment variable,
or as the first argument! (The format is user/name@host:port/sid)`)
	os.Exit(1)
	return ""
}

func testSelect(db *sql.DB) error {
	rows, err := db.Query("select 3.14, 'foo' from dual")
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var f1 float64
		var f2 string
		rows.Scan(&f1, &f2)
		println(f1, f2) // 3.14 foo
	}
	_, err = db.Exec("create table foo(bar varchar2(256))")
	_, err = db.Exec("drop table foo")
	if err != nil {
		return err
	}

	return nil
}

const tbl = "tst_oci8_i18n"
const tst_strings = "'Habitación doble', '雙人房', 'двухместный номер'"

func testI18n(db *sql.DB) error {
	db, err := sql.Open("oci8", getDSN())
	if err != nil {
		return err
	}
	defer db.Close()

	_, _ = db.Exec("DROP TABLE " + tbl)
	defer db.Exec("DROP TABLE " + tbl)
	if _, err = db.Exec("CREATE TABLE " + tbl + " (name_spainish VARCHAR2(100), name_chinesses VARCHAR2(100), name_russian VARCHAR2(100))"); err != nil {
		return err
	}
	if _, err = db.Exec("INSERT INTO " + tbl +
		" (name_spainish, name_chinesses, name_russian) " +
		" VALUES (" + tst_strings + ")"); err != nil {
		return err
	}

	rows, err := db.Query("select name_spainish, name_chinesses, name_russian from " + tbl)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var nameSpainish string
		var nameChinesses string
		var nameRussian string
		if err = rows.Scan(&nameSpainish, &nameChinesses, &nameRussian); err != nil {
			return err
		}
		got := fmt.Sprintf("'%s', '%s', '%s'", nameSpainish, nameChinesses, nameRussian)
		fmt.Println(got)
		if got != tst_strings {
			return fmt.Errorf("ERROR: string mismatch: got %q, awaited %q\n", got, tst_strings)
		}
	}
	return rows.Err()
}
<commit_msg>Graceful error<commit_after>package main

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	_ "github.com/mattn/go-oci8"
)

func main() {
	nlsLang := os.Getenv("NLS_LANG")
	if !strings.HasSuffix(nlsLang, "UTF8") {
		i := strings.LastIndex(nlsLang, ".")
		if i < 0 {
			os.Setenv("NLS_LANG", "AMERICAN_AMERICA.AL32UTF8")
		} else {
			nlsLang = nlsLang[:i+1] + "AL32UTF8"
			fmt.Fprintf(os.Stderr, "NLS_LANG error: should be %s, not %s!\n",
				nlsLang, os.Getenv("NLS_LANG"))
		}
	}

	db, err := sql.Open("oci8", getDSN())
	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()

	if err = testSelect(db); err != nil {
		fmt.Println(err)
		return
	}

	if err = testI18n(db); err != nil {
		fmt.Println(err)
		return
	}
}

func getDSN() string {
	var dsn string
	if len(os.Args) > 1 {
		dsn = os.Args[1]
		if dsn != "" {
			return dsn
		}
	}
	dsn = os.Getenv("GO_OCI8_CONNECT_STRING")
	if dsn != "" {
		return dsn
	}
	fmt.Fprintln(os.Stderr, `Please specifiy connection parameter in GO_OCI8_CONNECT_STRING environment variable,
or as the first argument! (The format is user/name@host:port/sid)`)
	os.Exit(1)
	return ""
}

func testSelect(db *sql.DB) error {
	rows, err := db.Query("select 3.14, 'foo' from dual")
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var f1 float64
		var f2 string
		rows.Scan(&f1, &f2)
		println(f1, f2) // 3.14 foo
	}
	_, err = db.Exec("create table foo(bar varchar2(256))")
	_, err = db.Exec("drop table foo")
	if err != nil {
		return err
	}

	return nil
}

const tbl = "tst_oci8_i18n"
const tst_strings = "'Habitación doble', '雙人房', 'двухместный номер'"

func testI18n(db *sql.DB) error {
	db, err := sql.Open("oci8", getDSN())
	if err != nil {
		return err
	}
	defer db.Close()

	_, _ = db.Exec("DROP TABLE " + tbl)
	defer db.Exec("DROP TABLE " + tbl)
	if _, err = db.Exec("CREATE TABLE " + tbl + " (name_spainish VARCHAR2(100), name_chinesses VARCHAR2(100), name_russian VARCHAR2(100))"); err != nil {
		return err
	}
	if _, err = db.Exec("INSERT INTO " + tbl +
		" (name_spainish, name_chinesses, name_russian) " +
		" VALUES (" + tst_strings + ")"); err != nil {
		return err
	}

	rows, err := db.Query("select name_spainish, name_chinesses, name_russian from " + tbl)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var nameSpainish string
		var nameChinesses string
		var nameRussian string
		if err = rows.Scan(&nameSpainish, &nameChinesses, &nameRussian); err != nil {
			return err
		}
		got := fmt.Sprintf("'%s', '%s', '%s'", nameSpainish, nameChinesses, nameRussian)
		fmt.Println(got)
		if got != tst_strings {
			return fmt.Errorf("ERROR: string mismatch: got %q, awaited %q\n", got, tst_strings)
		}
	}
	return rows.Err()
}
<|endoftext|>


<commit_before>//Copyright 2014 Rana Ian. All rights reserved.
//Use of this source code is governed by The MIT License
//found in the accompanying LICENSE file.

package ora_test

import (
	"fmt"
	"testing"

	"gopkg.in/rana/ora.v3"
)

//// string or bool
//charB1     oracleColumnType = "char(1 byte) not null"
//charB1Null oracleColumnType = "char(1 byte) null"
//charC1     oracleColumnType = "char(1 char) not null"
//charC1Null oracleColumnType = "char(1 char) null"

func TestBindDefineBool(t *testing.T) {
	type testCase struct {
		gen func() interface{}
		ct  oracleColumnType
	}
	sc := ora.NewStmtCfg()
	testCases := make(map[string]testCase, 32)
	for _, ctName := range []string{"charB1", "charB1Null"} {
		ct := _T_colType[ctName]
		for _, typName := range []string{"bool", "OraBool", "boolSlice"} {
			for _, valName := range []string{"false", "true"} {
				testCases[fmt.Sprintf("%s_%s_%s", ctName, typName, valName)] = testCase{ct: ct, gen: _T_boolGen[typName+"_"+valName]}
			}
		}
	}
	for name, tc := range testCases {
		t.Run(name, func(t *testing.T) { t.Parallel(); testBindDefine(tc.gen(), tc.ct, t, sc) })
	}
}

func TestBindPtrBool(t *testing.T) {
	type testCase struct {
		gen func() interface{}
		ct  oracleColumnType
	}
	testCases := make(map[string]testCase, 16)
	for _, ctName := range []string{"charB1", "charB1Null", "charC1", "charC1Null"} {
		for _, valName := range []string{"false", "true"} {
			k := ctName + "_" + valName
			testCases[k] = testCase{
				gen: _T_boolGen[k],
				ct:  _T_colType[ctName],
			}
		}
	}

	sc := ora.NewStmtCfg()
	for name, tc := range testCases {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			testBindPtr(tc.gen(), tc.ct, t)
		})
	}
}

func TestMultiDefineBool(t *testing.T) {
	sc := ora.NewStmtCfg()
	for _, ctName := range []string{
		"charB1", "charB1Null",
		"charC1", "charC1Null",
	} {
		t.Run(ctName, func(t *testing.T) {
			t.Parallel()
			testMultiDefine(
				_T_boolGen[ctName+"_true"],
				_T_colType[ctName],
				t,
			)
		})
	}
}

func TestWorkloadBool(t *testing.T) {
	for name, ct := range map[string]oracleColumnType{
		"charB1":     charB1,
		"charB1Null": charB1Null,
		"charC1":     charC1,
		"charC1Null": charC1Null,
	} {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			//enableLogging(t)
			defer setC1Bool()()
			testWorkload(ct, t)
		})
	}
}

var _T_colType = map[string]oracleColumnType{
	"charB1":     charB1,
	"charB1Null": charB1Null,
	"charC1":     charC1,
	"charC1Null": charC1Null,
}

var _T_boolGen = map[string](func() interface{}){
	"bool_false":        func() interface{} { gen_boolFalse },
	"bool_true":         func() interface{} { gen_boolTrue },
	"OraBool_false":     func() interface{} { return gen_OraBoolFalse() },
	"OraBool_true":      func() interface{} { return gen_OraBoolTrue() },
	"boolSlice_false":   func() interface{} { return gen_boolSlice() },
	"boolSlice_false":   func() interface{} { return gen_boolSlice() },
	"OraBoolSlice_true": func() interface{} { return gen_boolSlice(false) },
}

func setC1Bool() func() {
	old := ora.Cfg().Env.StmtCfg.Rset.Char1()
	ora.Cfg().Log.Logger.Infof("setting Char1 from %s to %s.", old, ora.OraB)
	ora.Cfg().Env.StmtCfg.Rset.SetChar1(ora.OraB)
	return func() {
		ora.Cfg().Log.Logger.Infof("setting Char1 back from %s to %s.", ora.Cfg().Env.StmtCfg.Rset.Char1(), old)
		ora.Cfg().Env.StmtCfg.Rset.SetChar1(old)
	}
}

// Issue89
func TestSelectChar(t *testing.T) {
	t.Parallel()
	tableName := tableName()
	if _, err := testDb.Exec("CREATE TABLE " + tableName + "(c1 CHAR(1), c2 CHAR(4))"); err != nil {
		t.Fatal(err)
	}
	if _, err := testSes.PrepAndExe("INSERT INTO "+tableName+" VALUES (:1, :2)",
		"A", "ABCD"); err != nil {
		t.Fatal(err)
	}
	got := make([]interface{}, 0, 2)
	for tN, tC := range []struct {
		colDefs []ora.GoColumnType
		want    []interface{}
	}{
		{[]ora.GoColumnType{ora.B, ora.B}, []interface{}{false, false}},
		{[]ora.GoColumnType{ora.S, ora.S}, []interface{}{"A", "ABCD"}},
		{nil, []interface{}{"A", "ABCD"}},
	} {
		stmt, err := testSes.Prep("SELECT c1, c2 FROM "+tableName, tC.colDefs...)
		if err != nil {
			t.Fatal(err)
		}
		defer stmt.Close()
		rset, err := stmt.Qry()
		if err != nil {
			t.Fatal(err)
		}
		got = got[:0]
		rset.Next()
		got = append(got, rset.Row[0], rset.Row[1])
		t.Logf("%d. got %q, want %q.", tN, got, tC.want)
		if len(got) != len(tC.want) || got[0] != tC.want[0] || got[1] != tC.want[1] {
			t.Errorf("%d. got %q, want %q.", tN, got, tC.want)
		}
	}
}
<commit_msg>modularize z_bool_session_test<commit_after>//Copyright 2014 Rana Ian. All rights reserved.
//Use of this source code is governed by The MIT License
//found in the accompanying LICENSE file.

package ora_test

import (
	"fmt"
	"testing"

	"gopkg.in/rana/ora.v3"
)

//// string or bool
//charB1     oracleColumnType = "char(1 byte) not null"
//charB1Null oracleColumnType = "char(1 byte) null"
//charC1     oracleColumnType = "char(1 char) not null"
//charC1Null oracleColumnType = "char(1 char) null"

func TestBindDefineBool(t *testing.T) {
	type testCase struct {
		gen func() interface{}
		ct  oracleColumnType
	}
	sc := ora.NewStmtCfg()
	testCases := make(map[string]testCase, 32)
	for _, ctName := range []string{"charB1", "charB1Null"} {
		ct := _T_colType[ctName]
		for _, typName := range []string{"bool", "OraBool", "boolSlice"} {
			for _, valName := range []string{"false", "true"} {
				testCases[fmt.Sprintf("%s_%s_%s", ctName, typName, valName)] = testCase{ct: ct, gen: _T_boolGen[typName+"_"+valName]}
			}
		}
	}
	for name, tc := range testCases {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			testBindDefine(tc.gen(), tc.ct, t, sc)
		})
	}
}

func TestBindPtrBool(t *testing.T) {
	type testCase struct {
		gen func() interface{}
		ct  oracleColumnType
	}
	testCases := make(map[string]testCase, 16)
	for _, ctName := range []string{"charB1", "charB1Null", "charC1", "charC1Null"} {
		for _, valName := range []string{"false", "true"} {
			k := ctName + "_" + valName
			testCases[k] = testCase{
				gen: _T_boolGen[k],
				ct:  _T_colType[ctName],
			}
		}
	}

	sc := ora.NewStmtCfg()
	for name, tc := range testCases {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			testBindPtr(tc.gen(), tc.ct, t)
		})
	}
}

func TestMultiDefineBool(t *testing.T) {
	sc := ora.NewStmtCfg()
	for _, ctName := range []string{
		"charB1", "charB1Null",
		"charC1", "charC1Null",
	} {
		t.Run(ctName, func(t *testing.T) {
			t.Parallel()
			testMultiDefine(
				_T_boolGen[ctName+"_true"],
				_T_colType[ctName],
				t,
			)
		})
	}
}

func TestWorkloadBool(t *testing.T) {
	for name, ct := range map[string]oracleColumnType{
		"charB1":     charB1,
		"charB1Null": charB1Null,
		"charC1":     charC1,
		"charC1Null": charC1Null,
	} {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			//enableLogging(t)
			defer setC1Bool()()
			testWorkload(ct, t)
		})
	}
}

var _T_colType = map[string]oracleColumnType{
	"charB1":     charB1,
	"charB1Null": charB1Null,
	"charC1":     charC1,
	"charC1Null": charC1Null,

	"longRaw":     longRaw,
	"longRawNull": longRawNull,
	"raw2000":     raw2000,
	"raw2000Null": raw2000Null,
	"blob":        blob,
	"blobNull":    blobNull,

	"intervalYM":     intervalYM,
	"intervalYMNull": intervalYMNull,
	"intervalDS":     intervalYM,
	"intervalDSNull": intervalYMNull,

	"numberP38S0":      numberP38S0,
	"numberP38S0Null":  numberP38S0Null,
	"numberP16S15":     numberP16S15,
	"numberP16S15Null": numberP16S15Null,
	"binaryDouble":     binaryDouble,
	"binaryDoubleNull": binaryDoubleNull,
	"binaryFloat":      binaryFloat,
	"binaryFloatNull":  binaryFloatNull,
	"floatP126":        floatP126,
	"floatP126Null":    floatP126Null,
}

var _T_boolGen = map[string](func() interface{}){
	"bool_false":        func() interface{} { gen_boolFalse },
	"bool_true":         func() interface{} { gen_boolTrue },
	"OraBool_false":     func() interface{} { return gen_OraBoolFalse() },
	"OraBool_true":      func() interface{} { return gen_OraBoolTrue() },
	"boolSlice_false":   func() interface{} { return gen_boolSlice() },
	"boolSlice_true":    func() interface{} { return gen_boolSlice() },
	"OraBoolSlice_true": func() interface{} { return gen_boolSlice(false) },
}

func setC1Bool() func() {
	old := ora.Cfg().Env.StmtCfg.Rset.Char1()
	ora.Cfg().Log.Logger.Infof("setting Char1 from %s to %s.", old, ora.OraB)
	ora.Cfg().Env.StmtCfg.Rset.SetChar1(ora.OraB)
	return func() {
		ora.Cfg().Log.Logger.Infof("setting Char1 back from %s to %s.", ora.Cfg().Env.StmtCfg.Rset.Char1(), old)
		ora.Cfg().Env.StmtCfg.Rset.SetChar1(old)
	}
}

// Issue89
func TestSelectChar(t *testing.T) {
	t.Parallel()
	tableName := tableName()
	if _, err := testDb.Exec("CREATE TABLE " + tableName + "(c1 CHAR(1), c2 CHAR(4))"); err != nil {
		t.Fatal(err)
	}
	if _, err := testSes.PrepAndExe("INSERT INTO "+tableName+" VALUES (:1, :2)",
		"A", "ABCD"); err != nil {
		t.Fatal(err)
	}
	got := make([]interface{}, 0, 2)
	for tN, tC := range []struct {
		colDefs []ora.GoColumnType
		want    []interface{}
	}{
		{[]ora.GoColumnType{ora.B, ora.B}, []interface{}{false, false}},
		{[]ora.GoColumnType{ora.S, ora.S}, []interface{}{"A", "ABCD"}},
		{nil, []interface{}{"A", "ABCD"}},
	} {
		stmt, err := testSes.Prep("SELECT c1, c2 FROM "+tableName, tC.colDefs...)
		if err != nil {
			t.Fatal(err)
		}
		defer stmt.Close()
		rset, err := stmt.Qry()
		if err != nil {
			t.Fatal(err)
		}
		got = got[:0]
		rset.Next()
		got = append(got, rset.Row[0], rset.Row[1])
		t.Logf("%d. got %q, want %q.", tN, got, tC.want)
		if len(got) != len(tC.want) || got[0] != tC.want[0] || got[1] != tC.want[1] {
			t.Errorf("%d. got %q, want %q.", tN, got, tC.want)
		}
	}
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]

package database /* import "github.com/mozilla/mig/database" */

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

type DB struct {
	c *sql.DB
}

// Connect opens a connection to the database and returns a handler
func Open(dbname, user, password, host string, port int, sslmode string) (db DB, err error) {
	url := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
		user, password, host, port, dbname, sslmode)
	db.c, err = sql.Open("postgres", url)
	return
}

func (db *DB) Close() {
	db.c.Close()
}

func (db *DB) SetMaxOpenConns(n int) {
	db.c.SetMaxOpenConns(n)
}
<commit_msg>Check for ping when connecting to postgresql db<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]

package database /* import "github.com/mozilla/mig/database" */

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

type DB struct {
	c *sql.DB
}

// Connect opens a connection to the database and returns a handler
func Open(dbname, user, password, host string, port int, sslmode string) (db DB, err error) {
	url := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
		user, password, host, port, dbname, sslmode)
	db.c, err = sql.Open("postgres", url)
	if err != nil {
		return
	}
	err = db.c.Ping()
	return
}

func (db *DB) Close() {
	db.c.Close()
}

func (db *DB) SetMaxOpenConns(n int) {
	db.c.SetMaxOpenConns(n)
}
<|endoftext|>