<commit_before>// Copyright 2016 Google, Inc.
//
// 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 cli

import (
	"context"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"strings"

	"github.com/GoogleCloudPlatform/docker-credential-gcr/config"
	"github.com/GoogleCloudPlatform/docker-credential-gcr/store"
	"github.com/GoogleCloudPlatform/docker-credential-gcr/util"
	cliconfig "github.com/docker/cli/cli/config"
	"github.com/docker/cli/cli/config/configfile"
	"github.com/docker/docker/api/types"
	"github.com/google/subcommands"
)

type dockerConfigCmd struct {
	cmd
	// overwrite any previously configured credential store and/or credentials
	overwrite bool
}

// see https://github.com/docker/docker/blob/master/cliconfig/credentials/native_store.go
const credHelperPrefix = "docker-credential-"

// NewDockerConfigSubcommand returns a subcommands.Command which configures
// the docker client to use this credential helper
func NewDockerConfigSubcommand() subcommands.Command {
	return &dockerConfigCmd{
		cmd{
			name:     "configure-docker",
			synopsis: fmt.Sprintf("configures the Docker client to use %s", os.Args[0]),
		},
		false,
	}
}

func (c *dockerConfigCmd) SetFlags(fs *flag.FlagSet) {
	fs.BoolVar(&c.overwrite, "overwrite", false, "overwrite any previously configured credential store and/or credentials")
}

func (c *dockerConfigCmd) Execute(context.Context, *flag.FlagSet, ...interface{}) subcommands.ExitStatus {
	binaryName := filepath.Base(os.Args[0])
	if !strings.HasPrefix(binaryName, credHelperPrefix) {
		printErrorln("Binary name must be prefixed with '%s': %s", credHelperPrefix, binaryName)
		return subcommands.ExitFailure
	}

	// the Docker client can only use binaries on the $PATH
	if _, err := exec.LookPath(binaryName); err != nil {
		printErrorln("'%s' must exist on your PATH", binaryName)
		return subcommands.ExitFailure
	}

	dockerConfig, err := cliconfig.Load("")
	if err != nil {
		printErrorln("Unable to load docker config: %v", err)
		return subcommands.ExitFailure
	}

	// 'credsStore' and 'credHelpers' take the suffix of the credential helper
	// binary.
	credHelperSuffix := binaryName[len(credHelperPrefix):]

	major, minor, _, _, err := util.DockerClientVersion()
	if err != nil {
		fmt.Printf("WARNING: Unable to determine Docker version: %v\n", err)
		fmt.Printf("Configuring %s as a registry-specific helper. This is only supported by Docker client versions 1.13+\n", binaryName)
		return setConfig(dockerConfig, credHelperSuffix)
	} else if credHelpersSupported(major, minor) {
		// If we can act as a registry-specific credential helper, do so...
		return setConfig(dockerConfig, credHelperSuffix)
	} else if credsStoreSupported(major, minor) {
		// Else, attempt to act as the cred store...
		return c.setLegacyConfig(dockerConfig, credHelperSuffix)
	}

	// Netiher cred helper nor cred store is supported by the detected docker
	// version.
	fmt.Fprintln(os.Stderr, "ERROR: Docker client version 1.10+ required")
	return subcommands.ExitFailure
}

// credHelpersSupported returns true if the installed version of Docker supports
// credential helpers (1.13+), error if Docker is not installed or there was an
// error determining the version.
func credHelpersSupported(majorVersion, minorVersion int) bool {
	return majorVersion >= 17 || (majorVersion == 1 && minorVersion >= 13)
}

// credsStoreSupported returns true if the installed version of Docker supports
// credential stores (1.11+), error if Docker is not installed or there was an
// error determining the version.
func credsStoreSupported(majorVersion, minorVersion int) bool {
	return majorVersion >= 17 || (majorVersion == 1 && minorVersion >= 11)
}

// Configure Docker to use the credential helper for GCR's registries only.
// Defining additional 'auths' entries is unnecessary in versions which
// support registry-specific credential helpers.
func setConfig(dockerConfig *configfile.ConfigFile, helperSuffix string) subcommands.ExitStatus {
	// We always overwrite since there's no way that we can accidentally
	// disable other credentials as a registry-specific credential helper.
	if dockerConfig.CredentialHelpers == nil {
		dockerConfig.CredentialHelpers = map[string]string{}
	}

	for registry := range config.SupportedGCRRegistries {
		dockerConfig.CredentialHelpers[registry] = helperSuffix
	}

	if err := dockerConfig.Save(); err != nil {
		printErrorln("Unable to save docker config: %v", err)
		return subcommands.ExitFailure
	}

	fmt.Printf("%s configured to use this credential helper for GCR registries\n", dockerConfig.Filename)
	return subcommands.ExitSuccess
}

// Configure Docker to use the credential helper as the default credential
// store. Also add 'auths' entries to the config to support versions where the
// docker config was the source of truth for the set of stored credentials.
func (c *dockerConfigCmd) setLegacyConfig(dockerConfig *configfile.ConfigFile, helperSuffix string) subcommands.ExitStatus {
	// Only proceed if the creds store is empty or we're allowed to overwrite.
	// Replacing a cred store effectivley makes any previously stored
	// credentials unreachable.
	otherCredStoreConfigured := dockerConfig.CredentialsStore != helperSuffix && dockerConfig.CredentialsStore != ""
	dcgcrConfiguredAsCredStore := dockerConfig.CredentialsStore == helperSuffix
	credentialsStored := len(dockerConfig.AuthConfigs) > 0
	if otherCredStoreConfigured && !c.overwrite {
		// If another credential store is configured, demand explicit
		// overwrite permissions.
		printErrorln("Docker is currently configured to use '%s%s' as its credential store. Please retry with --overwrite. This will render any previously store credentials unaccessible.", credHelperPrefix, dockerConfig.CredentialsStore)
		return subcommands.ExitFailure
	} else if credentialsStored && !dcgcrConfiguredAsCredStore && !c.overwrite {
		// If there are credentials stored somewhere other than this credential
		// helper, demand explicit overwrite permissions.
		printErrorln("%d credentials are currently stored which would be overwritten. Retry with --overwrite.", len(dockerConfig.AuthConfigs))
		return subcommands.ExitFailure
	}

	// Populate the AuthConfigs portion of the config.
	// This allows 'docker build' work on Docker client versions 1.11 and 1.12,
	// where AuthConfigs was
	s, err := store.DefaultGCRCredStore()
	if err != nil {
		printErrorln("Unable to read credentialStore: %v", err)
	}
	authsModified := setAuthConfigs(dockerConfig, s)

	// Optimization. Don't modify the dockerConfig if we're already fully configured.
	if authsModified || dockerConfig.CredentialsStore != helperSuffix {
		// Overwrite the existing set of AuthConfigs since they aren't visible anymore, anyway.
		dockerConfig.CredentialsStore = helperSuffix
		if err = dockerConfig.Save(); err != nil {
			printErrorln("Unable to save docker config: %v", err)
			return subcommands.ExitFailure
		}
	}

	fmt.Printf("%s successfully configured\n", dockerConfig.Filename)
	if c.overwrite {
		fmt.Println("Any previously stored credentials have been overwritten.")
	}
	return subcommands.ExitSuccess
}

// Ensures that the AuthConfigs in the given ConfigFile are exactly the set
// of config.SupportedGCRRegistries with the https scheme plus any 3p creds
// we have stored.
// Returns true if the ConfigFile was modified, false otherwise.
func setAuthConfigs(dockerConfig *configfile.ConfigFile, s store.GCRCredStore) bool {
	newAuthconfigs := make(map[string]types.AuthConfig)
	for registry := range config.SupportedGCRRegistries {
		// 'auths' members take a scheme
		registry = "https://" + registry
		newAuthconfigs[registry] = types.AuthConfig{}
	}

	creds, err := s.AllThirdPartyCreds()
	// Only add 3p creds if we can retrieve them, but FUBAR cred store is OK
	if err == nil {
		for registry := range creds {
			newAuthconfigs[registry] = types.AuthConfig{}
		}
	}

	if !reflect.DeepEqual(newAuthconfigs, dockerConfig.AuthConfigs) {
		dockerConfig.AuthConfigs = newAuthconfigs
		return true
	}

	return false
}

func printErrorln(fmtString string, v ...interface{}) {
	fmt.Fprintf(os.Stderr, "ERROR: "+fmtString+"\n", v...)
}
<commit_msg>Update configure-docker.go<commit_after>// Copyright 2016 Google, Inc.
//
// 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 cli

import (
	"context"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"reflect"
	"strings"

	"github.com/GoogleCloudPlatform/docker-credential-gcr/config"
	"github.com/GoogleCloudPlatform/docker-credential-gcr/store"
	"github.com/GoogleCloudPlatform/docker-credential-gcr/util"
	cliconfig "github.com/docker/cli/cli/config"
	"github.com/docker/cli/cli/config/configfile"
	"github.com/docker/docker/api/types"
	"github.com/google/subcommands"
)

type dockerConfigCmd struct {
	cmd
	// overwrite any previously configured credential store and/or credentials
	overwrite bool
}

// see https://github.com/docker/docker/blob/master/cliconfig/credentials/native_store.go
const credHelperPrefix = "docker-credential-"

// NewDockerConfigSubcommand returns a subcommands.Command which configures
// the docker client to use this credential helper
func NewDockerConfigSubcommand() subcommands.Command {
	return &dockerConfigCmd{
		cmd{
			name:     "configure-docker",
			synopsis: fmt.Sprintf("configures the Docker client to use %s", os.Args[0]),
		},
		false,
	}
}

func (c *dockerConfigCmd) SetFlags(fs *flag.FlagSet) {
	fs.BoolVar(&c.overwrite, "overwrite", false, "overwrite any previously configured credential store and/or credentials")
}

func (c *dockerConfigCmd) Execute(context.Context, *flag.FlagSet, ...interface{}) subcommands.ExitStatus {
	binaryName := filepath.Base(os.Args[0])
	if !strings.HasPrefix(binaryName, credHelperPrefix) {
		printErrorln("Binary name must be prefixed with '%s': %s", credHelperPrefix, binaryName)
		return subcommands.ExitFailure
	}

	// the Docker client can only use binaries on the $PATH
	if _, err := exec.LookPath(binaryName); err != nil {
		printErrorln("'%s' must exist on your PATH", binaryName)
		return subcommands.ExitFailure
	}

	dockerConfig, err := cliconfig.Load("")
	if err != nil {
		printErrorln("Unable to load docker config: %v", err)
		return subcommands.ExitFailure
	}

	// 'credsStore' and 'credHelpers' take the suffix of the credential helper
	// binary.
	credHelperSuffix := binaryName[len(credHelperPrefix):]

	major, minor, _, _, err := util.DockerClientVersion()
	if err != nil {
		fmt.Printf("WARNING: Unable to determine Docker version: %v\n", err)
		fmt.Printf("Configuring %s as a registry-specific helper. This is only supported by Docker client versions 1.13+\n", binaryName)
		return setConfig(dockerConfig, credHelperSuffix)
	} else if credHelpersSupported(major, minor) {
		// If we can act as a registry-specific credential helper, do so...
		return setConfig(dockerConfig, credHelperSuffix)
	} else if credsStoreSupported(major, minor) {
		// Else, attempt to act as the cred store...
		return c.setLegacyConfig(dockerConfig, credHelperSuffix)
	}

	// Netiher cred helper nor cred store is supported by the detected docker
	// version.
	fmt.Fprintln(os.Stderr, "ERROR: Docker client version 1.10+ required")
	return subcommands.ExitFailure
}

// credHelpersSupported returns true if the installed version of Docker supports
// credential helpers (1.13+), error if Docker is not installed or there was an
// error determining the version.
func credHelpersSupported(majorVersion, minorVersion int) bool {
	return majorVersion >= 17 || (majorVersion == 1 && minorVersion >= 13)
}

// credsStoreSupported returns true if the installed version of Docker supports
// credential stores (1.11+), error if Docker is not installed or there was an
// error determining the version.
func credsStoreSupported(majorVersion, minorVersion int) bool {
	return majorVersion >= 17 || (majorVersion == 1 && minorVersion >= 11)
}

// Configure Docker to use the credential helper for GCR's registries only.
// Defining additional 'auths' entries is unnecessary in versions which
// support registry-specific credential helpers.
func setConfig(dockerConfig *configfile.ConfigFile, helperSuffix string) subcommands.ExitStatus {
	// We always overwrite since there's no way that we can accidentally
	// disable other credentials as a registry-specific credential helper.
	if dockerConfig.CredentialHelpers == nil {
		dockerConfig.CredentialHelpers = map[string]string{}
	}

	for registry := range config.SupportedGCRRegistries {
		dockerConfig.CredentialHelpers[registry] = helperSuffix
	}

	if err := dockerConfig.Save(); err != nil {
		printErrorln("Unable to save docker config: %v", err)
		return subcommands.ExitFailure
	}

	fmt.Printf("%s configured to use this credential helper for GCR registries\n", dockerConfig.Filename)
	return subcommands.ExitSuccess
}

// Configure Docker to use the credential helper as the default credential
// store. Also add 'auths' entries to the config to support versions where the
// docker config was the source of truth for the set of stored credentials.
func (c *dockerConfigCmd) setLegacyConfig(dockerConfig *configfile.ConfigFile, helperSuffix string) subcommands.ExitStatus {
	// Only proceed if the creds store is empty or we're allowed to overwrite.
	// Replacing a cred store effectively makes any previously stored
	// credentials unreachable.
	otherCredStoreConfigured := dockerConfig.CredentialsStore != helperSuffix && dockerConfig.CredentialsStore != ""
	dcgcrConfiguredAsCredStore := dockerConfig.CredentialsStore == helperSuffix
	credentialsStored := len(dockerConfig.AuthConfigs) > 0
	if otherCredStoreConfigured && !c.overwrite {
		// If another credential store is configured, demand explicit
		// overwrite permissions.
		printErrorln("Docker is currently configured to use '%s%s' as its credential store. Please retry with --overwrite. This will render any previously store credentials unaccessible.", credHelperPrefix, dockerConfig.CredentialsStore)
		return subcommands.ExitFailure
	} else if credentialsStored && !dcgcrConfiguredAsCredStore && !c.overwrite {
		// If there are credentials stored somewhere other than this credential
		// helper, demand explicit overwrite permissions.
		printErrorln("%d credentials are currently stored which would be overwritten. Retry with --overwrite.", len(dockerConfig.AuthConfigs))
		return subcommands.ExitFailure
	}

	// Populate the AuthConfigs portion of the config.
	// This allows 'docker build' work on Docker client versions 1.11 and 1.12,
	// where AuthConfigs was
	s, err := store.DefaultGCRCredStore()
	if err != nil {
		printErrorln("Unable to read credentialStore: %v", err)
	}
	authsModified := setAuthConfigs(dockerConfig, s)

	// Optimization. Don't modify the dockerConfig if we're already fully configured.
	if authsModified || dockerConfig.CredentialsStore != helperSuffix {
		// Overwrite the existing set of AuthConfigs since they aren't visible anymore, anyway.
		dockerConfig.CredentialsStore = helperSuffix
		if err = dockerConfig.Save(); err != nil {
			printErrorln("Unable to save docker config: %v", err)
			return subcommands.ExitFailure
		}
	}

	fmt.Printf("%s successfully configured\n", dockerConfig.Filename)
	if c.overwrite {
		fmt.Println("Any previously stored credentials have been overwritten.")
	}
	return subcommands.ExitSuccess
}

// Ensures that the AuthConfigs in the given ConfigFile are exactly the set
// of config.SupportedGCRRegistries with the https scheme plus any 3p creds
// we have stored.
// Returns true if the ConfigFile was modified, false otherwise.
func setAuthConfigs(dockerConfig *configfile.ConfigFile, s store.GCRCredStore) bool {
	newAuthconfigs := make(map[string]types.AuthConfig)
	for registry := range config.SupportedGCRRegistries {
		// 'auths' members take a scheme
		registry = "https://" + registry
		newAuthconfigs[registry] = types.AuthConfig{}
	}

	creds, err := s.AllThirdPartyCreds()
	// Only add 3p creds if we can retrieve them, but FUBAR cred store is OK
	if err == nil {
		for registry := range creds {
			newAuthconfigs[registry] = types.AuthConfig{}
		}
	}

	if !reflect.DeepEqual(newAuthconfigs, dockerConfig.AuthConfigs) {
		dockerConfig.AuthConfigs = newAuthconfigs
		return true
	}

	return false
}

func printErrorln(fmtString string, v ...interface{}) {
	fmt.Fprintf(os.Stderr, "ERROR: "+fmtString+"\n", v...)
}
<|endoftext|>


<commit_before>package client

import (
	"github.com/godbus/dbus"
	"github.com/muka/device-manager/objects"
	"github.com/muka/device-manager/util"
	"log"
)

// NewDeviceManager create a new DeviceManager client
func NewDeviceManager() *DeviceManager {
	d := new(DeviceManager)
	d.client = NewClient(objects.DeviceManagerInterface, objects.DeviceManagerPath)
	d.logger = util.Logger()
	return d
}

// DeviceManager client
type DeviceManager struct {
	client *Client
	logger *log.Logger
}

// Create a new device
func (d *DeviceManager) Create(dev objects.DeviceDefinition) (dbus.ObjectPath, error) {
	var s dbus.ObjectPath
	err := d.client.Call("Create", 0, dev).Store(&s)
	util.CheckError(err)
	d.logger.Printf("Created device at path\n %v\n", s)
	return s, nil
}

// Update a device
func (d *DeviceManager) Update(id string, dev objects.DeviceDefinition) (bool, error) {
	var s bool
	err := d.client.Call("Create", 0, id, dev).Store(&s)
	util.CheckError(err)
	d.logger.Printf("Updated device %s\n", id)
	return s, nil
}

// Read a device definition
func (d *DeviceManager) Read(id string) (*objects.DeviceDefinition, error) {
	var s objects.DeviceDefinition
	err := d.client.Call("Read", 0, id).Store(&s)
	util.CheckError(err)
	return &s, nil
}

// Delete a device definition
func (d *DeviceManager) Delete(id string) (bool, error) {
	var s bool
	err := d.client.Call("Delete", 0, id).Store(&s)
	util.CheckError(err)
	return s, nil
}
<commit_msg>added find method to dbus client<commit_after>package client

import (
	"github.com/godbus/dbus"
	"github.com/muka/device-manager/objects"
	"github.com/muka/device-manager/util"
	"log"
)

// NewDeviceManager create a new DeviceManager client
func NewDeviceManager() *DeviceManager {
	d := new(DeviceManager)
	d.client = NewClient(objects.DeviceManagerInterface, objects.DeviceManagerPath)
	d.logger = util.Logger()
	return d
}

// DeviceManager client
type DeviceManager struct {
	client *Client
	logger *log.Logger
}

// Find a list of device
func (d *DeviceManager) Find(q *objects.BaseQuery) []dbus.ObjectPath {
	var s []dbus.ObjectPath
	err := d.client.Call("Find", 0, q).Store(&s)
	util.CheckError(err)
	return s
}

// Create a new device
func (d *DeviceManager) Create(dev objects.DeviceDefinition) (dbus.ObjectPath, error) {
	var s dbus.ObjectPath
	err := d.client.Call("Create", 0, dev).Store(&s)
	util.CheckError(err)
	d.logger.Printf("Created device at path\n %v\n", s)
	return s, nil
}

// Update a device
func (d *DeviceManager) Update(id string, dev objects.DeviceDefinition) (bool, error) {
	var s bool
	err := d.client.Call("Create", 0, id, dev).Store(&s)
	util.CheckError(err)
	d.logger.Printf("Updated device %s\n", id)
	return s, nil
}

// Read a device definition
func (d *DeviceManager) Read(id string) (*objects.DeviceDefinition, error) {
	var s objects.DeviceDefinition
	err := d.client.Call("Read", 0, id).Store(&s)
	util.CheckError(err)
	return &s, nil
}

// Delete a device definition
func (d *DeviceManager) Delete(id string) (bool, error) {
	var s bool
	err := d.client.Call("Delete", 0, id).Store(&s)
	util.CheckError(err)
	return s, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Andy Leap, Google
//
// 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.

// Run the shared test suite from https://github.com/microformats/tests

package microformats_test

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"willnorris.com/go/microformats"
)

// skip the tests which we don't pass yet
var skipTests = []string{
	"microformats-v2/h-as-note/note",
	"microformats-v2/h-card/impliedname",
	"microformats-v2/h-card/impliedphoto",
	"microformats-v2/h-card/impliedurl",
	"microformats-v2/h-card/nested",
	"microformats-v2/h-entry/summarycontent",
	"microformats-v2/h-entry/urlincontent",
	"microformats-v2/h-event/concatenate",
	"microformats-v2/h-event/dates",
	"microformats-v2/h-event/time",
	"microformats-v2/h-feed/implied-title",
	"microformats-v2/h-feed/simple",
	"microformats-v2/h-news/all",
	"microformats-v2/h-news/minimum",
	"microformats-v2/h-recipe/all",
	"microformats-v2/h-resume/affiliation",
	"microformats-v2/h-review/vcard",
	"microformats-v2/rel/duplicate-rels",
	"microformats-v2/rel/varying-text-duplicate-rels",
}

func TestSuite(t *testing.T) {
	t.Run("microformats-v2", func(t *testing.T) {
		version := "microformats-v2"
		base := filepath.Join("testdata", "tests", version)
		tests, err := listTests(base)
		if err != nil {
			t.Fatalf("error reading test cases: %v", err)
		}

		for _, test := range tests {
			t.Run(test, func(t *testing.T) {
				for _, skip := range skipTests {
					if path.Join(version, test) == skip {
						t.Skip()
					}
				}

				runTest(t, filepath.Join(base, test))
			})
		}
	})
}

// listTests recursively lists microformat tests in the specified root
// directory.  A test is identified as pair of matching .html and .json files
// in the same directory.  Returns a slice of named tests, where the test name
// is the path to the html and json files relative to root, excluding any file
// extension.
func listTests(root string) ([]string, error) {
	tests := []string{}
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if ext := filepath.Ext(path); ext == ".json" {
			test := strings.TrimSuffix(path, ext)
			// ensure .html file exists with the same name
			if _, err := os.Stat(test + ".html"); os.IsNotExist(err) {
				return nil
			}
			test, err = filepath.Rel(root, test)
			if err != nil {
				return err
			}
			tests = append(tests, test)
		}
		return nil
	})
	return tests, err
}

func runTest(t *testing.T, test string) {
	input, err := ioutil.ReadFile(test + ".html")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".html", err)
	}

	URL, _ := url.Parse("http://example.com/")
	data := microformats.Parse(bytes.NewReader(input), URL)

	expectedJSON, err := ioutil.ReadFile(test + ".json")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".json", err)
	}
	want := make(map[string]interface{})
	err = json.Unmarshal(expectedJSON, &want)
	if err != nil {
		t.Fatalf("error unmarshaling json in file %q: %v", test+".json", err)
	}

	outputJSON, _ := json.Marshal(data)
	got := make(map[string]interface{})
	err = json.Unmarshal(outputJSON, &got)
	if err != nil {
		t.Fatalf("error unmarshaling json: %v", err)
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("Parse returned %v\n\nwant: %v\n\n", got, want)
	}
}
<commit_msg>setup to run mf1 compat tests in the future<commit_after>// Copyright (c) 2015 Andy Leap, Google
//
// 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.

// Run the shared test suite from https://github.com/microformats/tests

package microformats_test

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"willnorris.com/go/microformats"
)

// skip the tests which we don't pass yet
var skipTests = []string{
	"microformats-v2/h-as-note/note",
	"microformats-v2/h-card/impliedname",
	"microformats-v2/h-card/impliedphoto",
	"microformats-v2/h-card/impliedurl",
	"microformats-v2/h-card/nested",
	"microformats-v2/h-entry/summarycontent",
	"microformats-v2/h-entry/urlincontent",
	"microformats-v2/h-event/concatenate",
	"microformats-v2/h-event/dates",
	"microformats-v2/h-event/time",
	"microformats-v2/h-feed/implied-title",
	"microformats-v2/h-feed/simple",
	"microformats-v2/h-news/all",
	"microformats-v2/h-news/minimum",
	"microformats-v2/h-recipe/all",
	"microformats-v2/h-resume/affiliation",
	"microformats-v2/h-review/vcard",
	"microformats-v2/rel/duplicate-rels",
	"microformats-v2/rel/varying-text-duplicate-rels",
}

func TestSuite(t *testing.T) {
	for _, version := range []string{"microformats-v2"} {
		t.Run(version, func(t *testing.T) {
			base := filepath.Join("testdata", "tests", version)
			tests, err := listTests(base)
			if err != nil {
				t.Fatalf("error reading test cases: %v", err)
			}

			for _, test := range tests {
				t.Run(test, func(t *testing.T) {
					for _, skip := range skipTests {
						if path.Join(version, test) == skip {
							t.Skip()
						}
					}

					runTest(t, filepath.Join(base, test))
				})
			}
		})
	}
}

// listTests recursively lists microformat tests in the specified root
// directory.  A test is identified as pair of matching .html and .json files
// in the same directory.  Returns a slice of named tests, where the test name
// is the path to the html and json files relative to root, excluding any file
// extension.
func listTests(root string) ([]string, error) {
	tests := []string{}
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if ext := filepath.Ext(path); ext == ".json" {
			test := strings.TrimSuffix(path, ext)
			// ensure .html file exists with the same name
			if _, err := os.Stat(test + ".html"); os.IsNotExist(err) {
				return nil
			}
			test, err = filepath.Rel(root, test)
			if err != nil {
				return err
			}
			tests = append(tests, test)
		}
		return nil
	})
	return tests, err
}

func runTest(t *testing.T, test string) {
	input, err := ioutil.ReadFile(test + ".html")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".html", err)
	}

	URL, _ := url.Parse("http://example.com/")
	data := microformats.Parse(bytes.NewReader(input), URL)

	expectedJSON, err := ioutil.ReadFile(test + ".json")
	if err != nil {
		t.Fatalf("error reading file %q: %v", test+".json", err)
	}
	want := make(map[string]interface{})
	err = json.Unmarshal(expectedJSON, &want)
	if err != nil {
		t.Fatalf("error unmarshaling json in file %q: %v", test+".json", err)
	}

	outputJSON, _ := json.Marshal(data)
	got := make(map[string]interface{})
	err = json.Unmarshal(outputJSON, &got)
	if err != nil {
		t.Fatalf("error unmarshaling json: %v", err)
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("Parse returned %v\n\nwant: %v\n\n", got, want)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/mcroydon/goplayground/tribblestore"
	"math/rand"
	"time"
)

func count(size int) {
	fmt.Printf("\nThere are now %v tribbles in the cargo hold.\n", size)
}

func main() {
	// In a world...
	rand.Seed(time.Now().UTC().UnixNano())

	// Create our first tribble.
	tribble := tribblestore.NewTribble("gray")
	fmt.Println("Is that a tribble?\n")

	// Give it some food.
	tribble.Eat()

	// This is inevitable.
	tribbles := tribble.Reproduce()

	// Time goes by.
	for i := 0; i < 100; i++ {
		for _, t := range tribbles {
			t.Eat()
		}
		// Note that this is not an accurate simulation as more than one
		// tribble is likely reproducing at any given moment.
		babytribbles := tribbles[rand.Intn(len(tribbles))].Reproduce()
		tribbles = append(tribbles, babytribbles...)
		count(len(tribbles))
	}

}
<commit_msg>go fmt cargo_hold.<commit_after>package main

import (
	"fmt"
	"github.com/mcroydon/goplayground/tribblestore"
	"math/rand"
	"time"
)

func count(size int) {
	fmt.Printf("\nThere are now %v tribbles in the cargo hold.\n", size)
}

func main() {
	// In a world...
	rand.Seed(time.Now().UTC().UnixNano())

	// Create our first tribble.
	tribble := tribblestore.NewTribble("gray")
	fmt.Println("Is that a tribble?\n")

	// Give it some food.
	tribble.Eat()

	// This is inevitable.
	tribbles := tribble.Reproduce()

	// Time goes by.
	for i := 0; i < 100; i++ {
		for _, t := range tribbles {
			t.Eat()
		}
		// Note that this is not an accurate simulation as more than one
		// tribble is likely reproducing at any given moment.
		babytribbles := tribbles[rand.Intn(len(tribbles))].Reproduce()
		tribbles = append(tribbles, babytribbles...)
		count(len(tribbles))
	}

}
<|endoftext|>


<commit_before>package openapi3

import (
	"fmt"
	"log"
	"net/url"
	"testing"
)

var basePathTests = []struct {
	v    string
	want string
}{
	{"https://{customerId}.saas-app.com:{port}/v2", "v2"},
}

func TestBasePath(t *testing.T) {
	for _, tt := range basePathTests {

		u1 := url.URL{
			Host: "https://{customerId}.saas-app.com:{port}",
		}
		fmt.Printf("HOST [%v]\n", u1.Host)

		tryUrl, err := url.Parse(tt.v)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("GOT PATH [%v]\n", tryUrl.Path)
		/*
			got := BasePath(tt.v)
			want := got
			if got != want {
				t.Errorf("openapi3.BasePath() Error: input [%v], want [%v], got [%v]",
					tt.v, tt.want, got)
			}*/
	}
}
<commit_msg>remove incomplete test<commit_after><|endoftext|>


<commit_before>package client

import (
	"bytes"
	"container/list"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)

// Variable size structure prefix-header byte lengths
const (
	CertificateLengthBytes      = 3
	PreCertificateLengthBytes   = 3
	ExtensionsLengthBytes       = 2
	CertificateChainLengthBytes = 3
)

// Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
// number of (BigEndian) prefix-bytes which contain the length of the actual
// array data bytes that follow.
// Allocates an array to hold the contents and returns a slice view into it if
// the read was successful, or an error otherwise.
func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
	var l uint64
	switch {
	case numLenBytes > 8:
		return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
	case numLenBytes == 0:
		return nil, errors.New("numLenBytes should be > 0")
	}
	// Read the length header bytes
	for i := 0; i < numLenBytes; i++ {
		l <<= 8
		var t uint8
		if err := binary.Read(r, binary.BigEndian, &t); err != nil {
			return nil, err
		}
		l |= uint64(t)
	}
	data := make([]byte, l)
	n, err := r.Read(data)
	if err != nil {
		return nil, err
	}
	if n != int(l) {
		return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
	}
	return data, nil
}

// Reads a list of ASN1Cert types from |r|
func readASN1CertList(r io.Reader, total_len_bytes int, element_len_bytes int) ([]ASN1Cert, error) {
	list_bytes, err := readVarBytes(r, total_len_bytes)
	if err != nil {
		return []ASN1Cert{}, err
	}
	list := list.New()
	list_reader := bytes.NewReader(list_bytes)
	var entry []byte
	for err == nil {
		entry, err = readVarBytes(list_reader, element_len_bytes)
		if err != nil {
			if err != io.EOF {
				return []ASN1Cert{}, err
			}
		} else {
			list.PushBack(entry)
		}
	}
	ret := make([]ASN1Cert, list.Len())
	i := 0
	for e := list.Front(); e != nil; e = e.Next() {
		ret[i] = e.Value.([]byte)
		i++
	}
	return ret, nil
}

// Parses the byte-stream representation of a TimestampedEntry from |r| and populates
// the struct |t| with the data.
// See RFC section 3.4 for details on the format.
// Returns a non-nil error if there was a problem.
func ReadTimestampedEntryInto(r io.Reader, t *TimestampedEntry) error {
	var err error
	if err = binary.Read(r, binary.BigEndian, &t.Timestamp); err != nil {
		return err
	}
	if err = binary.Read(r, binary.BigEndian, &t.EntryType); err != nil {
		return err
	}
	switch t.EntryType {
	case X509LogEntryType:
		if t.X509Entry, err = readVarBytes(r, CertificateLengthBytes); err != nil {
			return err
		}
	case PrecertLogEntryType:
		if err := binary.Read(r, binary.BigEndian, &t.PrecertEntry.IssuerKeyHash); err != nil {
			return err
		}
		if t.PrecertEntry.TBSCertificate, err = readVarBytes(r, PreCertificateLengthBytes); err != nil {
			return err
		}
	default:
		return fmt.Errorf("unknown EntryType: %d", t.EntryType)
	}
	t.Extensions, err = readVarBytes(r, ExtensionsLengthBytes)
	return nil
}

// Parses the byte-stream representation of a MerkleTreeLeaf and returns a
// pointer to a new MerkleTreeLeaf structure containing the parsed data.
// See RFC section 3.4 for details on the format.
// Returns a pointer to a new MerkleTreeLeaf or non-nil error if there was a problem
func ReadMerkleTreeLeaf(r io.Reader) (*MerkleTreeLeaf, error) {
	var m MerkleTreeLeaf
	if err := binary.Read(r, binary.BigEndian, &m.Version); err != nil {
		return nil, err
	}
	if m.Version != V1 {
		return nil, fmt.Errorf("unknown Version %d", m.Version)
	}
	if err := binary.Read(r, binary.BigEndian, &m.LeafType); err != nil {
		return nil, err
	}
	if m.LeafType != TimestampedEntryLeafType {
		return nil, fmt.Errorf("unknown LeafType %d", m.LeafType)
	}
	if err := ReadTimestampedEntryInto(r, &m.TimestampedEntry); err != nil {
		return nil, err
	}
	return &m, nil
}

// Unmarshalls the contents of the "chain:" entry in a GetEntries response in
// the case where the entry refers to an X509 leaf.
func UnmarshalX509ChainArray(b []byte) ([]ASN1Cert, error) {
	return readASN1CertList(bytes.NewReader(b), CertificateChainLengthBytes, CertificateLengthBytes)
}

// Unmarshalls the contents of the "chain:" entry in a GetEntries response in
// the case where the entry refers to a Precertificate leaf.
func UnmarshalPrecertChainArray(b []byte) ([]ASN1Cert, error) {
	var chain []ASN1Cert

	reader := bytes.NewReader(b)
	// read the pre-cert entry:
	precert, err := readVarBytes(reader, CertificateLengthBytes)
	if err != nil {
		return chain, err
	}
	chain = append(chain, precert)
	// and then read and return the chain up to the root:
	remaining_chain, err := readASN1CertList(reader, CertificateChainLengthBytes, CertificateLengthBytes)
	if err != nil {
		return chain, err
	}
	fmt.Printf("remainin_chain len %d\n", len(remaining_chain))
	chain = append(chain, remaining_chain...)
	return chain, nil
}
<commit_msg>Remove noise.<commit_after>package client

import (
	"bytes"
	"container/list"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)

// Variable size structure prefix-header byte lengths
const (
	CertificateLengthBytes      = 3
	PreCertificateLengthBytes   = 3
	ExtensionsLengthBytes       = 2
	CertificateChainLengthBytes = 3
)

// Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
// number of (BigEndian) prefix-bytes which contain the length of the actual
// array data bytes that follow.
// Allocates an array to hold the contents and returns a slice view into it if
// the read was successful, or an error otherwise.
func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
	var l uint64
	switch {
	case numLenBytes > 8:
		return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
	case numLenBytes == 0:
		return nil, errors.New("numLenBytes should be > 0")
	}
	// Read the length header bytes
	for i := 0; i < numLenBytes; i++ {
		l <<= 8
		var t uint8
		if err := binary.Read(r, binary.BigEndian, &t); err != nil {
			return nil, err
		}
		l |= uint64(t)
	}
	data := make([]byte, l)
	n, err := r.Read(data)
	if err != nil {
		return nil, err
	}
	if n != int(l) {
		return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
	}
	return data, nil
}

// Reads a list of ASN1Cert types from |r|
func readASN1CertList(r io.Reader, total_len_bytes int, element_len_bytes int) ([]ASN1Cert, error) {
	list_bytes, err := readVarBytes(r, total_len_bytes)
	if err != nil {
		return []ASN1Cert{}, err
	}
	list := list.New()
	list_reader := bytes.NewReader(list_bytes)
	var entry []byte
	for err == nil {
		entry, err = readVarBytes(list_reader, element_len_bytes)
		if err != nil {
			if err != io.EOF {
				return []ASN1Cert{}, err
			}
		} else {
			list.PushBack(entry)
		}
	}
	ret := make([]ASN1Cert, list.Len())
	i := 0
	for e := list.Front(); e != nil; e = e.Next() {
		ret[i] = e.Value.([]byte)
		i++
	}
	return ret, nil
}

// Parses the byte-stream representation of a TimestampedEntry from |r| and populates
// the struct |t| with the data.
// See RFC section 3.4 for details on the format.
// Returns a non-nil error if there was a problem.
func ReadTimestampedEntryInto(r io.Reader, t *TimestampedEntry) error {
	var err error
	if err = binary.Read(r, binary.BigEndian, &t.Timestamp); err != nil {
		return err
	}
	if err = binary.Read(r, binary.BigEndian, &t.EntryType); err != nil {
		return err
	}
	switch t.EntryType {
	case X509LogEntryType:
		if t.X509Entry, err = readVarBytes(r, CertificateLengthBytes); err != nil {
			return err
		}
	case PrecertLogEntryType:
		if err := binary.Read(r, binary.BigEndian, &t.PrecertEntry.IssuerKeyHash); err != nil {
			return err
		}
		if t.PrecertEntry.TBSCertificate, err = readVarBytes(r, PreCertificateLengthBytes); err != nil {
			return err
		}
	default:
		return fmt.Errorf("unknown EntryType: %d", t.EntryType)
	}
	t.Extensions, err = readVarBytes(r, ExtensionsLengthBytes)
	return nil
}

// Parses the byte-stream representation of a MerkleTreeLeaf and returns a
// pointer to a new MerkleTreeLeaf structure containing the parsed data.
// See RFC section 3.4 for details on the format.
// Returns a pointer to a new MerkleTreeLeaf or non-nil error if there was a problem
func ReadMerkleTreeLeaf(r io.Reader) (*MerkleTreeLeaf, error) {
	var m MerkleTreeLeaf
	if err := binary.Read(r, binary.BigEndian, &m.Version); err != nil {
		return nil, err
	}
	if m.Version != V1 {
		return nil, fmt.Errorf("unknown Version %d", m.Version)
	}
	if err := binary.Read(r, binary.BigEndian, &m.LeafType); err != nil {
		return nil, err
	}
	if m.LeafType != TimestampedEntryLeafType {
		return nil, fmt.Errorf("unknown LeafType %d", m.LeafType)
	}
	if err := ReadTimestampedEntryInto(r, &m.TimestampedEntry); err != nil {
		return nil, err
	}
	return &m, nil
}

// Unmarshalls the contents of the "chain:" entry in a GetEntries response in
// the case where the entry refers to an X509 leaf.
func UnmarshalX509ChainArray(b []byte) ([]ASN1Cert, error) {
	return readASN1CertList(bytes.NewReader(b), CertificateChainLengthBytes, CertificateLengthBytes)
}

// Unmarshalls the contents of the "chain:" entry in a GetEntries response in
// the case where the entry refers to a Precertificate leaf.
func UnmarshalPrecertChainArray(b []byte) ([]ASN1Cert, error) {
	var chain []ASN1Cert

	reader := bytes.NewReader(b)
	// read the pre-cert entry:
	precert, err := readVarBytes(reader, CertificateLengthBytes)
	if err != nil {
		return chain, err
	}
	chain = append(chain, precert)
	// and then read and return the chain up to the root:
	remaining_chain, err := readASN1CertList(reader, CertificateChainLengthBytes, CertificateLengthBytes)
	if err != nil {
		return chain, err
	}
	chain = append(chain, remaining_chain...)
	return chain, nil
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"strings"

	"log"

	"fmt"

	"github.com/julienschmidt/httprouter"
	"github.com/szydell/gogtm"
	"github.com/szydell/mstools"
)

func startRouter() {
	router := httprouter.New()

	//define routes
	//router.GET("/", Index)
	router.GET("/v1/data/:glvn", getGlvn)

	//Start to listen
	mstools.ErrCheck(http.ListenAndServe(":8080", router))

}

func getGlvn(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	glvn := string(ps.ByName("glvn"))
	log.Println("GET glvn:" + glvn)
	response, err := gogtm.Get(glvn, suuid)
	response = response[:len(response)-2] //response has blank \0 at the end
	fmt.Println("dlugosc response: ", len(response))
	if err != nil {
		http.Error(w, "503 Service Unavailable", 503)
		log.Println("503 /v1/data/" + glvn)
		return
	}
	fmt.Println(strings.Compare(suuid, response))
	fmt.Println("." + response + ".")
	fmt.Println("." + suuid + ".")
	if 1 == 1 {
		http.Error(w, "404 Not Found", 404)
		log.Println("404 /v1/data/" + glvn)
		return
	}
	fmt.Fprintf(w, "%s: %s", glvn, response)
	log.Println("200 /v1/data/" + glvn + " -> " + response)
}
<commit_msg>getGlvn probably works fine<commit_after>package main

import (
	"net/http"
	"strconv"

	"log"

	"fmt"

	"github.com/julienschmidt/httprouter"
	"github.com/szydell/gogtm"
	"github.com/szydell/mstools"
)

func startRouter() {
	router := httprouter.New()

	//define routes
	//router.GET("/", Index)
	router.GET("/v1/data/:glvn", getGlvn)

	//Start to listen
	mstools.ErrCheck(http.ListenAndServe(":8080", router))

}

func getGlvn(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	glvn := string(ps.ByName("glvn"))
	log.Println("GET glvn:" + glvn)
	response, err := gogtm.Get("^"+glvn, suuid)
	if err != nil {
		http.Error(w, "503 Service Unavailable", 503)
		log.Println("503 /v1/data/" + glvn)
		return
	}
	if response == suuid {
		http.Error(w, "404 Not Found", 404)
		log.Println("404 /v1/data/" + glvn)
		return
	}
	//return string formatted as JSON, try to figure out if response is a string or integer
	if _, err := strconv.Atoi(response); err == nil {
		fmt.Fprintf(w, "{\"%s\": %s}", glvn, response)
	} else {
		fmt.Fprintf(w, "{\"%s\": \"%s\"}", glvn, response)
	}
	log.Println("200 /v1/data/" + glvn + " -> " + response)
}
<|endoftext|>


<commit_before>package rest

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

// Handler является любая функция, которая принимает Context.
type Handler func(*Context)

// Method описывает список Handle, ассоциированные с HTTP-методами.
type Method map[string]Handler

// ServeMux описывает список обработчиков, ассоциированных с путями запроса и методами.
type ServeMux struct {
	router // обработчики запросов по путям, без учета метода запроса
	// Глобальный обработчик, вызываемый перед всеми заданными обработчиками,
	// если определен.
	CustomHandler func(Handler) Handler
}

// Handle добавляет новый обработчик для указанного пути и метода запроса.
func (m *ServeMux) Handle(method, path string, handler Handler) {
	if method == "" || handler == nil {
		return
	}
	method = strings.ToUpper(method) // хочу быть уверенным
	// предполагаем, что обработчик для данного пути уже есть
	if route, _ := m.router.lookup(path); route != nil {
		// в роутере хранятся обработчики с привязкой к методам
		if methods, ok := route.(Method); ok {
			methods[method] = handler // добавляем новый обработчик пути для данного метода
		} else {
			panic(fmt.Errorf("bad mux definition for: %s", path))
		}
	} else {
		// обработчик для данного пути не определен
		if err := m.router.add(path, Method{method: handler}); err != nil {
			panic(err)
		}
	}
}

// Handles добавляет определение обработчиков сразу для всех методов для указанного пути.
func (m *ServeMux) Handles(path string, handlers Method) {
	if len(handlers) == 0 {
		return
	}
	if err := m.router.add(path, handlers); err != nil {
		panic(err)
	}
}

// Handler позволяет привязать к нашему описанию стандартный обработчик http.Handler.
func (m *ServeMux) Handler(method, path string, handler http.Handler) {
	m.Handle(method, path, func(c *Context) {
		handler.ServeHTTP(c.Response, c.Request)
	})
}

// HandlerFunc позволяет привязать к нашему описанию стандартный обработчик http.Handler.
func (m *ServeMux) HandlerFunc(method, path string, handler http.HandlerFunc) {
	m.Handle(method, path, func(c *Context) {
		handler(c.Response, c.Request)
	})
}

// Lookup возвращает обработчик для указанного пути и метода, а так же заполненный список
// параметров пути. Если обработчик для данных параметров не определен, то возвращается nil.
func (m *ServeMux) Lookup(method, path string) (h Handler, params Params) {
	route, params := m.router.lookup(path)
	if route != nil {
		// в роутере хранятся обработчики с привязкой к методам
		if methods, ok := route.(Method); ok {
			h = methods[strings.ToUpper(method)]
		} else {
			panic(fmt.Errorf("bad mux definition for: %s", path))
		}
	}
	return
}

// ServeHTTP обеспечивает поддержку интерфейса http.Handler и обрабатывает основной запрос.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	route, params := m.router.lookup(req.URL.Path) // получаем обработчик для указанного пути
	context := newContext(w, req, params)          // формируем контекст для ответа
	if route == nil {
		// при статусе больше 399 пустой body формирует JSON с описанием ошибки автоматически
		context.Code(http.StatusNotFound).Body(nil)
		return
	}
	methods, ok := route.(Method) // приводим список методов
	if !ok || len(methods) == 0 {
		// в данном случае текст будет передан как ошибка, потому что код больше 399.
		context.Code(http.StatusInternalServerError).Body("bad mux definition")
		return
	}
	handler := methods[strings.ToUpper(req.Method)] // запрашиваем обработчик для метода
	if handler == nil {                             // обработчик для данного метода не определен
		allows := make([]string, 0, len(methods)) // формируем список поддерживаемых методов
		for method := range methods {
			allows = append(allows, method)
		}
		context.SetHeader("Allow", strings.Join(allows, ", "))
		context.Code(http.StatusMethodNotAllowed).Body(nil)
		return
	}
	if m.CustomHandler != nil { // если кастомный обработчик определен, то вызываем его
		m.CustomHandler(handler)(context)
	} else {
		handler(context) // вызываем обработчик запроса
	}
}
<commit_msg>mux.Handle fix<commit_after>package rest

import (
	"net/http"
	"strings"
)

// Handler является любая функция, которая принимает Context.
type Handler func(*Context)

// Method описывает список Handle, ассоциированные с HTTP-методами.
type Method map[string]Handler

// ServeMux описывает список обработчиков, ассоциированных с путями запроса и методами.
type ServeMux struct {
	router // обработчики запросов по путям, без учета метода запроса
	// Глобальный обработчик, вызываемый перед всеми заданными обработчиками,
	// если определен.
	CustomHandler func(Handler) Handler
}

// Handle добавляет новый обработчик для указанного пути и метода запроса.
func (m *ServeMux) Handle(method, path string, handler Handler) {
	if method == "" || handler == nil {
		return
	}
	method = strings.ToUpper(method) // хочу быть уверенным
	// предполагаем, что обработчик для данного пути уже есть
	if route, _ := m.router.lookup(path); route != nil {
		// в роутере хранятся обработчики с привязкой к методам
		if methods, ok := route.(Method); ok {
			methods[method] = handler // добавляем новый обработчик пути для данного метода
			return
		}
	}
	// обработчик для данного пути не определен
	if err := m.router.add(path, Method{method: handler}); err != nil {
		panic(err)
	}
}

// Handles добавляет определение обработчиков сразу для всех методов для указанного пути.
func (m *ServeMux) Handles(path string, handlers Method) {
	if len(handlers) == 0 {
		return
	}
	if err := m.router.add(path, handlers); err != nil {
		panic(err)
	}
}

// Handler позволяет привязать к нашему описанию стандартный обработчик http.Handler.
func (m *ServeMux) Handler(method, path string, handler http.Handler) {
	m.Handle(method, path, func(c *Context) {
		handler.ServeHTTP(c.Response, c.Request)
	})
}

// HandlerFunc позволяет привязать к нашему описанию стандартный обработчик http.Handler.
func (m *ServeMux) HandlerFunc(method, path string, handler http.HandlerFunc) {
	m.Handle(method, path, func(c *Context) {
		handler(c.Response, c.Request)
	})
}

// Lookup возвращает обработчик для указанного пути и метода, а так же заполненный список
// параметров пути. Если обработчик для данных параметров не определен, то возвращается nil.
func (m *ServeMux) Lookup(method, path string) (h Handler, params Params) {
	route, params := m.router.lookup(path)
	if route == nil {
		return
	}
	// в роутере хранятся обработчики с привязкой к методам
	if methods, ok := route.(Method); ok {
		h = methods[strings.ToUpper(method)]
	}
	return
}

// ServeHTTP обеспечивает поддержку интерфейса http.Handler и обрабатывает основной запрос.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	route, params := m.router.lookup(req.URL.Path) // получаем обработчик для указанного пути
	context := newContext(w, req, params)          // формируем контекст для ответа
	if route == nil {
		// при статусе больше 399 пустой body формирует JSON с описанием ошибки автоматически
		context.Code(http.StatusNotFound).Body(nil)
		return
	}
	methods, ok := route.(Method) // приводим список методов
	if !ok || len(methods) == 0 { // если методы не определены, то лучше вернем, что путь не найден
		context.Code(http.StatusNotFound).Body(nil)
		return
	}
	handler := methods[strings.ToUpper(req.Method)] // запрашиваем обработчик для метода
	if handler == nil {                             // обработчик для данного метода не определен
		allows := make([]string, 0, len(methods)) // формируем список поддерживаемых методов
		for method := range methods {
			allows = append(allows, method)
		}
		context.SetHeader("Allow", strings.Join(allows, ", "))
		context.Code(http.StatusMethodNotAllowed).Body(nil)
		return
	}
	if m.CustomHandler != nil { // если кастомный обработчик определен, то вызываем его
		m.CustomHandler(handler)(context)
	} else {
		handler(context) // вызываем обработчик запроса
	}
}
<|endoftext|>


<commit_before>package buildah

import (
	"fmt"
	"strings"

	is "github.com/containers/image/storage"
	"github.com/containers/image/transports"
	"github.com/containers/image/transports/alltransports"
	"github.com/containers/image/types"
	"github.com/containers/storage"
	"github.com/opencontainers/selinux/go-selinux"
	"github.com/opencontainers/selinux/go-selinux/label"
	"github.com/openshift/imagebuilder"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

const (
	// BaseImageFakeName is the "name" of a source image which we interpret
	// as "no image".
	BaseImageFakeName = imagebuilder.NoBaseImageSpecifier

	// DefaultTransport is a prefix that we apply to an image name if we
	// can't find one in the local Store, in order to generate a source
	// reference for the image that we can then copy to the local Store.
	DefaultTransport = "docker://"
)

func reserveSELinuxLabels(store storage.Store, id string) error {
	if selinux.GetEnabled() {
		containers, err := store.Containers()
		if err != nil {
			return err
		}

		for _, c := range containers {
			if id == c.ID {
				continue
			} else {
				b, err := OpenBuilder(store, c.ID)
				if err != nil {
					if err == storage.ErrContainerUnknown {
						continue
					}
					return err
				}
				// Prevent containers from using same MCS Label
				if err := label.ReserveLabel(b.ProcessLabel); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
	var ref types.ImageReference
	var img *storage.Image
	manifest := []byte{}
	config := []byte{}

	if options.FromImage == BaseImageFakeName {
		options.FromImage = ""
	}
	image := options.FromImage

	if options.Transport == "" {
		options.Transport = DefaultTransport
	}

	systemContext := getSystemContext(options.SignaturePolicyPath)

	imageID := ""
	if image != "" {
		var err error
		if options.PullPolicy == PullAlways {
			pulledReference, err2 := pullImage(store, options, systemContext)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error pulling image %q", image)
			}
			ref = pulledReference
		}
		if ref == nil {
			srcRef, err2 := alltransports.ParseImageName(image)
			if err2 != nil {
				srcRef2, err3 := alltransports.ParseImageName(options.Registry + image)
				if err3 != nil {
					srcRef3, err4 := alltransports.ParseImageName(options.Transport + options.Registry + image)
					if err4 != nil {
						return nil, errors.Wrapf(err4, "error parsing image name %q", options.Transport+options.Registry+image)
					}
					srcRef2 = srcRef3
				}
				srcRef = srcRef2
			}

			destImage, err2 := localImageNameForReference(store, srcRef)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error computing local image name for %q", transports.ImageName(srcRef))
			}
			if destImage == "" {
				return nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef))
			}

			ref, err = is.Transport.ParseStoreReference(store, destImage)
			if err != nil {
				return nil, errors.Wrapf(err, "error parsing reference to image %q", destImage)
			}

			image = destImage
		}
		img, err = is.Transport.GetStoreImage(store, ref)
		if err != nil {
			if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing {
				return nil, errors.Wrapf(err, "no such image %q", transports.ImageName(ref))
			}
			ref2, err2 := pullImage(store, options, systemContext)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error pulling image %q", image)
			}
			ref = ref2
			img, err = is.Transport.GetStoreImage(store, ref)
		}
		if err != nil {
			return nil, errors.Wrapf(err, "no such image %q", transports.ImageName(ref))
		}
		imageID = img.ID
		src, err := ref.NewImage(systemContext)
		if err != nil {
			return nil, errors.Wrapf(err, "error instantiating image for %q", transports.ImageName(ref))
		}
		defer src.Close()
		config, err = src.ConfigBlob()
		if err != nil {
			return nil, errors.Wrapf(err, "error reading image configuration for %q", transports.ImageName(ref))
		}
		manifest, _, err = src.Manifest()
		if err != nil {
			return nil, errors.Wrapf(err, "error reading image manifest for %q", transports.ImageName(ref))
		}
	}

	name := "working-container"
	if options.Container != "" {
		name = options.Container
	} else {
		var err2 error
		if image != "" {
			prefix := image
			s := strings.Split(prefix, "/")
			if len(s) > 0 {
				prefix = s[len(s)-1]
			}
			s = strings.Split(prefix, ":")
			if len(s) > 0 {
				prefix = s[0]
			}
			s = strings.Split(prefix, "@")
			if len(s) > 0 {
				prefix = s[0]
			}
			name = prefix + "-" + name
		}
		suffix := 1
		tmpName := name
		for errors.Cause(err2) != storage.ErrContainerUnknown {
			_, err2 = store.Container(tmpName)
			if err2 == nil {
				suffix++
				tmpName = fmt.Sprintf("%s-%d", name, suffix)
			}
		}
		name = tmpName
	}
	coptions := storage.ContainerOptions{}
	container, err := store.CreateContainer("", []string{name}, imageID, "", "", &coptions)
	if err != nil {
		return nil, errors.Wrapf(err, "error creating container")
	}

	defer func() {
		if err != nil {
			if err2 := store.DeleteContainer(container.ID); err != nil {
				logrus.Errorf("error deleting container %q: %v", container.ID, err2)
			}
		}
	}()

	if err := reserveSELinuxLabels(store, container.ID); err != nil {
		return nil, err
	}
	processLabel, mountLabel, err := label.InitLabels(nil)
	if err != nil {
		return nil, err
	}

	builder := &Builder{
		store:                 store,
		Type:                  containerType,
		FromImage:             image,
		FromImageID:           imageID,
		Config:                config,
		Manifest:              manifest,
		Container:             name,
		ContainerID:           container.ID,
		ImageAnnotations:      map[string]string{},
		ImageCreatedBy:        "",
		ProcessLabel:          processLabel,
		MountLabel:            mountLabel,
		DefaultMountsFilePath: options.DefaultMountsFilePath,
	}

	if options.Mount {
		_, err = builder.Mount(mountLabel)
		if err != nil {
			return nil, errors.Wrapf(err, "error mounting build container")
		}
	}

	builder.initConfig()
	err = builder.Save()
	if err != nil {
		return nil, errors.Wrapf(err, "error saving builder state")
	}

	return builder, nil
}
<commit_msg>Ignore errors when trying to read containers buildah.json<commit_after>package buildah

import (
	"fmt"
	"os"
	"strings"

	is "github.com/containers/image/storage"
	"github.com/containers/image/transports"
	"github.com/containers/image/transports/alltransports"
	"github.com/containers/image/types"
	"github.com/containers/storage"
	"github.com/opencontainers/selinux/go-selinux"
	"github.com/opencontainers/selinux/go-selinux/label"
	"github.com/openshift/imagebuilder"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

const (
	// BaseImageFakeName is the "name" of a source image which we interpret
	// as "no image".
	BaseImageFakeName = imagebuilder.NoBaseImageSpecifier

	// DefaultTransport is a prefix that we apply to an image name if we
	// can't find one in the local Store, in order to generate a source
	// reference for the image that we can then copy to the local Store.
	DefaultTransport = "docker://"
)

func reserveSELinuxLabels(store storage.Store, id string) error {
	if selinux.GetEnabled() {
		containers, err := store.Containers()
		if err != nil {
			return err
		}

		for _, c := range containers {
			if id == c.ID {
				continue
			} else {
				b, err := OpenBuilder(store, c.ID)
				if err != nil {
					if os.IsNotExist(err) {
						// Ignore not exist errors since containers probably created by other tool
						// TODO, we need to read other containers json data to reserve their SELinux labels
						continue
					}
					return err
				}
				// Prevent containers from using same MCS Label
				if err := label.ReserveLabel(b.ProcessLabel); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
	var ref types.ImageReference
	var img *storage.Image
	manifest := []byte{}
	config := []byte{}

	if options.FromImage == BaseImageFakeName {
		options.FromImage = ""
	}
	image := options.FromImage

	if options.Transport == "" {
		options.Transport = DefaultTransport
	}

	systemContext := getSystemContext(options.SignaturePolicyPath)

	imageID := ""
	if image != "" {
		var err error
		if options.PullPolicy == PullAlways {
			pulledReference, err2 := pullImage(store, options, systemContext)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error pulling image %q", image)
			}
			ref = pulledReference
		}
		if ref == nil {
			srcRef, err2 := alltransports.ParseImageName(image)
			if err2 != nil {
				srcRef2, err3 := alltransports.ParseImageName(options.Registry + image)
				if err3 != nil {
					srcRef3, err4 := alltransports.ParseImageName(options.Transport + options.Registry + image)
					if err4 != nil {
						return nil, errors.Wrapf(err4, "error parsing image name %q", options.Transport+options.Registry+image)
					}
					srcRef2 = srcRef3
				}
				srcRef = srcRef2
			}

			destImage, err2 := localImageNameForReference(store, srcRef)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error computing local image name for %q", transports.ImageName(srcRef))
			}
			if destImage == "" {
				return nil, errors.Errorf("error computing local image name for %q", transports.ImageName(srcRef))
			}

			ref, err = is.Transport.ParseStoreReference(store, destImage)
			if err != nil {
				return nil, errors.Wrapf(err, "error parsing reference to image %q", destImage)
			}

			image = destImage
		}
		img, err = is.Transport.GetStoreImage(store, ref)
		if err != nil {
			if errors.Cause(err) == storage.ErrImageUnknown && options.PullPolicy != PullIfMissing {
				return nil, errors.Wrapf(err, "no such image %q", transports.ImageName(ref))
			}
			ref2, err2 := pullImage(store, options, systemContext)
			if err2 != nil {
				return nil, errors.Wrapf(err2, "error pulling image %q", image)
			}
			ref = ref2
			img, err = is.Transport.GetStoreImage(store, ref)
		}
		if err != nil {
			return nil, errors.Wrapf(err, "no such image %q", transports.ImageName(ref))
		}
		imageID = img.ID
		src, err := ref.NewImage(systemContext)
		if err != nil {
			return nil, errors.Wrapf(err, "error instantiating image for %q", transports.ImageName(ref))
		}
		defer src.Close()
		config, err = src.ConfigBlob()
		if err != nil {
			return nil, errors.Wrapf(err, "error reading image configuration for %q", transports.ImageName(ref))
		}
		manifest, _, err = src.Manifest()
		if err != nil {
			return nil, errors.Wrapf(err, "error reading image manifest for %q", transports.ImageName(ref))
		}
	}

	name := "working-container"
	if options.Container != "" {
		name = options.Container
	} else {
		var err2 error
		if image != "" {
			prefix := image
			s := strings.Split(prefix, "/")
			if len(s) > 0 {
				prefix = s[len(s)-1]
			}
			s = strings.Split(prefix, ":")
			if len(s) > 0 {
				prefix = s[0]
			}
			s = strings.Split(prefix, "@")
			if len(s) > 0 {
				prefix = s[0]
			}
			name = prefix + "-" + name
		}
		suffix := 1
		tmpName := name
		for errors.Cause(err2) != storage.ErrContainerUnknown {
			_, err2 = store.Container(tmpName)
			if err2 == nil {
				suffix++
				tmpName = fmt.Sprintf("%s-%d", name, suffix)
			}
		}
		name = tmpName
	}
	coptions := storage.ContainerOptions{}
	container, err := store.CreateContainer("", []string{name}, imageID, "", "", &coptions)
	if err != nil {
		return nil, errors.Wrapf(err, "error creating container")
	}

	defer func() {
		if err != nil {
			if err2 := store.DeleteContainer(container.ID); err != nil {
				logrus.Errorf("error deleting container %q: %v", container.ID, err2)
			}
		}
	}()

	if err := reserveSELinuxLabels(store, container.ID); err != nil {
		return nil, err
	}
	processLabel, mountLabel, err := label.InitLabels(nil)
	if err != nil {
		return nil, err
	}

	builder := &Builder{
		store:                 store,
		Type:                  containerType,
		FromImage:             image,
		FromImageID:           imageID,
		Config:                config,
		Manifest:              manifest,
		Container:             name,
		ContainerID:           container.ID,
		ImageAnnotations:      map[string]string{},
		ImageCreatedBy:        "",
		ProcessLabel:          processLabel,
		MountLabel:            mountLabel,
		DefaultMountsFilePath: options.DefaultMountsFilePath,
	}

	if options.Mount {
		_, err = builder.Mount(mountLabel)
		if err != nil {
			return nil, errors.Wrapf(err, "error mounting build container")
		}
	}

	builder.initConfig()
	err = builder.Save()
	if err != nil {
		return nil, errors.Wrapf(err, "error saving builder state")
	}

	return builder, nil
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strings"
	"sync"
)

const (
	version   = "2.5"
	useragent = "Optimus Cache Prime/" + version + " (http://patrickmylund.com/projects/ocp/)"
)

var (
	one    chan bool
	sem    chan bool
	wg     = &sync.WaitGroup{}
	client = http.DefaultClient

	throttle    *uint   = flag.Uint("c", 1, "URLs to prime at once")
	max         *uint   = flag.Uint("max", 0, "maximum number of uncached URLs to prime")
	localDir    *string = flag.String("l", "", "directory containing cached files (relative file names, i.e. /about/ -> <path>/about/index.html)")
	localSuffix *string = flag.String("ls", "index.html", "suffix of locally cached files")
	verbose     *bool   = flag.Bool("v", false, "show additional information about the priming process")
	nowarn      *bool   = flag.Bool("no-warn", false, "do not warn about pages that were not primed successfully")
	printurls   *bool   = flag.Bool("print", false, "(exclusive) just print the sorted URLs (can be used with xargs)")
)

type Sitemap struct {
	Loc string `xml:"loc"`
	// Lastmod string `xml:"lastmod"`
}

type Url struct {
	Loc string `xml:"loc"`
	// Lastmod string `xml:"lastmod"`
	// Changefreq string `xml:"changefreq"`
	Priority float64 `xml:"priority"`
}

type Urlset struct {
	XMLName xml.Name  "urlset"
	Sitemap []Sitemap `xml:"sitemap"`
	Url     []Url     `xml:"url"`
}

// Functions needed by sort.Sort
func (u Urlset) Len() int {
	return len(u.Url)
}

func (u Urlset) Swap(i, j int) {
	u.Url[i], u.Url[j] = u.Url[j], u.Url[i]
}

func (u Urlset) Less(i, j int) bool {
	return u.Url[i].Priority > u.Url[j].Priority
}

func Get(url string) (*http.Response, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("User-Agent", useragent)
	return client.Do(req)
}

func GetUrlsFromSitemap(path string, follow bool) (*Urlset, error) {
	var (
		urlset Urlset
		f      io.ReadCloser
		err    error
		res    *http.Response
	)
	if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
		if *verbose {
			log.Println("Downloading", path)
		}
		res, err = Get(path)
		if err != nil {
			return nil, err
		}
		if res.Status != "200 OK" {
			return nil, fmt.Errorf("HTTP %s", res.Status)
		}
		f = res.Body
	} else {
		f, err = os.Open(path)
		if err != nil {
			return nil, err
		}
	}
	defer f.Close()
	if strings.HasSuffix(path, ".gz") {
		if *verbose {
			log.Println("Extracting compressed data")
		}
		f, err = gzip.NewReader(f)
		if err != nil {
			return nil, err
		}
		defer f.Close()
	}
	data, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	err = xml.Unmarshal(data, &urlset)
	if err == nil && follow && len(urlset.Sitemap) > 0 { // This is a sitemapindex
		ch := make(chan *Urlset, len(urlset.Sitemap))
		if *verbose {
			log.Printf("%s is a Sitemapindex\n", path)
		}
		for _, v := range urlset.Sitemap {
			sem <- true
			if *verbose {
				log.Printf("Adding URLs from child sitemap %s\n", v.Loc)
			}
			go func(loc string) {
				// Follow is false as Sitemapindex spec says sitemapindex children are illegal
				ourlset, err := GetUrlsFromSitemap(loc, false)
				if err != nil {
					log.Printf("Error getting Urlset from sitemap %s: %s", loc, err)
					ch <- nil
				} else {
					ch <- ourlset
				}
				<-sem
			}(v.Loc)
		}
		// Add every URL from each Urlset to the main Urlset
		for i := 0; i < len(urlset.Sitemap); i++ {
			childUrlset := <-ch
			if childUrlset != nil {
				urlset.Url = append(urlset.Url, childUrlset.Url...)
			}
		}
	}
	return &urlset, err
}

func PrimeUrlset(urlset *Urlset) {
	if *verbose {
		var top int
		m := int(*max)
		l := len(urlset.Url)
		if m > 0 && l > m {
			top = m
		} else {
			top = l
		}
		log.Println("URLs in sitemap:", l, "- URLs to prime:", top)
	}
	for _, u := range urlset.Url {
		sem <- true
		wg.Add(1)
		go PrimeUrl(u)
	}
	wg.Wait()
}

func PrimeUrl(u Url) error {
	var (
		err    error
		found  = false
		weight = int(u.Priority * 100)
	)
	if *localDir != "" {
		var parsed *url.URL
		parsed, err = url.ParseWithReference(u.Loc)
		if err == nil {
			joined := path.Join(*localDir, parsed.Path, *localSuffix)
			if _, err = os.Lstat(joined); err == nil {
				found = true
				if *verbose {
					log.Printf("Exists (weight %d) %s\n", weight, u.Loc)
				}
			}
		}
	}
	if !found {
		if *verbose {
			log.Printf("Get (weight %d) %s\n", weight, u.Loc)
		}
		res, err := Get(u.Loc)
		if err != nil {
			if !*nowarn {
				log.Printf("Error priming %s: %v\n", u.Loc, err)
			}
		} else {
			res.Body.Close()
			if res.Status != "200 OK" && !*nowarn {
				log.Printf("Bad response for %s: %s\n", u.Loc, res.Status)
			}
		}
		if *max > 0 {
			one <- true
		}
	}
	wg.Done()
	<-sem
	return err
}

func maxStopper() {
	count := uint(0)
	for {
		<-one
		count++
		if count == *max {
			log.Println("Uncached page prime limit reached; stopping")
			os.Exit(0)
		}
	}
}

func main() {
	var (
		urlset *Urlset
		err    error
	)
	flag.Parse()
	if flag.NArg() == 0 {
		fmt.Println("Optimus Cache Prime", version)
		fmt.Println("http://patrickmylund.com/projects/ocp/")
		fmt.Println("-----")
		flag.Usage()
		fmt.Println("")
		fmt.Println("Examples:")
		fmt.Println(" ", os.Args[0], "sitemap.xml")
		fmt.Println(" ", os.Args[0], "http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "-c 10 http://mysite.com/sitemap.xml.gz")
		fmt.Println(" ", os.Args[0], "-l /var/www/mysite.com/wp-content/cache/supercache/ http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "-l /var/www/mysite.com/wp-content/w3tc/pgcache/ -ls _index.html http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "--print http://mysite.com/sitemap.xml | xargs curl -I")
		fmt.Println("")
		fmt.Println("If specifying a sitemap URL, make sure to prepend http:// or https://")
		return
	}
	if *max > 0 {
		one = make(chan bool)
	}
	sem = make(chan bool, *throttle)
	path := flag.Arg(0)
	urlset, err = GetUrlsFromSitemap(path, true)
	if err != nil {
		fmt.Println("Error:", err)
	} else {
		sort.Sort(urlset)
		if *printurls {
			for _, v := range urlset.Url {
				fmt.Println(v.Loc)
			}
		} else {
			if *max > 0 {
				go maxStopper()
			}
			PrimeUrlset(urlset)
		}
	}
}
<commit_msg>gofix for tip<commit_after>package main

import (
	"compress/gzip"
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strings"
	"sync"
)

const (
	version   = "2.5"
	useragent = "Optimus Cache Prime/" + version + " (http://patrickmylund.com/projects/ocp/)"
)

var (
	one    chan bool
	sem    chan bool
	wg     = &sync.WaitGroup{}
	client = http.DefaultClient

	throttle    *uint   = flag.Uint("c", 1, "URLs to prime at once")
	max         *uint   = flag.Uint("max", 0, "maximum number of uncached URLs to prime")
	localDir    *string = flag.String("l", "", "directory containing cached files (relative file names, i.e. /about/ -> <path>/about/index.html)")
	localSuffix *string = flag.String("ls", "index.html", "suffix of locally cached files")
	verbose     *bool   = flag.Bool("v", false, "show additional information about the priming process")
	nowarn      *bool   = flag.Bool("no-warn", false, "do not warn about pages that were not primed successfully")
	printurls   *bool   = flag.Bool("print", false, "(exclusive) just print the sorted URLs (can be used with xargs)")
)

type Sitemap struct {
	Loc string `xml:"loc"`
	// Lastmod string `xml:"lastmod"`
}

type Url struct {
	Loc string `xml:"loc"`
	// Lastmod string `xml:"lastmod"`
	// Changefreq string `xml:"changefreq"`
	Priority float64 `xml:"priority"`
}

type Urlset struct {
	XMLName xml.Name  "urlset"
	Sitemap []Sitemap `xml:"sitemap"`
	Url     []Url     `xml:"url"`
}

// Functions needed by sort.Sort
func (u Urlset) Len() int {
	return len(u.Url)
}

func (u Urlset) Swap(i, j int) {
	u.Url[i], u.Url[j] = u.Url[j], u.Url[i]
}

func (u Urlset) Less(i, j int) bool {
	return u.Url[i].Priority > u.Url[j].Priority
}

func Get(url string) (*http.Response, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Add("User-Agent", useragent)
	return client.Do(req)
}

func GetUrlsFromSitemap(path string, follow bool) (*Urlset, error) {
	var (
		urlset Urlset
		f      io.ReadCloser
		err    error
		res    *http.Response
	)
	if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
		if *verbose {
			log.Println("Downloading", path)
		}
		res, err = Get(path)
		if err != nil {
			return nil, err
		}
		if res.Status != "200 OK" {
			return nil, fmt.Errorf("HTTP %s", res.Status)
		}
		f = res.Body
	} else {
		f, err = os.Open(path)
		if err != nil {
			return nil, err
		}
	}
	defer f.Close()
	if strings.HasSuffix(path, ".gz") {
		if *verbose {
			log.Println("Extracting compressed data")
		}
		f, err = gzip.NewReader(f)
		if err != nil {
			return nil, err
		}
		defer f.Close()
	}
	data, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	err = xml.Unmarshal(data, &urlset)
	if err == nil && follow && len(urlset.Sitemap) > 0 { // This is a sitemapindex
		ch := make(chan *Urlset, len(urlset.Sitemap))
		if *verbose {
			log.Printf("%s is a Sitemapindex\n", path)
		}
		for _, v := range urlset.Sitemap {
			sem <- true
			if *verbose {
				log.Printf("Adding URLs from child sitemap %s\n", v.Loc)
			}
			go func(loc string) {
				// Follow is false as Sitemapindex spec says sitemapindex children are illegal
				ourlset, err := GetUrlsFromSitemap(loc, false)
				if err != nil {
					log.Printf("Error getting Urlset from sitemap %s: %s", loc, err)
					ch <- nil
				} else {
					ch <- ourlset
				}
				<-sem
			}(v.Loc)
		}
		// Add every URL from each Urlset to the main Urlset
		for i := 0; i < len(urlset.Sitemap); i++ {
			childUrlset := <-ch
			if childUrlset != nil {
				urlset.Url = append(urlset.Url, childUrlset.Url...)
			}
		}
	}
	return &urlset, err
}

func PrimeUrlset(urlset *Urlset) {
	if *verbose {
		var top int
		m := int(*max)
		l := len(urlset.Url)
		if m > 0 && l > m {
			top = m
		} else {
			top = l
		}
		log.Println("URLs in sitemap:", l, "- URLs to prime:", top)
	}
	for _, u := range urlset.Url {
		sem <- true
		wg.Add(1)
		go PrimeUrl(u)
	}
	wg.Wait()
}

func PrimeUrl(u Url) error {
	var (
		err    error
		found  = false
		weight = int(u.Priority * 100)
	)
	if *localDir != "" {
		var parsed *url.URL
		parsed, err = url.ParseWithFragment(u.Loc)
		if err == nil {
			joined := path.Join(*localDir, parsed.Path, *localSuffix)
			if _, err = os.Lstat(joined); err == nil {
				found = true
				if *verbose {
					log.Printf("Exists (weight %d) %s\n", weight, u.Loc)
				}
			}
		}
	}
	if !found {
		if *verbose {
			log.Printf("Get (weight %d) %s\n", weight, u.Loc)
		}
		res, err := Get(u.Loc)
		if err != nil {
			if !*nowarn {
				log.Printf("Error priming %s: %v\n", u.Loc, err)
			}
		} else {
			res.Body.Close()
			if res.Status != "200 OK" && !*nowarn {
				log.Printf("Bad response for %s: %s\n", u.Loc, res.Status)
			}
		}
		if *max > 0 {
			one <- true
		}
	}
	wg.Done()
	<-sem
	return err
}

func maxStopper() {
	count := uint(0)
	for {
		<-one
		count++
		if count == *max {
			log.Println("Uncached page prime limit reached; stopping")
			os.Exit(0)
		}
	}
}

func main() {
	var (
		urlset *Urlset
		err    error
	)
	flag.Parse()
	if flag.NArg() == 0 {
		fmt.Println("Optimus Cache Prime", version)
		fmt.Println("http://patrickmylund.com/projects/ocp/")
		fmt.Println("-----")
		flag.Usage()
		fmt.Println("")
		fmt.Println("Examples:")
		fmt.Println(" ", os.Args[0], "sitemap.xml")
		fmt.Println(" ", os.Args[0], "http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "-c 10 http://mysite.com/sitemap.xml.gz")
		fmt.Println(" ", os.Args[0], "-l /var/www/mysite.com/wp-content/cache/supercache/ http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "-l /var/www/mysite.com/wp-content/w3tc/pgcache/ -ls _index.html http://mysite.com/sitemap.xml")
		fmt.Println(" ", os.Args[0], "--print http://mysite.com/sitemap.xml | xargs curl -I")
		fmt.Println("")
		fmt.Println("If specifying a sitemap URL, make sure to prepend http:// or https://")
		return
	}
	if *max > 0 {
		one = make(chan bool)
	}
	sem = make(chan bool, *throttle)
	path := flag.Arg(0)
	urlset, err = GetUrlsFromSitemap(path, true)
	if err != nil {
		fmt.Println("Error:", err)
	} else {
		sort.Sort(urlset)
		if *printurls {
			for _, v := range urlset.Url {
				fmt.Println(v.Loc)
			}
		} else {
			if *max > 0 {
				go maxStopper()
			}
			PrimeUrlset(urlset)
		}
	}
}
<|endoftext|>


<commit_before>package ole

import (
	"fmt"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

type OleError uintptr

func errstr(errno int) string {
	// ask windows for the remaining errors
	var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS
	b := make([]uint16, 300)
	n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil)
	if err != nil {
		return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err)
	}
	// trim terminating \r and \n
	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
	}
	return string(utf16.Decode(b[:n]))
}

func NewError(hr uintptr) OleError {
	return OleError(hr)
}

func (v OleError) Code() uintptr {
	return uintptr(v)
}

func (v OleError) Error() string {
	return errstr(int(v))
}

type DISPPARAMS struct {
	rgvarg            uintptr
	rgdispidNamedArgs uintptr
	cArgs             uint32
	cNamedArgs        uint32
}

type IUnknown struct {
	lpVtbl *pIUnknownVtbl
}

type pIUnknownVtbl struct {
	pQueryInterface uintptr
	pAddRef         uintptr
	pRelease        uintptr
}

type UnknownLike interface {
	QueryInterface(iid *GUID) (disp *IDispatch, err error)
	AddRef() int32
	Release() int32
}

func (v *IUnknown) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface(v, iid)
	return
}

func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) {
	disp, _ = queryInterface(v, iid)
	return
}

func (v *IUnknown) AddRef() int32 {
	return addRef(v)
}

func (v *IUnknown) Release() int32 {
	return release(v)
}

type IDispatch struct {
	lpVtbl *pIDispatchVtbl
}

type pIDispatchVtbl struct {
	pQueryInterface   uintptr
	pAddRef           uintptr
	pRelease          uintptr
	pGetTypeInfoCount uintptr
	pGetTypeInfo      uintptr
	pGetIDsOfNames    uintptr
	pInvoke           uintptr
}

func (v *IDispatch) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) MustQueryInterface(iid *GUID) (disp *IDispatch) {
	disp, _ = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IDispatch) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) {
	dispid, err = getIDsOfName(v, names)
	return
}

func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	result, err = invoke(v, dispid, dispatch, params...)
	return
}

func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) {
	c, err = getTypeInfoCount(v)
	return
}

func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) {
	tinfo, err = getTypeInfo(v)
	return
}

type ITypeInfo struct {
	lpVtbl *pITypeInfoVtbl
}

type pITypeInfoVtbl struct {
	pQueryInterface       uintptr
	pAddRef               uintptr
	pRelease              uintptr
	pGetTypeAttr          uintptr
	pGetTypeComp          uintptr
	pGetFuncDesc          uintptr
	pGetVarDesc           uintptr
	pGetNames             uintptr
	pGetRefTypeOfImplType uintptr
	pGetImplTypeFlags     uintptr
	pGetIDsOfNames        uintptr
	pInvoke               uintptr
	pGetDocumentation     uintptr
	pGetDllEntry          uintptr
	pGetRefTypeInfo       uintptr
	pAddressOfMember      uintptr
	pCreateInstance       uintptr
	pGetMops              uintptr
	pGetContainingTypeLib uintptr
	pReleaseTypeAttr      uintptr
	pReleaseFuncDesc      uintptr
	pReleaseVarDesc       uintptr
}

func (v *ITypeInfo) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *ITypeInfo) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *ITypeInfo) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) {
	hr, _, _ := syscall.Syscall(
		uintptr(v.lpVtbl.pGetTypeAttr),
		2,
		uintptr(unsafe.Pointer(v)),
		uintptr(unsafe.Pointer(&tattr)),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

type IConnectionPointContainer struct {
	lpVtbl *pIConnectionPointContainerVtbl
}

type pIConnectionPointContainerVtbl struct {
	pQueryInterface       uintptr
	pAddRef               uintptr
	pRelease              uintptr
	pEnumConnectionPoints uintptr
	pFindConnectionPoint  uintptr
}

func (v *IConnectionPointContainer) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IConnectionPointContainer) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IConnectionPointContainer) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) (err error) {
	err = NewError(E_NOTIMPL)
	return
}

func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) {
	hr, _, _ := syscall.Syscall(
		uintptr(v.lpVtbl.pFindConnectionPoint),
		3,
		uintptr(unsafe.Pointer(v)),
		uintptr(unsafe.Pointer(iid)),
		uintptr(unsafe.Pointer(point)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

type IProvideClassInfo struct {
	lpVtbl *pIProvideClassInfoVtbl
}

type pIProvideClassInfoVtbl struct {
	pQueryInterface uintptr
	pAddRef         uintptr
	pRelease        uintptr
	pGetClassInfo   uintptr
}

func (v *IProvideClassInfo) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IProvideClassInfo) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IProvideClassInfo) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) {
	cinfo, err = getClassInfo(v)
	return
}

type IConnectionPoint struct {
	lpVtbl *pIConnectionPointVtbl
}

type pIConnectionPointVtbl struct {
	pQueryInterface              uintptr
	pAddRef                      uintptr
	pRelease                     uintptr
	pGetConnectionInterface      uintptr
	pGetConnectionPointContainer uintptr
	pAdvise                      uintptr
	pUnadvise                    uintptr
	pEnumConnections             uintptr
}

func (v *IConnectionPoint) QueryInterface(iid *GUID) (disp *IDispatch, err error) {
	disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid)
	return
}

func (v *IConnectionPoint) AddRef() int32 {
	return addRef((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IConnectionPoint) Release() int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 {
	return release((*IUnknown)(unsafe.Pointer(v)))
}

func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) {
	hr, _, _ := syscall.Syscall(
		uintptr(v.lpVtbl.pAdvise),
		3,
		uintptr(unsafe.Pointer(v)),
		uintptr(unsafe.Pointer(unknown)),
		uintptr(unsafe.Pointer(&cookie)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) {
	hr, _, _ := syscall.Syscall(
		uintptr(v.lpVtbl.pAdvise),
		2,
		uintptr(unsafe.Pointer(v)),
		uintptr(cookie),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) {
	return NewError(E_NOTIMPL)
}

type VARIANT struct {
	VT         uint16 //  2
	wReserved1 uint16 //  4
	wReserved2 uint16 //  6
	wReserved3 uint16 //  8
	Val        int64  // 16
}

func (v *VARIANT) ToIUnknown() *IUnknown {
	return (*IUnknown)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToIDispatch() *IDispatch {
	return (*IDispatch)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToArray() *SafeArray {
	return (*SafeArray)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToString() string {
	return UTF16PtrToString(*(**uint16)(unsafe.Pointer(&v.Val)))
}

func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) {
	hr, _, _ := syscall.Syscall(
		unk.lpVtbl.pQueryInterface,
		3,
		uintptr(unsafe.Pointer(unk)),
		uintptr(unsafe.Pointer(iid)),
		uintptr(unsafe.Pointer(&disp)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func addRef(unk *IUnknown) int32 {
	ret, _, _ := syscall.Syscall(
		unk.lpVtbl.pAddRef,
		1,
		uintptr(unsafe.Pointer(unk)),
		0,
		0)
	return int32(ret)
}

func release(unk *IUnknown) int32 {
	ret, _, _ := syscall.Syscall(
		unk.lpVtbl.pRelease,
		1,
		uintptr(unsafe.Pointer(unk)),
		0,
		0)
	return int32(ret)
}

func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
	wnames := make([]*uint16, len(names))
	for i := 0; i < len(names); i++ {
		wnames[i] = syscall.StringToUTF16Ptr(names[i])
	}
	dispid = make([]int32, len(names))
	hr, _, _ := syscall.Syscall6(
		disp.lpVtbl.pGetIDsOfNames,
		6,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(unsafe.Pointer(&wnames[0])),
		uintptr(len(names)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&dispid[0])))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfoCount,
		2,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(&c)),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetTypeInfo,
		3,
		uintptr(unsafe.Pointer(disp)),
		uintptr(GetUserDefaultLCID()),
		uintptr(unsafe.Pointer(&tinfo)))
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) {
	hr, _, _ := syscall.Syscall(
		disp.lpVtbl.pGetClassInfo,
		2,
		uintptr(unsafe.Pointer(disp)),
		uintptr(unsafe.Pointer(&tinfo)),
		0)
	if hr != 0 {
		err = NewError(hr)
	}
	return
}

type EXCEPINFO struct {
	wCode             uint16
	wReserved         uint16
	bstrSource        *uint16
	bstrDescription   *uint16
	bstrHelpFile      *uint16
	dwHelpContext     uint32
	pvReserved        uintptr
	pfnDeferredFillIn uintptr
	scode             int32
}

type PARAMDATA struct {
	Name *int16
	Vt   uint16
}

type METHODDATA struct {
	Name     *uint16
	Data     *PARAMDATA
	Dispid   int32
	Meth     uint32
	CC       int32
	CArgs    uint32
	Flags    uint16
	VtReturn uint32
}

type INTERFACEDATA struct {
	MethodData *METHODDATA
	CMembers   uint32
}

func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
	var dispparams DISPPARAMS

	if dispatch&DISPATCH_PROPERTYPUT != 0 {
		dispnames := [1]int32{DISPID_PROPERTYPUT}
		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
		dispparams.cNamedArgs = 1
	}
	var vargs []VARIANT
	if len(params) > 0 {
		vargs = make([]VARIANT, len(params))
		for i, v := range params {
			//n := len(params)-i-1
			n := len(params) - i - 1
			VariantInit(&vargs[n])
			switch v.(type) {
			case bool:
				if v.(bool) {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
				} else {
					vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
				}
			case *bool:
				vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
			case byte:
				vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
			case *byte:
				vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
			case int16:
				vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
			case *int16:
				vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
			case uint16:
				vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
			case *uint16:
				vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
			case int, int32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
			case *int, *int32:
				vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
			case uint, uint32:
				vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
			case *uint, *uint32:
				vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
			case int64:
				vargs[n] = VARIANT{VT_I8, 0, 0, 0, int64(v.(int64))}
			case *int64:
				vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
			case uint64:
				vargs[n] = VARIANT{VT_UI8, 0, 0, 0, v.(int64)}
			case *uint64:
				vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
			case float32:
				vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
			case *float32:
				vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
			case float64:
				vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
			case *float64:
				vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
			case string:
				vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
			case *string:
				vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
			case *IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
			case **IDispatch:
				vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
			case nil:
				vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
			case *VARIANT:
				vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
			default:
				panic("unknown type")
			}
		}
		dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
		dispparams.cArgs = uint32(len(params))
	}

	result = new(VARIANT)
	var excepInfo EXCEPINFO
	VariantInit(result)
	hr, _, _ := syscall.Syscall9(
		disp.lpVtbl.pInvoke,
		9,
		uintptr(unsafe.Pointer(disp)),
		uintptr(dispid),
		uintptr(unsafe.Pointer(IID_NULL)),
		uintptr(GetUserDefaultLCID()),
		uintptr(dispatch),
		uintptr(unsafe.Pointer(&dispparams)),
		uintptr(unsafe.Pointer(result)),
		uintptr(unsafe.Pointer(&excepInfo)),
		0)
	if hr != 0 {
		err = NewError(hr)
		if excepInfo.bstrDescription != nil {
			bs := UTF16PtrToString(excepInfo.bstrDescription)
			println(bs)
		}
	}
	for _, varg := range vargs {
		if varg.VT == VT_BSTR && varg.Val != 0 {
			SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
		}
		/*
			if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
				*(params[n].(*string)) = UTF16PtrToString((*uint16)(unsafe.Pointer(uintptr(varg.Val))))
				println(*(params[n].(*string)))
			}
		*/
	}
	return
}

type Point struct {
	X int32
	Y int32
}

type Msg struct {
	Hwnd    uint32
	Message uint32
	Wparam  int32
	Lparam  int32
	Time    uint32
	Pt      Point
}

type TYPEDESC struct {
	Hreftype uint32
	VT       uint16
}

type IDLDESC struct {
	DwReserved uint32
	WIDLFlags  uint16
}

type TYPEATTR struct {
	Guid             GUID
	Lcid             uint32
	dwReserved       uint32
	MemidConstructor int32
	MemidDestructor  int32
	LpstrSchema      *uint16
	CbSizeInstance   uint32
	Typekind         int32
	CFuncs           uint16
	CVars            uint16
	CImplTypes       uint16
	CbSizeVft        uint16
	CbAlignment      uint16
	WTypeFlags       uint16
	WMajorVerNum     uint16
	WMinorVerNum     uint16
	TdescAlias       TYPEDESC
	IdldescType      IDLDESC
}
<commit_msg>Remove moved interfaces from ole.go file.<commit_after>package ole

import (
	"fmt"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

type OleError uintptr

func errstr(errno int) string {
	// ask windows for the remaining errors
	var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS
	b := make([]uint16, 300)
	n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil)
	if err != nil {
		return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err)
	}
	// trim terminating \r and \n
	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
	}
	return string(utf16.Decode(b[:n]))
}

func NewError(hr uintptr) OleError {
	return OleError(hr)
}

func (v OleError) Code() uintptr {
	return uintptr(v)
}

func (v OleError) Error() string {
	return errstr(int(v))
}

type DISPPARAMS struct {
	rgvarg            uintptr
	rgdispidNamedArgs uintptr
	cArgs             uint32
	cNamedArgs        uint32
}

type VARIANT struct {
	VT         uint16 //  2
	wReserved1 uint16 //  4
	wReserved2 uint16 //  6
	wReserved3 uint16 //  8
	Val        int64  // 16
}

func (v *VARIANT) ToIUnknown() *IUnknown {
	return (*IUnknown)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToIDispatch() *IDispatch {
	return (*IDispatch)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToArray() *SafeArray {
	return (*SafeArray)(unsafe.Pointer(uintptr(v.Val)))
}

func (v *VARIANT) ToString() string {
	return UTF16PtrToString(*(**uint16)(unsafe.Pointer(&v.Val)))
}

type EXCEPINFO struct {
	wCode             uint16
	wReserved         uint16
	bstrSource        *uint16
	bstrDescription   *uint16
	bstrHelpFile      *uint16
	dwHelpContext     uint32
	pvReserved        uintptr
	pfnDeferredFillIn uintptr
	scode             int32
}

type PARAMDATA struct {
	Name *int16
	Vt   uint16
}

type METHODDATA struct {
	Name     *uint16
	Data     *PARAMDATA
	Dispid   int32
	Meth     uint32
	CC       int32
	CArgs    uint32
	Flags    uint16
	VtReturn uint32
}

type INTERFACEDATA struct {
	MethodData *METHODDATA
	CMembers   uint32
}

type Point struct {
	X int32
	Y int32
}

type Msg struct {
	Hwnd    uint32
	Message uint32
	Wparam  int32
	Lparam  int32
	Time    uint32
	Pt      Point
}

type TYPEDESC struct {
	Hreftype uint32
	VT       uint16
}

type IDLDESC struct {
	DwReserved uint32
	WIDLFlags  uint16
}

type TYPEATTR struct {
	Guid             GUID
	Lcid             uint32
	dwReserved       uint32
	MemidConstructor int32
	MemidDestructor  int32
	LpstrSchema      *uint16
	CbSizeInstance   uint32
	Typekind         int32
	CFuncs           uint16
	CVars            uint16
	CImplTypes       uint16
	CbSizeVft        uint16
	CbAlignment      uint16
	WTypeFlags       uint16
	WMajorVerNum     uint16
	WMinorVerNum     uint16
	TdescAlias       TYPEDESC
	IdldescType      IDLDESC
}
<|endoftext|>