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

package saml

import (
	"strconv"
	"net/url"
	"strings"
	"fmt"

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/auth/native"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/validation"
	saml "github.com/diego-araujo/go-saml"
)

var (
	ErrMissingRequestIdError       = &errors.ValidationError{Message: "You must provide RequestID to login"}
	ErrMissingFormValueError       = &errors.ValidationError{Message: "SAMLResponse form value missing"}
	ErrParseResponseError       = &errors.ValidationError{Message: "SAMLResponse parse error"}
	ErrEmptyIDPResponseError       = &errors.ValidationError{Message: "SSAMLResponse form value missing"}
	ErrRequestWaitingForCredentials			  = &errors.ValidationError{Message: "Waiting credentials from IDP"}
)

type SAMLAuthParser interface {
	Parse(infoResponse string) (*saml.Response, error)
}

type SAMLAuthScheme struct {
	BaseConfig  BaseConfig
	Parser      SAMLAuthParser
}

type BaseConfig struct {
	EntityID string
	DisplayName string
	Description string
	PublicCert string
	PrivateKey string
	IdpUrl string
	IdpPublicCert string
	SignRequest bool
	SignedResponse bool
	DeflatEncodedResponse bool
}

func init() {
	auth.RegisterScheme("saml", &SAMLAuthScheme{})
}

func (s SAMLAuthScheme) AppLogout(token string) error {
	return s.Logout(token)
}

// This method loads basic config and returns a copy of the
// config object.
func (s *SAMLAuthScheme) loadConfig() (BaseConfig, error) {
	if s.BaseConfig.EntityID != "" {
		return s.BaseConfig, nil
	}
	if s.Parser == nil {
		s.Parser = s
	}
	var emptyConfig BaseConfig

	publicCert, err := config.GetString("auth:saml:sp-publiccert")
	if err != nil {
		return emptyConfig, err
	}
	privateKey, err := config.GetString("auth:saml:sp-privatekey")
	if err != nil {
		return emptyConfig, err
	}
	idpUrl, err := config.GetString("auth:saml:idp-ssourl")
	if err != nil {
		return emptyConfig, err
	}
	displayName, err := config.GetString("auth:saml:sp-display-name")
	if err != nil {
		displayName = "Tsuru"
		log.Debugf("auth:saml:sp-display-name not found using default: %s", err)

	}
	description, err := config.GetString("auth:saml:sp-description")
	if err != nil {
		description = "Tsuru Platform as a Service software"
		log.Debugf("auth:saml:sp-description not found using default: %s", err)
	}

	idpPublicCert, err := config.GetString("auth:saml:idp-publiccert")
	if err != nil {
		return emptyConfig, err
	}

	entityId, err := config.GetString("auth:saml:sp-entityid")
	if err != nil {
		return emptyConfig, err
	}

	signRequest, err := config.GetBool("auth:saml:sp-sign-request")
	if err != nil {
		return emptyConfig, err
	}

	signedResponse, err := config.GetBool("auth:saml:idp-sign-response")
	if err != nil {
		return emptyConfig, err
	}

	deflatEncodedResponse, err := config.GetBool("auth:saml:idp-deflate-encoding")
	if err != nil {
		deflatEncodedResponse = false
		log.Debugf("auth:saml:idp-deflate-encoding not found using default [false]: %s", err)
	}

	s.BaseConfig = BaseConfig{
		EntityID:     			entityId,
		DisplayName:   			displayName,
		Description:   			description,
		PublicCert:   			publicCert,
		PrivateKey:   			privateKey,
		IdpUrl:		  			idpUrl,
		IdpPublicCert: 			idpPublicCert,
		SignRequest: 			signRequest,
		SignedResponse: 		signedResponse,
		DeflatEncodedResponse: 	deflatEncodedResponse,

	}
	return s.BaseConfig, nil
}

func Metadata() (string, error) {

	scheme := SAMLAuthScheme{}
	sp, err := scheme.createSP()
	if err != nil {
			return "", err
	}
    md, err := sp.GetEntityDescriptor()
    if err != nil {
    	return "", err
    }

    return md, nil
}

func (s *SAMLAuthScheme) Login(params map[string]string) (auth.Token, error) {

	_, err := s.loadConfig()
	if err != nil {
		return nil, err
	}

	//verify for callback requests, param 'callback' indicate callback
	_, ok := params["callback"]
	if ok {
		return nil, s.callback(params)
	}

	requestId, ok := params["request_id"]
	if !ok {
		return nil, ErrMissingRequestIdError
	}

	request ,err := GetRequestById(requestId)
	if err != nil {
		return nil, err
	}

	if request.Authed == false {
		return nil, ErrRequestWaitingForCredentials
	}

	user, err := auth.GetUserByEmail(request.GetEmail())
	if err != nil {
		if err != auth.ErrUserNotFound {
			return nil, err
		}
		registrationEnabled, _ := config.GetBool("auth:user-registration")
		if !registrationEnabled {
			return nil, err
		}

		user = &auth.User{Email: request.GetEmail()}
		err := user.Create()
		if err != nil {
			return nil, err
		}
	}

	token, err := createToken(user)
	if err != nil {
		return nil, err
	}

	request.Remove()

	return token, nil
}

func (s *SAMLAuthScheme) idpHost() string {

	url, err := url.Parse(s.BaseConfig.IdpUrl)
    if err != nil {
           return ""
    }
    hostport := strings.Split(url.Host, ":")
    return hostport[0]
}

func (s *SAMLAuthScheme) callback(params map[string]string) error {

	xml, ok := params["xml"]
	if !ok {
		return ErrMissingFormValueError
	}

	log.Debugf("Data received from identity provider: %s", xml)

	response, err := s.Parser.Parse(xml)
	if err != nil {
		log.Errorf("Got error while parsing IDP data %s: %s",  err)
		return ErrParseResponseError
	}

	sp, err := s.createSP()
	if err != nil {
			return err
	}
	err = ValidateResponse(response,sp)
	if err != nil {
		log.Errorf("Got error while validing IDP data %s: %s",  err)
		if strings.Contains(err.Error(), "assertion has expired") {
		 	return  ErrRequestNotFound
	 	}

		return ErrParseResponseError
	}

	requestId, err := GetRequestIdFromResponse(response)
	if requestId == "" && err == ErrRequestIdNotFound {
		log.Debugf("Request ID %s not found: %s", requestId, err.Error())
		return err
	}

	request ,err := GetRequestById(requestId)
	if err != nil {
		return err
	}

	email, err := GetUserIdentity(response)
	if err != nil {
		return err
	}

	if !validation.ValidateEmail(email) {

		 if strings.Contains(email, "@") {
		 	return &errors.ValidationError{Message: "attribute user identity contains invalid character"}
		 }
		// we need create a unique email for the user
		email = strings.Join([]string{email, "@", s.idpHost()},"")

		if !validation.ValidateEmail(email) {
			return &errors.ValidationError{Message: "could not create valid email with auth:saml:idp-attribute-user-identity"}
		}
	}

	request.SetAuth(true)
	request.SetEmail(email)
	request.Update()

	return nil
}

func (s *SAMLAuthScheme) AppLogin(appName string) (auth.Token, error) {
	nativeScheme := native.NativeScheme{}
	return nativeScheme.AppLogin(appName)
}

func (s *SAMLAuthScheme) Logout(token string) error {
	return deleteToken(token)
}

func (s *SAMLAuthScheme) Auth(token string) (auth.Token, error) {
	return getToken(token)
}

func (s *SAMLAuthScheme) Name() string {
	return "saml"
}

func (s *SAMLAuthScheme) generateAuthnRequest() (*AuthnRequestData, error) {

	sp, err := s.createSP()
	if err != nil {
			return nil, err
	}
	// generate the AuthnRequest and then get a base64 encoded string of the XML
	authnRequest := sp.GetAuthnRequest()

	//b64XML, err := authnRequest.String(authnRequest)
	b64XML, err := authnRequest.CompressedEncodedSignedString(sp.PrivateKeyPath)
	//b64XML, err := authnRequest.EncodedSignedString(sp.PrivateKeyPath)
	if err != nil {
		return nil, err
	}

	url, err := saml.GetAuthnRequestURL(sp.IDPSSOURL, b64XML, sp.AssertionConsumerServiceURL)
	if err != nil {
		return nil, err
	}

	data := AuthnRequestData {
		Base64AuthRequest: b64XML,
		URL:               url,
		ID:				   authnRequest.ID,

	}

	return &data, nil
}

type AuthnRequestData struct {
	Base64AuthRequest string
	URL               string
	ID 				  string
}

func (s *SAMLAuthScheme) createSP() (*saml.ServiceProviderSettings, error){
	conf, err := s.loadConfig()
	if err != nil {
		return nil, err
	}

	authCallbackUrl, _ := config.GetString("host")

	sp := saml.ServiceProviderSettings{
		PublicCertPath: 			 conf.PublicCert,
		PrivateKeyPath: 			 conf.PrivateKey,
		IDPSSOURL:					 conf.IdpUrl,
		DisplayName:   				 conf.DisplayName,
		Description:   				 conf.Description,
		IDPPublicCertPath:   		 conf.IdpPublicCert,
		Id:							 conf.EntityID,
		SPSignRequest:               conf.SignRequest,
		IDPSignResponse:             conf.SignedResponse,
		AssertionConsumerServiceURL: authCallbackUrl+"/auth/saml",
	}
	sp.Init()

	return &sp, nil
}

func (s *SAMLAuthScheme) Info() (auth.SchemeInfo, error) {

	authnRequestData, err := s.generateAuthnRequest()
	if err != nil {
		return nil, err
	}

	r := Request{}
	//persist request in database
	_, err = r.Create(authnRequestData)
	if err != nil {
		return nil, err
	}

	return auth.SchemeInfo{
						"request_id":authnRequestData.ID,
						"saml_request": authnRequestData.Base64AuthRequest,
						"url": authnRequestData.URL,
						"request_timeout": strconv.Itoa(r.GetExpireTimeOut()),

			}, nil
}

func (s *SAMLAuthScheme) Parse(xml string) (*saml.Response, error) {

	if xml == "" {
		return nil, ErrMissingFormValueError
	}

	var response *saml.Response
	var err error
	if !s.BaseConfig.DeflatEncodedResponse {
		response, err = saml.ParseEncodedResponse(xml)
	} else {
		response, err = saml.ParseCompressedEncodedResponse(xml)
	}

	if err != nil || response == nil {
		return nil, fmt.Errorf("unable to parse identity provider data: %s - %s", xml, err)
	}

	sp, err := s.createSP()
	if err != nil {
		return nil, fmt.Errorf("unable to create service provider object: %s", err)
	}

	//If is a encrypted response need decode
	if response.IsEncrypted() {
		err = response.Decrypt(sp.PrivateKeyPath)
		if err != nil {
			return nil, fmt.Errorf("unable to decrypt identity provider data: %s - %s", response.String, err)
		}
	}

	resp, _ := response.String()
	log.Debugf("Data received from identity provider decoded: %s", resp)

	return response, nil
}

func (s *SAMLAuthScheme) Create(user *auth.User) (*auth.User, error) {
	user.Password = ""
	err := user.Create()
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (s *SAMLAuthScheme) Remove(u *auth.User) error {
	err := deleteAllTokens(u.Email)
	if err != nil {
		return err
	}
	return u.Delete()
}<commit_msg>gofmt and remove dead code<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package saml

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"

	saml "github.com/diego-araujo/go-saml"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/auth/native"
	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/validation"
)

var (
	ErrMissingRequestIdError        = &errors.ValidationError{Message: "You must provide RequestID to login"}
	ErrMissingFormValueError        = &errors.ValidationError{Message: "SAMLResponse form value missing"}
	ErrParseResponseError           = &errors.ValidationError{Message: "SAMLResponse parse error"}
	ErrEmptyIDPResponseError        = &errors.ValidationError{Message: "SSAMLResponse form value missing"}
	ErrRequestWaitingForCredentials = &errors.ValidationError{Message: "Waiting credentials from IDP"}
)

type SAMLAuthParser interface {
	Parse(infoResponse string) (*saml.Response, error)
}

type SAMLAuthScheme struct {
	BaseConfig BaseConfig
	Parser     SAMLAuthParser
}

type BaseConfig struct {
	EntityID              string
	DisplayName           string
	Description           string
	PublicCert            string
	PrivateKey            string
	IdpUrl                string
	IdpPublicCert         string
	SignRequest           bool
	SignedResponse        bool
	DeflatEncodedResponse bool
}

func init() {
	auth.RegisterScheme("saml", &SAMLAuthScheme{})
}

func (s SAMLAuthScheme) AppLogout(token string) error {
	return s.Logout(token)
}

// This method loads basic config and returns a copy of the
// config object.
func (s *SAMLAuthScheme) loadConfig() (BaseConfig, error) {
	if s.BaseConfig.EntityID != "" {
		return s.BaseConfig, nil
	}
	if s.Parser == nil {
		s.Parser = s
	}
	var emptyConfig BaseConfig

	publicCert, err := config.GetString("auth:saml:sp-publiccert")
	if err != nil {
		return emptyConfig, err
	}
	privateKey, err := config.GetString("auth:saml:sp-privatekey")
	if err != nil {
		return emptyConfig, err
	}
	idpUrl, err := config.GetString("auth:saml:idp-ssourl")
	if err != nil {
		return emptyConfig, err
	}
	displayName, err := config.GetString("auth:saml:sp-display-name")
	if err != nil {
		displayName = "Tsuru"
		log.Debugf("auth:saml:sp-display-name not found using default: %s", err)

	}
	description, err := config.GetString("auth:saml:sp-description")
	if err != nil {
		description = "Tsuru Platform as a Service software"
		log.Debugf("auth:saml:sp-description not found using default: %s", err)
	}

	idpPublicCert, err := config.GetString("auth:saml:idp-publiccert")
	if err != nil {
		return emptyConfig, err
	}

	entityId, err := config.GetString("auth:saml:sp-entityid")
	if err != nil {
		return emptyConfig, err
	}

	signRequest, err := config.GetBool("auth:saml:sp-sign-request")
	if err != nil {
		return emptyConfig, err
	}

	signedResponse, err := config.GetBool("auth:saml:idp-sign-response")
	if err != nil {
		return emptyConfig, err
	}

	deflatEncodedResponse, err := config.GetBool("auth:saml:idp-deflate-encoding")
	if err != nil {
		deflatEncodedResponse = false
		log.Debugf("auth:saml:idp-deflate-encoding not found using default [false]: %s", err)
	}

	s.BaseConfig = BaseConfig{
		EntityID:              entityId,
		DisplayName:           displayName,
		Description:           description,
		PublicCert:            publicCert,
		PrivateKey:            privateKey,
		IdpUrl:                idpUrl,
		IdpPublicCert:         idpPublicCert,
		SignRequest:           signRequest,
		SignedResponse:        signedResponse,
		DeflatEncodedResponse: deflatEncodedResponse,
	}
	return s.BaseConfig, nil
}

func Metadata() (string, error) {

	scheme := SAMLAuthScheme{}
	sp, err := scheme.createSP()
	if err != nil {
		return "", err
	}
	md, err := sp.GetEntityDescriptor()
	if err != nil {
		return "", err
	}

	return md, nil
}

func (s *SAMLAuthScheme) Login(params map[string]string) (auth.Token, error) {

	_, err := s.loadConfig()
	if err != nil {
		return nil, err
	}

	//verify for callback requests, param 'callback' indicate callback
	_, ok := params["callback"]
	if ok {
		return nil, s.callback(params)
	}

	requestId, ok := params["request_id"]
	if !ok {
		return nil, ErrMissingRequestIdError
	}

	request, err := GetRequestById(requestId)
	if err != nil {
		return nil, err
	}

	if request.Authed == false {
		return nil, ErrRequestWaitingForCredentials
	}

	user, err := auth.GetUserByEmail(request.GetEmail())
	if err != nil {
		if err != auth.ErrUserNotFound {
			return nil, err
		}
		registrationEnabled, _ := config.GetBool("auth:user-registration")
		if !registrationEnabled {
			return nil, err
		}

		user = &auth.User{Email: request.GetEmail()}
		err := user.Create()
		if err != nil {
			return nil, err
		}
	}

	token, err := createToken(user)
	if err != nil {
		return nil, err
	}

	request.Remove()

	return token, nil
}

func (s *SAMLAuthScheme) idpHost() string {

	url, err := url.Parse(s.BaseConfig.IdpUrl)
	if err != nil {
		return ""
	}
	hostport := strings.Split(url.Host, ":")
	return hostport[0]
}

func (s *SAMLAuthScheme) callback(params map[string]string) error {

	xml, ok := params["xml"]
	if !ok {
		return ErrMissingFormValueError
	}

	log.Debugf("Data received from identity provider: %s", xml)

	response, err := s.Parser.Parse(xml)
	if err != nil {
		log.Errorf("Got error while parsing IDP data: %s", err)
		return ErrParseResponseError
	}

	sp, err := s.createSP()
	if err != nil {
		return err
	}
	err = ValidateResponse(response, sp)
	if err != nil {
		log.Errorf("Got error while validing IDP data: %s", err)
		if strings.Contains(err.Error(), "assertion has expired") {
			return ErrRequestNotFound
		}

		return ErrParseResponseError
	}

	requestId, err := GetRequestIdFromResponse(response)
	if requestId == "" && err == ErrRequestIdNotFound {
		log.Debugf("Request ID %s not found: %s", requestId, err.Error())
		return err
	}

	request, err := GetRequestById(requestId)
	if err != nil {
		return err
	}

	email, err := GetUserIdentity(response)
	if err != nil {
		return err
	}

	if !validation.ValidateEmail(email) {

		if strings.Contains(email, "@") {
			return &errors.ValidationError{Message: "attribute user identity contains invalid character"}
		}
		// we need create a unique email for the user
		email = strings.Join([]string{email, "@", s.idpHost()}, "")

		if !validation.ValidateEmail(email) {
			return &errors.ValidationError{Message: "could not create valid email with auth:saml:idp-attribute-user-identity"}
		}
	}

	request.SetAuth(true)
	request.SetEmail(email)
	request.Update()

	return nil
}

func (s *SAMLAuthScheme) AppLogin(appName string) (auth.Token, error) {
	nativeScheme := native.NativeScheme{}
	return nativeScheme.AppLogin(appName)
}

func (s *SAMLAuthScheme) Logout(token string) error {
	return deleteToken(token)
}

func (s *SAMLAuthScheme) Auth(token string) (auth.Token, error) {
	return getToken(token)
}

func (s *SAMLAuthScheme) Name() string {
	return "saml"
}

func (s *SAMLAuthScheme) generateAuthnRequest() (*AuthnRequestData, error) {

	sp, err := s.createSP()
	if err != nil {
		return nil, err
	}
	// generate the AuthnRequest and then get a base64 encoded string of the XML
	authnRequest := sp.GetAuthnRequest()

	//b64XML, err := authnRequest.String(authnRequest)
	b64XML, err := authnRequest.CompressedEncodedSignedString(sp.PrivateKeyPath)
	//b64XML, err := authnRequest.EncodedSignedString(sp.PrivateKeyPath)
	if err != nil {
		return nil, err
	}

	url, err := saml.GetAuthnRequestURL(sp.IDPSSOURL, b64XML, sp.AssertionConsumerServiceURL)
	if err != nil {
		return nil, err
	}

	data := AuthnRequestData{
		Base64AuthRequest: b64XML,
		URL:               url,
		ID:                authnRequest.ID,
	}

	return &data, nil
}

type AuthnRequestData struct {
	Base64AuthRequest string
	URL               string
	ID                string
}

func (s *SAMLAuthScheme) createSP() (*saml.ServiceProviderSettings, error) {
	conf, err := s.loadConfig()
	if err != nil {
		return nil, err
	}

	authCallbackUrl, _ := config.GetString("host")

	sp := saml.ServiceProviderSettings{
		PublicCertPath:              conf.PublicCert,
		PrivateKeyPath:              conf.PrivateKey,
		IDPSSOURL:                   conf.IdpUrl,
		DisplayName:                 conf.DisplayName,
		Description:                 conf.Description,
		IDPPublicCertPath:           conf.IdpPublicCert,
		Id:                          conf.EntityID,
		SPSignRequest:               conf.SignRequest,
		IDPSignResponse:             conf.SignedResponse,
		AssertionConsumerServiceURL: authCallbackUrl + "/auth/saml",
	}
	sp.Init()

	return &sp, nil
}

func (s *SAMLAuthScheme) Info() (auth.SchemeInfo, error) {

	authnRequestData, err := s.generateAuthnRequest()
	if err != nil {
		return nil, err
	}

	r := Request{}
	//persist request in database
	_, err = r.Create(authnRequestData)
	if err != nil {
		return nil, err
	}

	return auth.SchemeInfo{
		"request_id":      authnRequestData.ID,
		"saml_request":    authnRequestData.Base64AuthRequest,
		"url":             authnRequestData.URL,
		"request_timeout": strconv.Itoa(r.GetExpireTimeOut()),
	}, nil
}

func (s *SAMLAuthScheme) Parse(xml string) (*saml.Response, error) {

	if xml == "" {
		return nil, ErrMissingFormValueError
	}

	var response *saml.Response
	var err error
	if !s.BaseConfig.DeflatEncodedResponse {
		response, err = saml.ParseEncodedResponse(xml)
	} else {
		response, err = saml.ParseCompressedEncodedResponse(xml)
	}

	if err != nil || response == nil {
		return nil, fmt.Errorf("unable to parse identity provider data: %s - %s", xml, err)
	}

	sp, err := s.createSP()
	if err != nil {
		return nil, fmt.Errorf("unable to create service provider object: %s", err)
	}

	//If is a encrypted response need decode
	if response.IsEncrypted() {
		err = response.Decrypt(sp.PrivateKeyPath)
		if err != nil {
			return nil, fmt.Errorf("unable to decrypt identity provider data: %s - %s", response.String, err)
		}
	}

	resp, _ := response.String()
	log.Debugf("Data received from identity provider decoded: %s", resp)

	return response, nil
}

func (s *SAMLAuthScheme) Create(user *auth.User) (*auth.User, error) {
	user.Password = ""
	err := user.Create()
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (s *SAMLAuthScheme) Remove(u *auth.User) error {
	err := deleteAllTokens(u.Email)
	if err != nil {
		return err
	}
	return u.Delete()
}
<|endoftext|>


<commit_before>/*

Package gogame is a set of functions and modules designed for writing games. Gogame uses SDL2 internally.

This software is free. It's released under the LGPL license. You can create open source and commercial games with it. See the license for full details.

OPENGL is required. Developer libraries of SDL2, SDL2-image and SDL2-TTF are required also.

*/
package gogame

/*
#cgo pkg-config: sdl2
#include "SDL.h"

int initSDL() {
	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) != 0) {
		SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
		return 1;
	}
	return 0;
}

SDL_Window * newScreen(char *title, int h, int v) {
    return SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, h, v, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}

SDL_Renderer * newRenderer( SDL_Window * screen ) {
    return SDL_CreateRenderer(screen, -1, SDL_RENDERER_PRESENTVSYNC); // SDL_RENDERER_SOFTWARE ); // SDL_RENDERER_ACCELERATED  );
}

*/
import "C"
import "errors"

var screen *C.SDL_Window
var renderer *C.SDL_Renderer

type Color struct {
	R, G, B, A uint8
}

var COLOR_WHITE = &Color{255, 255, 255, 255}
var COLOR_BLACK = &Color{0, 0, 0, 255}
var COLOR_RED = &Color{255, 0, 0, 255}
var COLOR_BLUE = &Color{0, 0, 255, 255}

// Use this function to create a window and a renderer (not visible to user)
func Init(title string, h, v int) error {
	if i := C.initSDL(); i != 0 {
		return errors.New("Error initializing SDL")
	}
	screen = C.newScreen(C.CString(title), C.int(h), C.int(v))
	renderer = C.newRenderer(screen)
	if screen == nil || renderer == nil {
		return errors.New("Error on initializing SDL2")
	}
	return nil
}

// Full Screen mode
func SetFullScreen(fs bool) {
	if fs {
		C.SDL_SetWindowFullscreen(screen, C.SDL_WINDOW_FULLSCREEN_DESKTOP)
	} else {
		C.SDL_SetWindowFullscreen(screen, 0)
	}
}

// Get window size
func GetWindowSize() (int, int) {
	var w, h C.int
	C.SDL_GetWindowSize(screen, &w, &h)
	return int(w), int(h)
}

// Set window size
func SetWindowSize(h, v int) {
	C.SDL_SetWindowSize(screen, C.int(h), C.int(v))
}

// Set a device independent resolution for rendering
func SetLogicalSize(h, v int) {
	C.SDL_RenderSetLogicalSize(renderer, C.int(h), C.int(v))
}

// Destroys renderer and window
func Quit() {
	C.SDL_DestroyRenderer(renderer)
	C.SDL_DestroyWindow(screen)
	C.SDL_Quit()
}

// Clear the current rendering target with black color
func RenderClear() {
	C.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0)
	C.SDL_RenderClear(renderer)
}

// Update the screen with rendering performed
func RenderPresent() {
	C.SDL_RenderPresent(renderer)
}

// Wait specified number of milliseconds before returning
func Delay(s int) {
	C.SDL_Delay(C.Uint32(s))
}

// Draw pixel at position x,y
func DrawPixel(x, y int, color *Color) {
	C.SDL_SetRenderDrawColor(renderer, C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.A))
	C.SDL_RenderDrawPoint(renderer, C.int(x), C.int(y))
}
<commit_msg>Added drawline<commit_after>/*

Package gogame is a set of functions and modules designed for writing games. Gogame uses SDL2 internally.

This software is free. It's released under the LGPL license. You can create open source and commercial games with it. See the license for full details.

OPENGL is required. Developer libraries of SDL2, SDL2-image and SDL2-TTF are required also.

*/
package gogame

/*
#cgo pkg-config: sdl2
#include "SDL.h"

int initSDL() {
	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) != 0) {
		SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
		return 1;
	}
	return 0;
}

SDL_Window * newScreen(char *title, int h, int v) {
    return SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, h, v, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}

SDL_Renderer * newRenderer( SDL_Window * screen ) {
    return SDL_CreateRenderer(screen, -1, SDL_RENDERER_PRESENTVSYNC); // SDL_RENDERER_SOFTWARE ); // SDL_RENDERER_ACCELERATED  );
}

*/
import "C"
import "errors"

var screen *C.SDL_Window
var renderer *C.SDL_Renderer

type Color struct {
	R, G, B, A uint8
}

var COLOR_WHITE = &Color{255, 255, 255, 255}
var COLOR_BLACK = &Color{0, 0, 0, 255}
var COLOR_RED = &Color{255, 0, 0, 255}
var COLOR_BLUE = &Color{0, 0, 255, 255}

// Use this function to create a window and a renderer (not visible to user)
func Init(title string, h, v int) error {
	if i := C.initSDL(); i != 0 {
		return errors.New("Error initializing SDL")
	}
	screen = C.newScreen(C.CString(title), C.int(h), C.int(v))
	renderer = C.newRenderer(screen)
	if screen == nil || renderer == nil {
		return errors.New("Error on initializing SDL2")
	}
	return nil
}

// Full Screen mode
func SetFullScreen(fs bool) {
	if fs {
		C.SDL_SetWindowFullscreen(screen, C.SDL_WINDOW_FULLSCREEN_DESKTOP)
	} else {
		C.SDL_SetWindowFullscreen(screen, 0)
	}
}

// Get window size
func GetWindowSize() (int, int) {
	var w, h C.int
	C.SDL_GetWindowSize(screen, &w, &h)
	return int(w), int(h)
}

// Set window size
func SetWindowSize(h, v int) {
	C.SDL_SetWindowSize(screen, C.int(h), C.int(v))
}

// Set a device independent resolution for rendering
func SetLogicalSize(h, v int) {
	C.SDL_RenderSetLogicalSize(renderer, C.int(h), C.int(v))
}

// Destroys renderer and window
func Quit() {
	C.SDL_DestroyRenderer(renderer)
	C.SDL_DestroyWindow(screen)
	C.SDL_Quit()
}

// Clear the current rendering target with black color
func RenderClear() {
	C.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0)
	C.SDL_RenderClear(renderer)
}

// Update the screen with rendering performed
func RenderPresent() {
	C.SDL_RenderPresent(renderer)
}

// Wait specified number of milliseconds before returning
func Delay(s int) {
	C.SDL_Delay(C.Uint32(s))
}

// Draw pixel at position x,y
func DrawPixel(x, y int, color *Color) {
	C.SDL_SetRenderDrawColor(renderer, C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.A))
	C.SDL_RenderDrawPoint(renderer, C.int(x), C.int(y))
}

// Draw line
func DrawLine(x1, y1, x2, y2 int, color *Color) {
	C.SDL_SetRenderDrawColor(renderer, C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.A))
	C.SDL_RenderDrawLine(renderer, C.int(x1), C.int(y1), C.int(x2), C.int(y2))
}
<|endoftext|>


<commit_before>//
//  sed.go
//  sed
//
// Copyright (c) 2009 Geoffrey Clements
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

package sed

import (
  "flag";
  "fmt";
  "io";
  "os";
  "strings";
  "container/vector";
)

const (
  versionMajor = 0;
  versionMinor = 1;
  versionPoint = 0;
)

var versionString string

func init() {
  versionString = fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionPoint)
}

var show_version = flag.Bool("version", false, "Show version information.")
var show_help = flag.Bool("h", false, "Show help information.")
var quiet = flag.Bool("n", false, "Don't print the pattern space at the end of each script cycle.")
var script = flag.String("e", "", "The script used to process the input file.")
var script_file = flag.String("f", "", "Specify a file to read as the script. Ignored if -e present")
var edit_inplace = flag.Bool("i", false, "This option specifies that files are to be edited in-place. Otherwise output is printed to stdout.")
var line_wrap = flag.Uint("l", 70, "Specify the default line-wrap length for the l command. A length of 0 (zero) means to never wrap long lines. If not specified, it is taken to be 70.")
var unbuffered = flag.Bool("u", false, "Buffer both input and output as minimally as practical. (ignored)")
var treat_files_as_seperate = flag.Bool("s", false, "Treat files as searate entites. Line numbers reset to 1 for each file")

var usageShown bool = false

type Sed struct {
  inputLines              []string;
  commands                *vector.Vector;
  outputFile              *os.File;
  patternSpace, holdSpace string;
  lineNumber              int;
}

func (s *Sed) Init() {
  s.commands = new(vector.Vector);
  s.outputFile = os.Stdout;
  s.patternSpace = "";
  s.holdSpace = "";
}

func usage() {
  // only show usage once.
  if !usageShown {
    usageShown = true;
    fmt.Fprint(os.Stdout, "sed [options] [script] input_file\n\n");
    flag.PrintDefaults();
  }
}

var inputFilename string

func (s *Sed) readInputFile() {
  f, err := os.Open(inputFilename, os.O_RDONLY, 0);
  if err != nil {
    fmt.Fprintf(os.Stderr, "Error opening input file %s\n", inputFilename);
    os.Exit(-1);
  }
  b, err := io.ReadAll(f);
  if err != nil {
    fmt.Fprintf(os.Stderr, "Error reading input file %s\n", inputFilename);
    os.Exit(-1);
  }
  _ = f.Close();
  s.inputLines = strings.Split(string(b), "\n", 0);
}

func (s *Sed) parseScript() (err os.Error) {
  // a script may be a single command or it may be several
  scriptLines := strings.Split(*script, "\n", 0);
  for idx, line := range scriptLines {
    line = strings.TrimSpace(line);
    if strings.HasPrefix(line, "#") || len(line) == 0 {
      // comment
      continue
    }
    // this isn't really right. There may be slashes in the regular expression
    pieces := strings.Split(line, "/", 0);
    c, err := NewCmd(pieces);
    if err != nil {
      fmt.Printf("%v line %d: %s\n", err, idx+1, line);
      os.Exit(-1);
    }
    s.commands.Push(c);
  }
  return nil;
}

func (s *Sed) printPatternSpace() {
  l := len(s.patternSpace);
  if *line_wrap <= 0 || l < int(*line_wrap) {
    fmt.Fprintf(s.outputFile, "%s\n", s.patternSpace)
  } else {
    // print the line in segments
    for i := 0; i < l; i += int(*line_wrap) {
      endOfLine := i + int(*line_wrap);
      if endOfLine > l {
        endOfLine = l
      }
      fmt.Fprintf(s.outputFile, "%s\n", s.patternSpace[i:endOfLine]);
    }
  }
}

func (s *Sed) process() {
  if *treat_files_as_seperate || *edit_inplace {
    s.lineNumber = 0
  }
  for _, s.patternSpace = range s.inputLines {
    // track line number starting with line 1
    s.lineNumber++;
    for c := range s.commands.Iter() {
      // println("cmd: ", c.(fmt.Stringer).String());
      if s.lineMatchesAddress(c.(Cmd).getAddress()) {
        stop, err := c.(Cmd).processLine(s);
        if err != nil {
          fmt.Printf("%v\n", err);
          os.Exit(-1);
        }
        if stop {
          break
        }
      }
    }
    if !*quiet {
      s.printPatternSpace()
    }
  }
}

func Main() {
  s := new(Sed);
  s.Init();
  flag.Parse();
  if *show_version {
    fmt.Fprintf(os.Stdout, "Version: %s (c)2009 Geoffrey Clements All Rights Reserved\n\n", versionString)
  }
  if *show_help {
    usage();
    return;
  }

  // the first parameter may be a script or an input file. This helps us track which
  currentFileParameter := 0;

  // we need a script
  if len(*script) == 0 {
    // no -e so try -f
    if len(*script_file) > 0 {
      f, err := os.Open(*script_file, os.O_RDONLY, 0);
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error opening file %s\n", *script_file);
        os.Exit(-1);
      }
      b, _ := io.ReadAll(f);
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error reading script file %s\n", *script_file);
        os.Exit(-1);
      }
      s := string(b);
      script = &s;
    } else if flag.NArg() > 1 {
      s := flag.Arg(0);
      script = &s;
      // first parameter was the script so move to second parameter
      currentFileParameter++;
    }
  }

  // if script still isn't set we are screwed, exit.
  if len(*script) == 0 {
    fmt.Fprint(os.Stderr, "No script found.\n\n");
    usage();
    os.Exit(-1);
  }

  // parse script
  s.parseScript();

  if currentFileParameter >= flag.NArg() {
    fmt.Fprint(os.Stderr, "No input file specified.\n\n");
    usage();
    os.Exit(-1);
  }

  for ; currentFileParameter < flag.NArg(); currentFileParameter++ {
    inputFilename = flag.Arg(currentFileParameter);
    // actually do the processing
    s.readInputFile();
    if *edit_inplace {
      dir, err := os.Stat(inputFilename);
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error getting information about input file: %s %v\n", err);
        os.Exit(-1);
      }
      f, err := os.Open(inputFilename, os.O_WRONLY|os.O_TRUNC, int(dir.Mode));
      if err != nil {
        fmt.Fprint(os.Stderr, "Error opening input file for inplace editing: %s %v\n", err);
        os.Exit(-1);
      }
      s.outputFile = f;
    }
    s.process();
    if *edit_inplace {
      s.outputFile.Close()
    }
  }
}
<commit_msg>Change ReadAll to ReadFile<commit_after>//
//  sed.go
//  sed
//
// Copyright (c) 2009 Geoffrey Clements
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

package sed

import (
  "flag";
  "fmt";
  "io/ioutil";
  "os";
  "strings";
  "container/vector";
)

const (
  versionMajor = 0;
  versionMinor = 1;
  versionPoint = 0;
)

var versionString string

func init() {
  versionString = fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionPoint)
}

var show_version = flag.Bool("version", false, "Show version information.")
var show_help = flag.Bool("h", false, "Show help information.")
var quiet = flag.Bool("n", false, "Don't print the pattern space at the end of each script cycle.")
var script = flag.String("e", "", "The script used to process the input file.")
var script_file = flag.String("f", "", "Specify a file to read as the script. Ignored if -e present")
var edit_inplace = flag.Bool("i", false, "This option specifies that files are to be edited in-place. Otherwise output is printed to stdout.")
var line_wrap = flag.Uint("l", 70, "Specify the default line-wrap length for the l command. A length of 0 (zero) means to never wrap long lines. If not specified, it is taken to be 70.")
var unbuffered = flag.Bool("u", false, "Buffer both input and output as minimally as practical. (ignored)")
var treat_files_as_seperate = flag.Bool("s", false, "Treat files as searate entites. Line numbers reset to 1 for each file")

var usageShown bool = false

type Sed struct {
  inputLines              []string;
  commands                *vector.Vector;
  outputFile              *os.File;
  patternSpace, holdSpace string;
  lineNumber              int;
}

func (s *Sed) Init() {
  s.commands = new(vector.Vector);
  s.outputFile = os.Stdout;
  s.patternSpace = "";
  s.holdSpace = "";
}

func usage() {
  // only show usage once.
  if !usageShown {
    usageShown = true;
    fmt.Fprint(os.Stdout, "sed [options] [script] input_file\n\n");
    flag.PrintDefaults();
  }
}

var inputFilename string

func (s *Sed) readInputFile() {
  b, err := ioutil.ReadFile(inputFilename);
  if err != nil {
    fmt.Fprintf(os.Stderr, "Error reading input file %s\n", inputFilename);
    os.Exit(-1);
  }
  s.inputLines = strings.Split(string(b), "\n", 0);
}

func (s *Sed) parseScript() (err os.Error) {
  // a script may be a single command or it may be several
  scriptLines := strings.Split(*script, "\n", 0);
  for idx, line := range scriptLines {
    line = strings.TrimSpace(line);
    if strings.HasPrefix(line, "#") || len(line) == 0 {
      // comment
      continue
    }
    // this isn't really right. There may be slashes in the regular expression
    pieces := strings.Split(line, "/", 0);
    c, err := NewCmd(pieces);
    if err != nil {
      fmt.Printf("%v line %d: %s\n", err, idx+1, line);
      os.Exit(-1);
    }
    s.commands.Push(c);
  }
  return nil;
}

func (s *Sed) printPatternSpace() {
  l := len(s.patternSpace);
  if *line_wrap <= 0 || l < int(*line_wrap) {
    fmt.Fprintf(s.outputFile, "%s\n", s.patternSpace)
  } else {
    // print the line in segments
    for i := 0; i < l; i += int(*line_wrap) {
      endOfLine := i + int(*line_wrap);
      if endOfLine > l {
        endOfLine = l
      }
      fmt.Fprintf(s.outputFile, "%s\n", s.patternSpace[i:endOfLine]);
    }
  }
}

func (s *Sed) process() {
  if *treat_files_as_seperate || *edit_inplace {
    s.lineNumber = 0
  }
  for _, s.patternSpace = range s.inputLines {
    // track line number starting with line 1
    s.lineNumber++;
    for c := range s.commands.Iter() {
      // println("cmd: ", c.(fmt.Stringer).String());
      if s.lineMatchesAddress(c.(Cmd).getAddress()) {
        stop, err := c.(Cmd).processLine(s);
        if err != nil {
          fmt.Printf("%v\n", err);
          os.Exit(-1);
        }
        if stop {
          break
        }
      }
    }
    if !*quiet {
      s.printPatternSpace()
    }
  }
}

func Main() {
  s := new(Sed);
  s.Init();
  flag.Parse();
  if *show_version {
    fmt.Fprintf(os.Stdout, "Version: %s (c)2009 Geoffrey Clements All Rights Reserved\n\n", versionString)
  }
  if *show_help {
    usage();
    return;
  }

  // the first parameter may be a script or an input file. This helps us track which
  currentFileParameter := 0;

  // we need a script
  if len(*script) == 0 {
    // no -e so try -f
    if len(*script_file) > 0 {
      b, err := ioutil.ReadFile(*script_file);
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error reading script file %s\n", *script_file);
        os.Exit(-1);
      }
      s := string(b);
      script = &s;
    } else if flag.NArg() > 1 {
      s := flag.Arg(0);
      script = &s;
      // first parameter was the script so move to second parameter
      currentFileParameter++;
    }
  }

  // if script still isn't set we are screwed, exit.
  if len(*script) == 0 {
    fmt.Fprint(os.Stderr, "No script found.\n\n");
    usage();
    os.Exit(-1);
  }

  // parse script
  s.parseScript();

  if currentFileParameter >= flag.NArg() {
    fmt.Fprint(os.Stderr, "No input file specified.\n\n");
    usage();
    os.Exit(-1);
  }

  for ; currentFileParameter < flag.NArg(); currentFileParameter++ {
    inputFilename = flag.Arg(currentFileParameter);
    // actually do the processing
    s.readInputFile();
    if *edit_inplace {
      dir, err := os.Stat(inputFilename);
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error getting information about input file: %s %v\n", err);
        os.Exit(-1);
      }
      f, err := os.Open(inputFilename, os.O_WRONLY|os.O_TRUNC, int(dir.Mode));
      if err != nil {
        fmt.Fprint(os.Stderr, "Error opening input file for inplace editing: %s %v\n", err);
        os.Exit(-1);
      }
      s.outputFile = f;
    }
    s.process();
    if *edit_inplace {
      s.outputFile.Close()
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 SourceGraph, Inc.
// Copyright 2011-2013 Numrotron Inc.
// Use of this source code is governed by an MIT-style license
// that can be found in the LICENSE file.

package ses

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

// Config specifies configuration options and credentials for accessing Amazon SES.
type Config struct {
	// Endpoint is the AWS endpoint to use for requests.
	Endpoint string

	// AccessKeyID is your Amazon AWS access key ID.
	AccessKeyID string

	// SecretAccessKey is your Amazon AWS secret key.
	SecretAccessKey string
}

// EnvConfig takes the access key ID and secret access key values from the environment variables
// $AWS_ACCESS_KEY_ID and $AWS_SECRET_KEY, respectively.
var EnvConfig = Config{
	Endpoint:        "https://email.us-east-1.amazonaws.com",
	AccessKeyID:     os.Getenv("AWS_ACCESS_KEY_ID"),
	SecretAccessKey: os.Getenv("AWS_SECRET_KEY"),
}

// SendEmail sends a plain text email. Note that from must be a verified
// address in the AWS control panel.
func (c *Config) SendEmail(from, to, subject, body string) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendEmail")
	data.Add("Source", from)
	data.Add("Destination.ToAddresses.member.1", to)
	data.Add("Message.Subject.Data", subject)
	data.Add("Message.Body.Text.Data", body)
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

// SendEmailHTML sends a HTML email. Note that from must be a verified address
// in the AWS control panel.
func (c *Config) SendEmailHTML(from, to, subject, bodyText, bodyHTML string) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendEmail")
	data.Add("Source", from)
	data.Add("Destination.ToAddresses.member.1", to)
	data.Add("Message.Subject.Data", subject)
	data.Add("Message.Body.Text.Data", bodyText)
	data.Add("Message.Body.Html.Data", bodyHTML)
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

// SendRawEmail sends a raw email. Note that from must be a verified address
// in the AWS control panel.
func (c *Config) SendRawEmail(raw []byte) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendRawEmail")
	data.Add("RawMessage.Data", base64.StdEncoding.EncodeToString(raw))
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

func authorizationHeader(date, accessKeyID, secretAccessKey string) []string {
	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	return []string{auth}
}

func sesGet(data url.Values, endpoint, accessKeyID, secretAccessKey string) (string, error) {
	urlstr := fmt.Sprintf("%s?%s", endpoint, data.Encode())
	endpointURL, _ := url.Parse(urlstr)
	headers := map[string][]string{}

	now := time.Now().UTC()
	// date format: "Tue, 25 May 2010 21:20:27 +0000"
	date := now.Format("Mon, 02 Jan 2006 15:04:05 -0700")
	headers["Date"] = []string{date}

	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	headers["X-Amzn-Authorization"] = []string{auth}

	req := http.Request{
		URL:        endpointURL,
		Method:     "GET",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
		Header:     headers,
	}

	r, err := http.DefaultClient.Do(&req)
	if err != nil {
		log.Printf("http error: %s", err)
		return "", err
	}

	resultbody, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	if r.StatusCode != 200 {
		log.Printf("error, status = %d", r.StatusCode)

		log.Printf("error response: %s", resultbody)
		return "", errors.New(string(resultbody))
	}

	return string(resultbody), nil
}

func sesPost(data url.Values, endpoint, accessKeyID, secretAccessKey string) (string, error) {
	body := strings.NewReader(data.Encode())
	req, err := http.NewRequest("POST", endpoint, body)
	if err != nil {
		return "", err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	now := time.Now().UTC()
	// date format: "Tue, 25 May 2010 21:20:27 +0000"
	date := now.Format("Mon, 02 Jan 2006 15:04:05 -0700")
	req.Header.Set("Date", date)

	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	req.Header.Set("X-Amzn-Authorization", auth)

	r, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Printf("http error: %s", err)
		return "", err
	}

	resultbody, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	if r.StatusCode != 200 {
		log.Printf("error, status = %d", r.StatusCode)

		log.Printf("error response: %s", resultbody)
		return "", fmt.Errorf("error code %d. response: %s", r.StatusCode, resultbody)
	}

	return string(resultbody), nil
}
<commit_msg>Adds endpoint as env var<commit_after>// Copyright 2013 SourceGraph, Inc.
// Copyright 2011-2013 Numrotron Inc.
// Use of this source code is governed by an MIT-style license
// that can be found in the LICENSE file.

package ses

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

// Config specifies configuration options and credentials for accessing Amazon SES.
type Config struct {
	// Endpoint is the AWS endpoint to use for requests.
	Endpoint string

	// AccessKeyID is your Amazon AWS access key ID.
	AccessKeyID string

	// SecretAccessKey is your Amazon AWS secret key.
	SecretAccessKey string
}

// EnvConfig takes the access key ID and secret access key values from the environment variables
// $AWS_ACCESS_KEY_ID and $AWS_SECRET_KEY, respectively.
var EnvConfig = Config{
	Endpoint:        os.Getenv("AWS_SES_ENDPOINT"),
	AccessKeyID:     os.Getenv("AWS_ACCESS_KEY_ID"),
	SecretAccessKey: os.Getenv("AWS_SECRET_KEY"),
}

// SendEmail sends a plain text email. Note that from must be a verified
// address in the AWS control panel.
func (c *Config) SendEmail(from, to, subject, body string) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendEmail")
	data.Add("Source", from)
	data.Add("Destination.ToAddresses.member.1", to)
	data.Add("Message.Subject.Data", subject)
	data.Add("Message.Body.Text.Data", body)
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

// SendEmailHTML sends a HTML email. Note that from must be a verified address
// in the AWS control panel.
func (c *Config) SendEmailHTML(from, to, subject, bodyText, bodyHTML string) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendEmail")
	data.Add("Source", from)
	data.Add("Destination.ToAddresses.member.1", to)
	data.Add("Message.Subject.Data", subject)
	data.Add("Message.Body.Text.Data", bodyText)
	data.Add("Message.Body.Html.Data", bodyHTML)
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

// SendRawEmail sends a raw email. Note that from must be a verified address
// in the AWS control panel.
func (c *Config) SendRawEmail(raw []byte) (string, error) {
	data := make(url.Values)
	data.Add("Action", "SendRawEmail")
	data.Add("RawMessage.Data", base64.StdEncoding.EncodeToString(raw))
	data.Add("AWSAccessKeyId", c.AccessKeyID)

	return sesPost(data, c.Endpoint, c.AccessKeyID, c.SecretAccessKey)
}

func authorizationHeader(date, accessKeyID, secretAccessKey string) []string {
	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	return []string{auth}
}

func sesGet(data url.Values, endpoint, accessKeyID, secretAccessKey string) (string, error) {
	urlstr := fmt.Sprintf("%s?%s", endpoint, data.Encode())
	endpointURL, _ := url.Parse(urlstr)
	headers := map[string][]string{}

	now := time.Now().UTC()
	// date format: "Tue, 25 May 2010 21:20:27 +0000"
	date := now.Format("Mon, 02 Jan 2006 15:04:05 -0700")
	headers["Date"] = []string{date}

	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	headers["X-Amzn-Authorization"] = []string{auth}

	req := http.Request{
		URL:        endpointURL,
		Method:     "GET",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
		Header:     headers,
	}

	r, err := http.DefaultClient.Do(&req)
	if err != nil {
		log.Printf("http error: %s", err)
		return "", err
	}

	resultbody, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	if r.StatusCode != 200 {
		log.Printf("error, status = %d", r.StatusCode)

		log.Printf("error response: %s", resultbody)
		return "", errors.New(string(resultbody))
	}

	return string(resultbody), nil
}

func sesPost(data url.Values, endpoint, accessKeyID, secretAccessKey string) (string, error) {
	body := strings.NewReader(data.Encode())
	req, err := http.NewRequest("POST", endpoint, body)
	if err != nil {
		return "", err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	now := time.Now().UTC()
	// date format: "Tue, 25 May 2010 21:20:27 +0000"
	date := now.Format("Mon, 02 Jan 2006 15:04:05 -0700")
	req.Header.Set("Date", date)

	h := hmac.New(sha256.New, []uint8(secretAccessKey))
	h.Write([]uint8(date))
	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
	auth := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", accessKeyID, signature)
	req.Header.Set("X-Amzn-Authorization", auth)

	r, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Printf("http error: %s", err)
		return "", err
	}

	resultbody, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	if r.StatusCode != 200 {
		log.Printf("error, status = %d", r.StatusCode)

		log.Printf("error response: %s", resultbody)
		return "", fmt.Errorf("error code %d. response: %s", r.StatusCode, resultbody)
	}

	return string(resultbody), nil
}
<|endoftext|>


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

package ioutil_test

import (
	. "io/ioutil"
	"os"
	"regexp"
	"testing"
)

func TestTempFile(t *testing.T) {
	f, err := TempFile("/_not_exists_", "foo")
	if f != nil || err == nil {
		t.Errorf("TempFile(`/_not_exists_`, `foo`) = %v, %v", f, err)
	}

	dir := os.TempDir()
	f, err = TempFile(dir, "ioutil_test")
	if f == nil || err != nil {
		t.Errorf("TempFile(dir, `ioutil_test`) = %v, %v", f, err)
	}
	if f != nil {
		f.Close()
		os.Remove(f.Name())
		re := regexp.MustCompile("^" + regexp.QuoteMeta(dir) + "/ioutil_test[0-9]+$")
		if !re.MatchString(f.Name()) {
			t.Errorf("TempFile(`"+dir+"`, `ioutil_test`) created bad name %s", f.Name())
		}
	}
}

func TestTempDir(t *testing.T) {
	name, err := TempDir("/_not_exists_", "foo")
	if name != "" || err == nil {
		t.Errorf("TempDir(`/_not_exists_`, `foo`) = %v, %v", name, err)
	}

	dir := os.TempDir()
	name, err = TempDir(dir, "ioutil_test")
	if name == "" || err != nil {
		t.Errorf("TempDir(dir, `ioutil_test`) = %v, %v", name, err)
	}
	if name != "" {
		os.Remove(name)
		re := regexp.MustCompile("^" + regexp.QuoteMeta(dir) + "/ioutil_test[0-9]+$")
		if !re.MatchString(name) {
			t.Errorf("TempDir(`"+dir+"`, `ioutil_test`) created bad name %s", name)
		}
	}
}
<commit_msg>io/ioutil: use filepath.Join, handle trailing / in $TMPDIR<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ioutil_test

import (
	. "io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"testing"
)

func TestTempFile(t *testing.T) {
	f, err := TempFile("/_not_exists_", "foo")
	if f != nil || err == nil {
		t.Errorf("TempFile(`/_not_exists_`, `foo`) = %v, %v", f, err)
	}

	dir := os.TempDir()
	f, err = TempFile(dir, "ioutil_test")
	if f == nil || err != nil {
		t.Errorf("TempFile(dir, `ioutil_test`) = %v, %v", f, err)
	}
	if f != nil {
		f.Close()
		os.Remove(f.Name())
		re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$")
		if !re.MatchString(f.Name()) {
			t.Errorf("TempFile(`"+dir+"`, `ioutil_test`) created bad name %s", f.Name())
		}
	}
}

func TestTempDir(t *testing.T) {
	name, err := TempDir("/_not_exists_", "foo")
	if name != "" || err == nil {
		t.Errorf("TempDir(`/_not_exists_`, `foo`) = %v, %v", name, err)
	}

	dir := os.TempDir()
	name, err = TempDir(dir, "ioutil_test")
	if name == "" || err != nil {
		t.Errorf("TempDir(dir, `ioutil_test`) = %v, %v", name, err)
	}
	if name != "" {
		os.Remove(name)
		re := regexp.MustCompile("^" + regexp.QuoteMeta(filepath.Join(dir, "ioutil_test")) + "[0-9]+$")
		if !re.MatchString(name) {
			t.Errorf("TempDir(`"+dir+"`, `ioutil_test`) created bad name %s", name)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"flag"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port    = flag.String("p", "", "serial port (required: /dev/tty* or COM*)")
	baud    = flag.Int("b", 115200, "baud rate")
	upload  = flag.String("u", "", "upload the specified firmware, then quit")
	expand  = flag.String("e", "", "expand specified file to stdout, then quit")
	verbose = flag.Bool("v", false, "verbose output, for debugging only")
	capture = flag.String("c", "", "a file where captured output is appended")
	timeout = flag.Duration("t", 500 * time.Millisecond, "serial echo timeout")
)

func main() {
	flag.Parse()
	var err error

	// expansion does not use the serial port, it just expands include lines
	if *expand != "" {
		expandFile()
		return
	}

	if *port == "" || flag.NArg() > 0 {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()
	fmt.Println("Connected to:", *port)

	go serialInput() // feed the serIn channel

	// firmware upload uses serial in a different way, needs to quit when done
	if *upload != "" {
		firmwareUpload()
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	// don't interfere with whatever is running, so don't send a return here:
	//outBound <- ""
	//<-progress

	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		doInclude(line[8:])
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	var f *os.File
	if *capture != "" {
		var err error
		opts := os.O_WRONLY | os.O_APPEND | os.O_CREATE
		f, err = os.OpenFile(*capture, opts, 0666)
		check(err)
		defer f.Close()
	}
	for {
		buf := make([]byte, 100)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		if f != nil {
			f.Write(buf[:n])
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(*timeout):
		return nil
	}
}

func serialExchange() {
	depth := 0
	for {
		select {

		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			fmt.Print(string(data))

		case line := <-outBound:
			immediate := depth == 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, false, func(s string) {
					fmt.Print(s) // called to flush pending serial input lines
				})
				fmt.Print(prefix)
				if matched && immediate {
					fmt.Print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, immediate, func(s string) {
				fmt.Print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if immediate || prefix != " " || !matched {
				fmt.Print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched

		case n := <-incLevel:
			depth += n
		}
	}
}

func expectEcho(match string, immed bool, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if immed || len(data) == 0 {
			return string(collected), false
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\\       >>> include %s\n", fname)
	defer func() {
		fmt.Printf("\\       <<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			if len(*expand) == 0 {
				continue // don't send empty or comment-only lines
			}
		}

		parseAndSend(line)
	}
}

func expandFile() {
	go func() {
		for line := range outBound {
			fmt.Println(line)
			progress <- true
		}
	}()

	go func() {
		for range incLevel {
		}
	}()

	for _, fname := range strings.Split(*expand, ",") {
		doInclude(fname)
	}
}

func hexToBin(data []byte) []byte {
	var bin []byte
	for _, line := range strings.Split(string(data), "\n") {
		if strings.HasSuffix(line, "\r") {
			line = line[:len(line)-1]
		}
		if len(line) == 0 {
			continue
		}
		if line[0] != ':' || len(line) < 11 {
			fmt.Println("Not ihex format:", line)
			os.Exit(1)
		}
		bytes, err := hex.DecodeString(line[1:])
		check(err)
		if bytes[3] != 0x00 {
			continue
		}
		offset := (int(bytes[1]) << 8) + int(bytes[2])
		length := bytes[0]
		for offset < len(bin) {
			bin = append(bin, 0xFF)
		}
		bin = append(bin, bytes[4:4+length]...)
	}
	return bin
}

func firmwareUpload() {
	f, err := os.Open(*upload)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	check(err)

	// convert to binary if first bytes look like they are in hex format
	tag := ""
	if len(data) > 11 && data[0] == ':' {
		_, err = hex.DecodeString(string(data[1:11]))
		if err == nil {
			data = hexToBin(data)
			tag = " (converted from Intel HEX)"
		}
	}

	fmt.Printf("        File: %s\n", *upload)
	fmt.Printf("       Count: %d bytes%s\n", len(data), tag)
	fmt.Printf("    Checksum: %08x hex\n", crc32.ChecksumIEEE(data))

	uploadSTM32(data)
}
<commit_msg>allow multiple files in one include line<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"flag"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port    = flag.String("p", "", "serial port (required: /dev/tty* or COM*)")
	baud    = flag.Int("b", 115200, "baud rate")
	upload  = flag.String("u", "", "upload the specified firmware, then quit")
	expand  = flag.String("e", "", "expand specified file to stdout, then quit")
	verbose = flag.Bool("v", false, "verbose output, for debugging only")
	capture = flag.String("c", "", "a file where captured output is appended")
	timeout = flag.Duration("t", 500 * time.Millisecond, "serial echo timeout")
)

func main() {
	flag.Parse()
	var err error

	// expansion does not use the serial port, it just expands include lines
	if *expand != "" {
		expandFile()
		return
	}

	if *port == "" || flag.NArg() > 0 {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()
	fmt.Println("Connected to:", *port)

	go serialInput() // feed the serIn channel

	// firmware upload uses serial in a different way, needs to quit when done
	if *upload != "" {
		firmwareUpload()
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	// don't interfere with whatever is running, so don't send a return here:
	//outBound <- ""
	//<-progress

	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		for _, fname := range strings.Split(line[8:], " ") {
			doInclude(fname)
		}
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	var f *os.File
	if *capture != "" {
		var err error
		opts := os.O_WRONLY | os.O_APPEND | os.O_CREATE
		f, err = os.OpenFile(*capture, opts, 0666)
		check(err)
		defer f.Close()
	}
	for {
		buf := make([]byte, 100)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		if f != nil {
			f.Write(buf[:n])
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(*timeout):
		return nil
	}
}

func serialExchange() {
	depth := 0
	for {
		select {

		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			fmt.Print(string(data))

		case line := <-outBound:
			immediate := depth == 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, false, func(s string) {
					fmt.Print(s) // called to flush pending serial input lines
				})
				fmt.Print(prefix)
				if matched && immediate {
					fmt.Print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, immediate, func(s string) {
				fmt.Print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if immediate || prefix != " " || !matched {
				fmt.Print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched

		case n := <-incLevel:
			depth += n
		}
	}
}

func expectEcho(match string, immed bool, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if immed || len(data) == 0 {
			return string(collected), false
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	if fname == "" {
		return  // silently ignore empty files
	}

	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\\       >>> include %s\n", fname)
	defer func() {
		fmt.Printf("\\       <<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			if len(*expand) == 0 {
				continue // don't send empty or comment-only lines
			}
		}

		parseAndSend(line)
	}
}

func expandFile() {
	go func() {
		for line := range outBound {
			fmt.Println(line)
			progress <- true
		}
	}()

	go func() {
		for range incLevel {
		}
	}()

	for _, fname := range strings.Split(*expand, ",") {
		doInclude(fname)
	}
}

func hexToBin(data []byte) []byte {
	var bin []byte
	for _, line := range strings.Split(string(data), "\n") {
		if strings.HasSuffix(line, "\r") {
			line = line[:len(line)-1]
		}
		if len(line) == 0 {
			continue
		}
		if line[0] != ':' || len(line) < 11 {
			fmt.Println("Not ihex format:", line)
			os.Exit(1)
		}
		bytes, err := hex.DecodeString(line[1:])
		check(err)
		if bytes[3] != 0x00 {
			continue
		}
		offset := (int(bytes[1]) << 8) + int(bytes[2])
		length := bytes[0]
		for offset < len(bin) {
			bin = append(bin, 0xFF)
		}
		bin = append(bin, bytes[4:4+length]...)
	}
	return bin
}

func firmwareUpload() {
	f, err := os.Open(*upload)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	check(err)

	// convert to binary if first bytes look like they are in hex format
	tag := ""
	if len(data) > 11 && data[0] == ':' {
		_, err = hex.DecodeString(string(data[1:11]))
		if err == nil {
			data = hexToBin(data)
			tag = " (converted from Intel HEX)"
		}
	}

	fmt.Printf("        File: %s\n", *upload)
	fmt.Printf("       Count: %d bytes%s\n", len(data), tag)
	fmt.Printf("    Checksum: %08x hex\n", crc32.ChecksumIEEE(data))

	uploadSTM32(data)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"os"
	"os/exec"
)

// via go list -json
type Package struct {
	Standard   bool
	ImportPath string

	Deps []string

	TestImports  []string
	XTestImports []string
}

func listPackages(packages ...string) ([]Package, error) {
	if len(packages) == 0 {
		return []Package{}, nil
	}

	listPackages := exec.Command(
		"go",
		append([]string{"list", "-e", "-json"}, packages...)...,
	)

	listPackages.Stderr = os.Stderr

	packageStream, err := listPackages.StdoutPipe()
	if err != nil {
		return nil, err
	}

	err = listPackages.Start()
	if err != nil {
		return nil, err
	}

	decoder := json.NewDecoder(packageStream)

	pkgs := []Package{}
	for {
		var pkg Package
		err := decoder.Decode(&pkg)
		if err != nil {
			if err == io.EOF {
				break
			}

			return nil, err
		}

		pkgs = append(pkgs, pkg)
	}

	err = listPackages.Wait()
	if err != nil {
		return nil, err
	}

	return pkgs, nil
}

func getAppImports(packages ...string) ([]string, error) {
	appPackages, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	imports := []string{}
	for _, pkg := range appPackages {
		imports = append(imports, pkg.ImportPath)
	}

	return imports, nil
}

func getTestImports(packages ...string) ([]string, error) {
	testPackages, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	imports := []string{}
	imports = append(imports, packages...)

	for _, pkg := range testPackages {
		imports = append(imports, pkg.TestImports...)
		imports = append(imports, pkg.XTestImports...)
	}

	return filterNonStandard(imports...)
}

func getAllDeps(packages ...string) ([]string, error) {
	pkgs, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	allDeps := []string{}
	allDeps = append(allDeps, packages...)

	for _, pkg := range pkgs {
		if pkg.Standard {
			continue
		}

		allDeps = append(allDeps, pkg.Deps...)
	}

	return allDeps, nil
}

func filterNonStandard(packages ...string) ([]string, error) {
	pkgs, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	nonStandard := []string{}
	for _, pkg := range pkgs {
		if pkg.Standard {
			continue
		}

		nonStandard = append(nonStandard, pkg.ImportPath)
	}

	return nonStandard, nil
}
<commit_msg>list in batches to avoid arg list too long<commit_after>package main

import (
	"encoding/json"
	"io"
	"os"
	"os/exec"
)

const packageBatchSize = 100

// via go list -json
type Package struct {
	Standard   bool
	ImportPath string

	Deps []string

	TestImports  []string
	XTestImports []string
}

func listPackages(ps ...string) ([]Package, error) {
	if len(ps) == 0 {
		return []Package{}, nil
	}

	pkgs := map[string]Package{}

	packages := []string{}
	remainingPackages := ps
	for {
		if len(remainingPackages) == 0 {
			break
		}

		if len(remainingPackages) < packageBatchSize {
			packages = remainingPackages
			remainingPackages = nil
		} else {
			packages = remainingPackages[:packageBatchSize]
			remainingPackages = remainingPackages[packageBatchSize:]
		}

		listPackages := exec.Command(
			"go",
			append([]string{"list", "-e", "-json"}, packages...)...,
		)

		listPackages.Stderr = os.Stderr

		packageStream, err := listPackages.StdoutPipe()
		if err != nil {
			return nil, err
		}

		err = listPackages.Start()
		if err != nil {
			return nil, err
		}

		decoder := json.NewDecoder(packageStream)

		for {
			var pkg Package
			err := decoder.Decode(&pkg)
			if err != nil {
				if err == io.EOF {
					break
				}

				return nil, err
			}

			pkgs[pkg.ImportPath] = pkg
		}

		err = listPackages.Wait()
		if err != nil {
			return nil, err
		}
	}

	pkgList := []Package{}
	for _, pkg := range pkgs {
		pkgList = append(pkgList, pkg)
	}

	return pkgList, nil
}

func getAppImports(packages ...string) ([]string, error) {
	appPackages, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	imports := []string{}
	for _, pkg := range appPackages {
		imports = append(imports, pkg.ImportPath)
	}

	return imports, nil
}

func getTestImports(packages ...string) ([]string, error) {
	testPackages, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	imports := []string{}
	imports = append(imports, packages...)

	for _, pkg := range testPackages {
		imports = append(imports, pkg.TestImports...)
		imports = append(imports, pkg.XTestImports...)
	}

	return filterNonStandard(imports...)
}

func getAllDeps(packages ...string) ([]string, error) {
	pkgs, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	allDeps := []string{}
	allDeps = append(allDeps, packages...)

	for _, pkg := range pkgs {
		if pkg.Standard {
			continue
		}

		allDeps = append(allDeps, pkg.Deps...)
	}

	return allDeps, nil
}

func filterNonStandard(packages ...string) ([]string, error) {
	pkgs, err := listPackages(packages...)
	if err != nil {
		return nil, err
	}

	nonStandard := []string{}
	for _, pkg := range pkgs {
		if pkg.Standard {
			continue
		}

		nonStandard = append(nonStandard, pkg.ImportPath)
	}

	return nonStandard, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port   = flag.String("p", "", "serial port (required: /dev/tty*, COM*, etc)")
	baud   = flag.Int("b", 115200, "baud rate")
	upload = flag.String("u", "", "upload the specified firmware, then quit")
)

func main() {
	flag.Parse()
	var err error

	println("Connecting to", *port)
	if *port == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()

	go serialInput() // feed the serIn channel

	if *upload != "" {
		f, err := os.Open(*upload)
		if err != nil {
			fmt.Println(err)
		}
		defer f.Close()

		data, err := ioutil.ReadAll(f)
		check(err)

		println("Uploading", len(data), "bytes")
		uploadSTM32(data)
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	outBound <- ""
	<-progress
	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		doInclude(line[8:])
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	for {
		buf := make([]byte, 100)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(500 * time.Millisecond):
		return nil
	}
}

func serialExchange() {
	includeDepth := 0
	for {
		select {
		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			print(string(data))
		case line := <-outBound:
			including := includeDepth > 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, func(s string) {
					print(s) // called to flush pending serial input lines
				})
				print(prefix)
				if matched && !including {
					print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, func(s string) {
				print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if !including || prefix != " " || !matched {
				print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched
		case n := <-incLevel:
			includeDepth += n
		}
	}
}

func expectEcho(match string, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		if len(data) == 0 {
			return string(collected), false
		}
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\t>>> include %s\n", fname)
	defer func() {
		fmt.Printf("\t<<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			continue // don't send empty or comment-only lines
		}

		parseAndSend(line)
	}
}
<commit_msg>add -e expand option to generate single-file source<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/tarm/serial"
	"gopkg.in/readline.v1"
)

var (
	rlInstance *readline.Instance
	conn       *serial.Port
	serIn      = make(chan []byte)
	outBound   = make(chan string)
	progress   = make(chan bool, 1)
	incLevel   = make(chan int)

	port   = flag.String("p", "", "serial port (required: /dev/tty*, COM*, etc)")
	baud   = flag.Int("b", 115200, "baud rate")
	upload = flag.String("u", "", "upload the specified firmware, then quit")
	expand = flag.String("e", "", "expand specified file to stdout, then quit")
)

func main() {
	flag.Parse()
	var err error

	// expansion does not use the serial port, it just expands include lines
	if *expand != "" {
		expandFile(*expand)
		return
	}

	fmt.Println("Connecting to", *port)
	if *port == "" {
		flag.PrintDefaults()
		os.Exit(1)
	}
	config := serial.Config{Name: *port, Baud: *baud}
	if *upload != "" {
		config.Parity = serial.ParityEven
	}
	conn, err = serial.OpenPort(&config)
	check(err)
	//defer conn.Close()

	go serialInput() // feed the serIn channel

	if *upload != "" {
		f, err := os.Open(*upload)
		if err != nil {
			fmt.Println(err)
		}
		defer f.Close()

		data, err := ioutil.ReadAll(f)
		check(err)

		fmt.Println("Uploading", len(data), "bytes")
		uploadSTM32(data)
		return
	}

	rlInstance, err = readline.NewEx(&readline.Config{
		UniqueEditLine: true,
	})
	check(err)
	defer rlInstance.Close()

	go serialExchange()

	outBound <- ""
	<-progress
	for {
		line, err := rlInstance.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		parseAndSend(line)
	}
}

func parseAndSend(line string) {
	if strings.HasPrefix(line, "include ") {
		doInclude(line[8:])
	} else {
		outBound <- line
		<-progress
	}
}

func check(err error) {
	if err != nil {
		if rlInstance != nil {
			rlInstance.Close()
		}
		log.Fatal(err)
	}
}

func serialInput() {
	for {
		buf := make([]byte, 100)
		n, err := conn.Read(buf)
		check(err)
		if n == 0 {
			close(serIn)
			return
		}
		serIn <- buf[:n]
	}
}

func readWithTimeout() []byte {
	select {
	case data := <-serIn:
		return data
	case <-time.After(500 * time.Millisecond):
		return nil
	}
}

func serialExchange() {
	includeDepth := 0
	for {
		select {
		case data := <-serIn:
			if len(data) == 0 {
				return
			}
			fmt.Print(string(data))
		case line := <-outBound:
			including := includeDepth > 0
			// the task here is to omit "normal" output for included lines,
			// i.e. lines which only generate an echo, a space, and " ok.\n"
			// everything else should be echoed in full, including the input
			if len(line) > 0 {
				serialSend(line)
				prefix, matched := expectEcho(line, func(s string) {
					fmt.Print(s) // called to flush pending serial input lines
				})
				fmt.Print(prefix)
				if matched && !including {
					fmt.Print(line)
					line = ""
				}
			}
			// now that the echo is done, send a CR and wait for the prompt
			serialSend("\r")
			prompt := " ok.\n"
			prefix, matched := expectEcho(prompt, func(s string) {
				fmt.Print(line + s) // show original command first
				line = ""
			})
			if !matched {
				prompt = ""
			}
			if !including || prefix != " " || !matched {
				fmt.Print(line + prefix + prompt)
			}
			// signal to sender that this request has been processed
			progress <- matched
		case n := <-incLevel:
			includeDepth += n
		}
	}
}

func expectEcho(match string, flusher func(string)) (string, bool) {
	var collected []byte
	for {
		data := readWithTimeout()
		if len(data) == 0 {
			return string(collected), false
		}
		collected = append(collected, data...)
		if bytes.HasSuffix(collected, []byte(match)) {
			bytesBefore := len(collected) - len(match)
			return string(collected[:bytesBefore]), true
		}
		if n := bytes.LastIndexByte(collected, '\n'); n >= 0 {
			flusher(string(collected[:n+1]))
			collected = collected[n+1:]
		}
	}
}

func serialSend(data string) {
	_, err := conn.Write([]byte(data))
	check(err)
}

func doInclude(fname string) {
	incLevel <- +1
	defer func() { incLevel <- -1 }()

	lineNum := 0
	fmt.Printf("\\\t>>> include %s\n", fname)
	defer func() {
		fmt.Printf("\\\t<<<<<<<<<<< %s (%d lines)\n", fname, lineNum)
	}()

	f, err := os.Open(fname)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		lineNum++

		s := strings.TrimLeft(line, " ")
		if s == "" || strings.HasPrefix(s, "\\ ") {
			if len(*expand) == 0 {
				continue // don't send empty or comment-only lines
			}
		}

		parseAndSend(line)
	}
}

func expandFile(fname string) {
	go func() {
		for line := range outBound {
			fmt.Println(line)
			progress <- true
		}
	}()

	go func() {
		for range incLevel {}
	}()

	doInclude(fname)
}
<|endoftext|>


<commit_before>package tasks

import (
	"fmt"
	"time"

	"github.com/satori/go.uuid"
)

// Arg represents a single argument passed to invocation fo a task
type Arg struct {
	Type  string      `bson:"type"`
	Value interface{} `bson:"value"`
}

// Headers represents the headers which should be used to direct the task
type Headers map[string]interface{}

// Signature represents a single task invocation
type Signature struct {
	UUID           string
	Name           string
	RoutingKey     string
	ETA            *time.Time
	GroupUUID      string
	GroupTaskCount int
	Args           []Arg
	Headers        Headers
	Immutable      bool
	RetryCount     int
	RetryTimeout   int
	OnSuccess      []*Signature
	OnError        []*Signature
	ChordCallback  *Signature
}

// NewSignature creates a new task signature
func NewSignature(name string, args []Arg) *Signature {
	return &Signature{
		UUID: fmt.Sprintf("task_%v", uuid.NewV4()),
		Name: name,
		Args: args,
	}
}
<commit_msg>Name field added to Arg struct.<commit_after>package tasks

import (
	"fmt"
	"time"

	"github.com/satori/go.uuid"
)

// Arg represents a single argument passed to invocation fo a task
type Arg struct {
	Name  string      `bson:"name"`
	Type  string      `bson:"type"`
	Value interface{} `bson:"value"`
}

// Headers represents the headers which should be used to direct the task
type Headers map[string]interface{}

// Signature represents a single task invocation
type Signature struct {
	UUID           string
	Name           string
	RoutingKey     string
	ETA            *time.Time
	GroupUUID      string
	GroupTaskCount int
	Args           []Arg
	Headers        Headers
	Immutable      bool
	RetryCount     int
	RetryTimeout   int
	OnSuccess      []*Signature
	OnError        []*Signature
	ChordCallback  *Signature
}

// NewSignature creates a new task signature
func NewSignature(name string, args []Arg) *Signature {
	return &Signature{
		UUID: fmt.Sprintf("task_%v", uuid.NewV4()),
		Name: name,
		Args: args,
	}
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"fmt"
	"strings"
	"time"

	acceptance "github.com/cloudfoundry/bosh-bootloader/acceptance-tests"
	"github.com/cloudfoundry/bosh-bootloader/acceptance-tests/actors"
	"github.com/cloudfoundry/bosh-bootloader/testhelpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("lbs test", func() {
	var (
		bbl     actors.BBL
		aws     actors.AWS
		bosh    actors.BOSH
		boshcli actors.BOSHCLI
		state   acceptance.State

		certPath       string
		chainPath      string
		keyPath        string
		otherCertPath  string
		otherChainPath string
		otherKeyPath   string
		vpcName        string
	)

	BeforeEach(func() {
		var err error
		configuration, err := acceptance.LoadConfig()
		Expect(err).NotTo(HaveOccurred())

		bbl = actors.NewBBL(configuration.StateFileDir, pathToBBL, configuration, "lbs-env")
		aws = actors.NewAWS(configuration)
		bosh = actors.NewBOSH()
		boshcli = actors.NewBOSHCLI()
		state = acceptance.NewState(configuration.StateFileDir)

		certPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_CERT)
		Expect(err).NotTo(HaveOccurred())

		chainPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_CHAIN)
		Expect(err).NotTo(HaveOccurred())

		keyPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_KEY)
		Expect(err).NotTo(HaveOccurred())

		otherCertPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_CERT)
		Expect(err).NotTo(HaveOccurred())

		otherKeyPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_KEY)
		Expect(err).NotTo(HaveOccurred())

		otherChainPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_CHAIN)
		Expect(err).NotTo(HaveOccurred())

		session := bbl.Up("--name", bbl.PredefinedEnvID(), "--no-director")
		Eventually(session, 40*time.Minute).Should(gexec.Exit(0))

		vpcName = fmt.Sprintf("%s-vpc", bbl.PredefinedEnvID())
	})

	AfterEach(func() {
		session := bbl.Destroy()
		Eventually(session, 10*time.Minute).Should(gexec.Exit())
	})

	It("creates, updates and deletes a concourse LB with the specified cert and key", func() {
		By("verifying there are no load balancers", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})

		By("creating a concourse lb", func() {
			session := bbl.CreateLB("concourse", certPath, keyPath, chainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(1))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(MatchRegexp(".*-concourse-lb")))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(testhelpers.BBL_CERT)))
		})

		By("verifying that the bbl lbs output contains the concourse lb", func() {
			session := bbl.LBs()
			Eventually(session).Should(gexec.Exit(0))

			stdout := string(session.Out.Contents())
			Expect(stdout).To(MatchRegexp("Concourse LB: .*"))
		})

		By("updating the certs of the lb", func() {
			session := bbl.UpdateLB(otherCertPath, otherKeyPath, otherChainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(1))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(MatchRegexp(".*-concourse-lb")))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(string(testhelpers.OTHER_BBL_CERT))))
		})

		By("deleting lbs", func() {
			session := bbl.DeleteLBs()
			Eventually(session, 15*time.Minute).Should(gexec.Exit(0))
		})

		By("confirming that the concourse lb does not exist", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})
	})

	It("creates, updates and deletes cf LBs with the specified cert and key", func() {
		By("verifying there are no load balancers", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})

		By("creating cf lbs", func() {
			session := bbl.CreateLB("cf", certPath, keyPath, chainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(3))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(
				MatchRegexp(".*-cf-router-lb"),
				MatchRegexp(".*-cf-ssh-lb"),
				MatchRegexp(".*-cf-tcp-lb"),
			))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(testhelpers.BBL_CERT)))
		})

		By("verifying that the bbl lbs output contains the cf lbs", func() {
			session := bbl.LBs()
			Eventually(session).Should(gexec.Exit(0))

			stdout := string(session.Out.Contents())
			Expect(stdout).To(MatchRegexp("CF Router LB: .*"))
			Expect(stdout).To(MatchRegexp("CF SSH Proxy LB: .*"))
			Expect(stdout).To(MatchRegexp("CF TCP Router LB: .*"))
		})

		By("updating the certs of the cf router lb", func() {
			session := bbl.UpdateLB(otherCertPath, otherKeyPath, otherChainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(3))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(
				MatchRegexp(".*-cf-router-lb"),
				MatchRegexp(".*-cf-ssh-lb"),
				MatchRegexp(".*-cf-tcp-lb"),
			))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(string(testhelpers.OTHER_BBL_CERT))))
		})

		By("deleting lbs", func() {
			session := bbl.DeleteLBs()
			Eventually(session, 15*time.Minute).Should(gexec.Exit(0))
		})

		By("confirming that the cf lbs do not exist", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})
	})
})
<commit_msg>Remove concourse-lbs coverage from aws lbs acceptance test.<commit_after>package acceptance_test

import (
	"fmt"
	"strings"
	"time"

	acceptance "github.com/cloudfoundry/bosh-bootloader/acceptance-tests"
	"github.com/cloudfoundry/bosh-bootloader/acceptance-tests/actors"
	"github.com/cloudfoundry/bosh-bootloader/testhelpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("lbs test", func() {
	var (
		bbl   actors.BBL
		aws   actors.AWS
		state acceptance.State

		certPath       string
		chainPath      string
		keyPath        string
		otherCertPath  string
		otherChainPath string
		otherKeyPath   string
		vpcName        string
	)

	BeforeEach(func() {
		var err error
		configuration, err := acceptance.LoadConfig()
		Expect(err).NotTo(HaveOccurred())

		bbl = actors.NewBBL(configuration.StateFileDir, pathToBBL, configuration, "lbs-env")
		aws = actors.NewAWS(configuration)
		state = acceptance.NewState(configuration.StateFileDir)

		certPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_CERT)
		Expect(err).NotTo(HaveOccurred())

		chainPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_CHAIN)
		Expect(err).NotTo(HaveOccurred())

		keyPath, err = testhelpers.WriteContentsToTempFile(testhelpers.BBL_KEY)
		Expect(err).NotTo(HaveOccurred())

		otherCertPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_CERT)
		Expect(err).NotTo(HaveOccurred())

		otherKeyPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_KEY)
		Expect(err).NotTo(HaveOccurred())

		otherChainPath, err = testhelpers.WriteContentsToTempFile(testhelpers.OTHER_BBL_CHAIN)
		Expect(err).NotTo(HaveOccurred())

		session := bbl.Up("--name", bbl.PredefinedEnvID(), "--no-director")
		Eventually(session, 40*time.Minute).Should(gexec.Exit(0))

		vpcName = fmt.Sprintf("%s-vpc", bbl.PredefinedEnvID())
	})

	AfterEach(func() {
		session := bbl.Destroy()
		Eventually(session, 10*time.Minute).Should(gexec.Exit())
	})

	It("creates, updates and deletes cf LBs with the specified cert and key", func() {
		By("verifying there are no load balancers", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})

		By("creating cf lbs", func() {
			session := bbl.CreateLB("cf", certPath, keyPath, chainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(3))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(
				MatchRegexp(".*-cf-router-lb"),
				MatchRegexp(".*-cf-ssh-lb"),
				MatchRegexp(".*-cf-tcp-lb"),
			))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(testhelpers.BBL_CERT)))
		})

		By("verifying that the bbl lbs output contains the cf lbs", func() {
			session := bbl.LBs()
			Eventually(session).Should(gexec.Exit(0))

			stdout := string(session.Out.Contents())
			Expect(stdout).To(MatchRegexp("CF Router LB: .*"))
			Expect(stdout).To(MatchRegexp("CF SSH Proxy LB: .*"))
			Expect(stdout).To(MatchRegexp("CF TCP Router LB: .*"))
		})

		By("updating the certs of the cf router lb", func() {
			session := bbl.UpdateLB(otherCertPath, otherKeyPath, otherChainPath)
			Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

			Expect(aws.LoadBalancers(vpcName)).To(HaveLen(3))
			Expect(aws.LoadBalancers(vpcName)).To(ConsistOf(
				MatchRegexp(".*-cf-router-lb"),
				MatchRegexp(".*-cf-ssh-lb"),
				MatchRegexp(".*-cf-tcp-lb"),
			))

			certificateName := aws.GetSSLCertificateNameFromLBs(bbl.PredefinedEnvID())
			Expect(strings.TrimSpace(aws.DescribeCertificate(certificateName).Body)).To(Equal(strings.TrimSpace(string(testhelpers.OTHER_BBL_CERT))))
		})

		By("deleting lbs", func() {
			session := bbl.DeleteLBs()
			Eventually(session, 15*time.Minute).Should(gexec.Exit(0))
		})

		By("confirming that the cf lbs do not exist", func() {
			Expect(aws.LoadBalancers(vpcName)).To(BeEmpty())
		})
	})
})
<|endoftext|>


<commit_before>package downloaders

import (
	"strconv"

	"code.cloudfoundry.org/lager"

	"github.com/cavaliercoder/grab"
	"github.com/flavioribeiro/gonfig"
	"github.com/snickers/snickers/db"
)

// HTTPDownload function downloads sources using
// http protocol.
func HTTPDownload(logger lager.Logger, config gonfig.Gonfig, dbInstance db.Storage, jobID string) error {
	log := logger.Session("http-download")
	log.Info("start", lager.Data{"job": jobID})
	defer log.Info("finished")

	job, err := dbInstance.RetrieveJob(jobID)
	if err != nil {
		return err
	}

	respch, err := grab.GetAsync(job.LocalSource, job.Source)
	if err != nil {
		return nil
	}

	resp := <-respch
	for !resp.IsComplete() {
		job, err = dbInstance.RetrieveJob(jobID)
		if err != nil {
			return err
		}

		percentage := strconv.FormatInt(int64(resp.BytesTransferred()*100/resp.Size), 10)
		if job.Progress != percentage {
			job.Progress = percentage + "%"
			dbInstance.UpdateJob(job.ID, job)
		}
	}

	if resp.Error != nil {
		return resp.Error
	}

	return nil
}
<commit_msg>Fix: code refactor<commit_after>package downloaders

import (
	"strconv"

	"code.cloudfoundry.org/lager"

	"github.com/cavaliercoder/grab"
	"github.com/flavioribeiro/gonfig"
	"github.com/snickers/snickers/db"
)

// HTTPDownload function downloads sources using
// http protocol.
func HTTPDownload(logger lager.Logger, config gonfig.Gonfig, dbInstance db.Storage, jobID string) error {
	log := logger.Session("http-download")
	log.Info("start", lager.Data{"job": jobID})
	defer log.Info("finished")

	job, err := dbInstance.RetrieveJob(jobID)
	if err != nil {
		return err
	}

	client := grab.NewClient()
	req, err := grab.NewRequest(job.LocalSource, job.Source)
	if err != nil {
		return nil
	}
	resp := client.Do(req)
	if err := resp.Err(); err != nil {
		return nil
	}

	for !resp.IsComplete() {
		job, err = dbInstance.RetrieveJob(jobID)
		if err != nil {
			return err
		}

		percentage := strconv.FormatInt(int64(resp.BytesComplete()*100/resp.Size), 10)
		if job.Progress != percentage {
			job.Progress = percentage + "%"
			dbInstance.UpdateJob(job.ID, job)
		}
	}

	if resp.Err() != nil {
		return resp.Err()
	}

	return nil
}
<|endoftext|>