From 919d567362543483a4fa4b3dbab739c6693cffde Mon Sep 17 00:00:00 2001 From: Josh Dolitsky <josh@dolit.ski> Date: Mon, 8 Feb 2021 14:30:19 -0500 Subject: [PATCH 1/2] Add 'umoci copy' subcommand - Support for pulling oci:// URL into local store - Support for pushing from local store to registry - Downloads blobs only when not found in local store - Currently only supports OCI v1 manifest media type - Does not support docker:// URLs or Docker manifests - Does not yet support chunked blob uploading Signed-off-by: Josh Dolitsky <josh@dolit.ski> --- cmd/umoci/copy-local-to-remote.go | 184 +++++++++++++++++++++++++ cmd/umoci/copy-remote-to-local.go | 217 ++++++++++++++++++++++++++++++ cmd/umoci/copy.go | 200 +++++++++++++++++++++++++++ cmd/umoci/main.go | 1 + 4 files changed, 602 insertions(+) create mode 100644 cmd/umoci/copy-local-to-remote.go create mode 100644 cmd/umoci/copy-remote-to-local.go create mode 100644 cmd/umoci/copy.go diff --git a/cmd/umoci/copy-local-to-remote.go b/cmd/umoci/copy-local-to-remote.go new file mode 100644 index 000000000..3e36bc238 --- /dev/null +++ b/cmd/umoci/copy-local-to-remote.go @@ -0,0 +1,184 @@ +/* + * umoci: Umoci Modifies Open Containers' Images + * Copyright (C) 2016-2020 SUSE LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "github.com/apex/log" + "github.com/bloodorangeio/reggie" + v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/umoci/oci/cas/dir" + "github.com/opencontainers/umoci/oci/casext" + "github.com/pkg/errors" + "github.com/urfave/cli" +) + +// a.k.a. "push" +func copyLocalToRemote(ctx *cli.Context, local *parsedLocalReference, remote *parsedRemoteReference) error { + client, err := newRegistryClient(ctx, remote) + if err != nil { + return err + } + + engine, err := dir.Open(local.dir) + if err != nil { + return errors.Wrap(err, "open CAS") + } + engineExt := casext.NewEngine(engine) + defer engine.Close() + engineContext := context.Background() + + descriptorPaths, err := engineExt.ResolveReference(engineContext, local.tag) + if err != nil { + return err + } + + // TODO: in what scenario would this length be greater than 1?? + numDescriptorPaths := len(descriptorPaths) + if numDescriptorPaths == 0 { + return errors.New(fmt.Sprintf("Reference '%s' not found in index", local.tag)) + } else if numDescriptorPaths > 1 { + return errors.New(fmt.Sprintf("More than one entry for reference '%s' in index", local.tag)) + } + + manifestDescriptor := descriptorPaths[0].Descriptor() + manifestDigest := manifestDescriptor.Digest + log.Infof("Reference '%s' found in index, points to manifest %s", local.tag, manifestDigest) + + manifestReader, err := engine.GetBlob(engineContext, manifestDigest) + defer manifestReader.Close() + if err != nil { + return err + } + + manifestBytes, err := ioutil.ReadAll(manifestReader) + if err != nil { + return err + } + + // Parse into OCI Manifest + var manifest v1.Manifest + err = json.Unmarshal(manifestBytes, &manifest) + if err != nil { + return err + } + log.Infof("Manifest successfully loaded from local store") + + // Upload layers + numLayers := len(manifest.Layers) + log.Infof("Manifest layer list contains %d item(s)", numLayers) + for i, layer := range manifest.Layers { + layerDigest := layer.Digest + layerReader, err := engine.GetBlob(engineContext, layerDigest) + defer layerReader.Close() + if err != nil { + return err + } + log.Infof("Uploading layer %d/%d with digest %s from local store", i+1, numLayers, layerDigest) + + // Create upload session + req := client.NewRequest(reggie.POST, "/v2/<name>/blobs/uploads/") + resp, err := client.Do(req) + if err != nil { + return err + } + + layerBytes, err := ioutil.ReadAll(layerReader) + if err != nil { + return err + } + + // Monolithic upload + // TODO: support chunked uploading + req = client.NewRequest(reggie.PUT, resp.GetRelativeLocation()). + SetQueryParam("digest", layerDigest.String()). + SetHeader("Content-Type", "application/octet-stream"). + SetHeader("Content-Length", fmt.Sprint(layer.Size)). + SetBody(layerBytes) + resp, err = client.Do(req) + if err != nil { + return err + } + + statusCode := resp.StatusCode() + if statusCode != http.StatusCreated && statusCode != http.StatusAccepted { + return errors.New("Registry did not return 201 or 202 on layer upload") + } + } + + // Upload config if present + if manifest.Config.Size > 0 { + configDigest := manifest.Config.Digest + configReader, err := engine.GetBlob(engineContext, configDigest) + defer configReader.Close() + if err != nil { + return err + } + log.Infof("Uploading config %s", configDigest) + + // Create upload session + req := client.NewRequest(reggie.POST, "/v2/<name>/blobs/uploads/") + resp, err := client.Do(req) + if err != nil { + return err + } + + layerBytes, err := ioutil.ReadAll(configReader) + if err != nil { + return err + } + + // Monolithic upload + req = client.NewRequest(reggie.PUT, resp.GetRelativeLocation()). + SetQueryParam("digest", configDigest.String()). + SetHeader("Content-Type", "application/octet-stream"). + SetHeader("Content-Length", fmt.Sprint(manifest.Config.Size)). + SetBody(layerBytes) + resp, err = client.Do(req) + if err != nil { + return err + } + + statusCode := resp.StatusCode() + if statusCode != http.StatusCreated && statusCode != http.StatusAccepted { + return errors.New("Registry did not return 201 or 202 on config upload") + } + } + + // upload manifest + req := client.NewRequest(reggie.PUT, "/v2/<name>/manifests/<reference>", + reggie.WithReference(remote.tag)). + SetHeader("Content-Type", v1.MediaTypeImageManifest). + SetBody(manifestBytes) + resp, err := client.Do(req) + if err != nil { + return err + } + statusCode := resp.StatusCode() + if statusCode != http.StatusCreated && statusCode != http.StatusAccepted { + return errors.New("Registry did not return 201 or 202 on manifest upload") + } + + log.Infof("Successfully copied to remote %s", remote.host) + return nil +} diff --git a/cmd/umoci/copy-remote-to-local.go b/cmd/umoci/copy-remote-to-local.go new file mode 100644 index 000000000..b509e2ea1 --- /dev/null +++ b/cmd/umoci/copy-remote-to-local.go @@ -0,0 +1,217 @@ +/* + * umoci: Umoci Modifies Open Containers' Images + * Copyright (C) 2016-2020 SUSE LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "strings" + + "github.com/apex/log" + "github.com/bloodorangeio/reggie" + godigest "github.com/opencontainers/go-digest" + v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/umoci/oci/cas/dir" + "github.com/opencontainers/umoci/oci/casext" + "github.com/pkg/errors" + "github.com/urfave/cli" +) + +// a.k.a. "pull" +func copyRemoteToLocal(ctx *cli.Context, remote *parsedRemoteReference, local *parsedLocalReference) error { + client, err := newRegistryClient(ctx, remote) + if err != nil { + return err + } + + // Get a reference to the CAS. + dir.Create(local.dir) // TODO: handle this error? + engine, err := dir.Open(local.dir) + if err != nil { + return errors.Wrap(err, "open CAS") + } + engineExt := casext.NewEngine(engine) + defer engine.Close() + engineContext := context.Background() + + log.Infof("Checking if manifest available in registry") + req := client.NewRequest(reggie.HEAD, "/v2/<name>/manifests/<reference>", + reggie.WithReference(remote.tag)). + SetHeader("Accept", v1.MediaTypeImageManifest) + resp, err := client.Do(req) + if err != nil { + return err + } + expectedContentDigest := resp.Header().Get(contentDigestHeader) + log.Infof("Registry reports manifest with digest %s", expectedContentDigest) + parsedDigest, err := godigest.Parse(expectedContentDigest) + if err != nil { + return err + } + + // download manifest if it doesnt already exist is local store + var manifestBytes []byte + manifestReader, err := engine.GetBlob(engineContext, parsedDigest) + defer manifestReader.Close() + if err != nil { + // TODO: better than this error check + if !strings.Contains(err.Error(), "no such file") { + return err + } + // Fetch the raw manifest from registry and validate its digest + log.Infof("Downloading manifest from registry") + req = client.NewRequest(reggie.GET, "/v2/<name>/manifests/<reference>", + reggie.WithReference(remote.tag)). + SetHeader("Accept", v1.MediaTypeImageManifest) + resp, err = client.Do(req) + if err != nil { + return err + } + if h := resp.Header().Get(contentDigestHeader); h != expectedContentDigest { + return errors.New( + fmt.Sprintf("Possible MITM attack: the %s header was %s on manifest HEAD, but %s on manifest GET", + contentDigestHeader, expectedContentDigest, h)) + } + actualContentDigest := godigest.FromBytes(resp.Body()).String() + if actualContentDigest != expectedContentDigest { + return errors.New( + fmt.Sprintf("Possible MITM attack: the real digest of the downloaded manifest was %s", + actualContentDigest)) + } + log.Debugf("actual manifest digest matches expected digest (%s)", expectedContentDigest) + + // Note: only "application/vnd.oci.image.manifest.v1+json" supported for now + mediaType := resp.Header().Get(manifestMediaTypeHeader) + if mediaType != v1.MediaTypeImageManifest { + return errors.New( + fmt.Sprintf("Content-Type header for image manifest invalid: %s", mediaType)) + } + + d, s, err := engine.PutBlob(engineContext, bytes.NewReader(resp.Body())) + if err != nil { + return err + } + log.Debugf("blob saved to local store, digest: %s, size: %d", d, s) + + manifestBytes = resp.Body() + } else { + // load directly from CAS + log.Infof("Manifest with digest %s already exists in local store", expectedContentDigest) + manifestBytes, err = ioutil.ReadAll(manifestReader) + if err != nil { + return err + } + } + + // Parse into OCI Manifest + var manifest v1.Manifest + err = json.Unmarshal(manifestBytes, &manifest) + if err != nil { + return err + } + + // Parse into OCI Descriptor + var descriptor v1.Descriptor + err = json.Unmarshal(manifestBytes, &descriptor) + if err != nil { + return err + } + descriptor.MediaType = v1.MediaTypeImageManifest + descriptor.Digest = parsedDigest + descriptor.Size = int64(len(manifestBytes)) + + // Patiently and synchronously fetch layer blobs from registry, verify, and store them + numLayers := len(manifest.Layers) + log.Infof("Manifest layer list contains %d item(s)", numLayers) + for i, layer := range manifest.Layers { + layerDigest := layer.Digest + layerReader, err := engine.GetBlob(engineContext, layerDigest) + if err != nil { + if !strings.Contains(err.Error(), "no such file") { + return err + } + log.Infof("Copying layer %d/%d with digest %s", i+1, numLayers, layerDigest) + req = client.NewRequest(reggie.GET, "/v2/<name>/blobs/<digest>", + reggie.WithDigest(layerDigest.String())) + resp, err = client.Do(req) + if err != nil { + return err + } + + if d := godigest.FromBytes(resp.Body()).String(); d != layerDigest.String() { + return errors.New( + fmt.Sprintf("Possible MITM attack: the real digest of the downloaded layer was %s", d)) + } + log.Debugf("actual layer digest matches expected digest (%s)", layerDigest) + + d, s, err := engine.PutBlob(engineContext, bytes.NewReader(resp.Body())) + if err != nil { + return err + } + log.Debugf("blob saved to local store, digest: %s, size: %d", d, s) + continue + } + layerReader.Close() + log.Infof("Layer %d/%d with digest %s already exists in local store", i+1, numLayers, layerDigest) + } + + // Fetch config blob if exists + if manifest.Config.Size > 0 { + configDigest := manifest.Config.Digest + configReader, err := engine.GetBlob(engineContext, configDigest) + defer configReader.Close() + if err != nil { + if !strings.Contains(err.Error(), "no such file") { + return err + } + log.Infof("Copying config with digest %s", configDigest) + req = client.NewRequest(reggie.GET, "/v2/<name>/blobs/<digest>", + reggie.WithDigest(configDigest.String())) + resp, err = client.Do(req) + if err != nil { + return err + } + + if d := godigest.FromBytes(resp.Body()).String(); d != configDigest.String() { + return errors.New( + fmt.Sprintf("Possible MITM attack: the real digest of the downloaded config was %s", d)) + } + log.Debugf("actual config digest matches expected digest (%s)", configDigest) + + d, s, err := engine.PutBlob(engineContext, bytes.NewReader(resp.Body())) + if err != nil { + return err + } + log.Debugf("blob saved to local store, digest: %s, size: %d", d, s) + } else { + log.Infof("Config with digest %s already exists in local store", configDigest) + } + } + + // Add reference to index + log.Infof("Saving reference '%s' to index in %s", local.tag, local.dir) + err = engineExt.UpdateReference(engineContext, local.tag, descriptor) + if err != nil { + return err + } + + return nil +} diff --git a/cmd/umoci/copy.go b/cmd/umoci/copy.go new file mode 100644 index 000000000..a806ce594 --- /dev/null +++ b/cmd/umoci/copy.go @@ -0,0 +1,200 @@ +/* + * umoci: Umoci Modifies Open Containers' Images + * Copyright (C) 2016-2020 SUSE LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "fmt" + "net/url" + "strings" + + "github.com/apex/log" + "github.com/bloodorangeio/reggie" + "github.com/opencontainers/umoci" + "github.com/opencontainers/umoci/oci/casext" + "github.com/pkg/errors" + "github.com/urfave/cli" +) + +var copyCommand = cli.Command{ + Name: "copy", + Aliases: []string{"cp"}, + Usage: "copy an image into OCI layout", + ArgsUsage: `--layout <image-path> + +Where "<image-path>" is the path to the OCI layout.`, + + Before: func(ctx *cli.Context) error { + if ctx.NArg() != 2 { + return errors.Errorf("invalid number of positional arguments: expected <src> <dest>") + } + if ctx.Args().First() == "" { + return errors.Errorf("src cannot be empty") + } + ctx.App.Metadata["src"] = ctx.Args().Get(0) + if ctx.Args().First() == "" { + return errors.Errorf("dest cannot be empty") + } + ctx.App.Metadata["dest"] = ctx.Args().Get(1) + return nil + }, + + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "username", + Usage: "authentication username", + Required: false, + }, + cli.StringFlag{ + Name: "password", + Usage: "authentication password", + Required: false, + }, + cli.BoolFlag{ + Name: "plain-http", + Usage: "use plain HTTP for registry connection", + }, + cli.BoolFlag{ + Name: "trace-requests", + Usage: "print detailed HTTP(s) logs from registry requests", + }, + }, + + Action: copy, +} + +func copy(ctx *cli.Context) error { + src := ctx.App.Metadata["src"].(string) + dest := ctx.App.Metadata["dest"].(string) + remote, err := parseRemoteReference(src) + if err != nil { + // Assume the args are flipped (remote to local vs. local to remote) + if err == badRemoteURLError { + remote, err = parseRemoteReference(dest) + if err != nil { + return err + } + local, err := parseLocalReference(src) + if err != nil { + return err + } + return copyLocalToRemote(ctx, local, remote) + } + return err + } + local, err := parseLocalReference(dest) + if err != nil { + return err + } + return copyRemoteToLocal(ctx, remote, local) +} + +const ( + manifestMediaTypeHeader = "Content-Type" + contentDigestHeader = "Docker-Content-Digest" +) + +var ( + badRemoteURLError = errors.New("remote URLs must be prefixed with oci://") +) + +type parsedRemoteReference struct { + host string + namespace string + tag string +} + +type parsedLocalReference struct { + dir string + tag string +} + +// parse something in the form of "oci://localhost:5000/opensuse:42.2" +func parseRemoteReference(raw string) (*parsedRemoteReference, error) { + u, err := url.Parse(raw) + if err != nil { + return nil, err + } + + if u.Scheme != "oci" { + return nil, badRemoteURLError + } + + host := u.Host + parts := strings.Split(u.Path, ":") + namespace := strings.Trim(strings.Join(parts[0:len(parts)-1], ":"), "/") + tag := parts[len(parts)-1] + + ref := parsedRemoteReference{ + host: host, + namespace: namespace, + tag: tag, + } + return &ref, nil +} + +// parse something in the form "opensuse:42.2" +// TODO: copied/modified from utils_ux.go +func parseLocalReference(raw string) (*parsedLocalReference, error) { + var dir, tag string + sep := strings.Index(raw, ":") + if sep == -1 { + dir = raw + tag = "latest" + } else { + dir = raw[:sep] + tag = raw[sep+1:] + } + + // Verify directory value. + if dir == "" { + return nil, errors.New("path is empty") + } + + // Verify tag value. + if !casext.IsValidReferenceName(tag) { + return nil, errors.New(fmt.Sprintf("tag contains invalid characters: '%s'", tag)) + } + if tag == "" { + return nil, errors.New("tag is empty") + } + + ref := parsedLocalReference{ + dir: dir, + tag: tag, + } + return &ref, nil +} + +// construct a registry client from context +func newRegistryClient(ctx *cli.Context, remote *parsedRemoteReference) (*reggie.Client, error) { + scheme := "https" + if ctx.Bool("plain-http") { + scheme = "http" + } + registryAddress := scheme + "://" + remote.host + log.Debugf("Registry address: %s, namespace: %s, tag: %s", registryAddress, remote.namespace, remote.tag) + userAgent := fmt.Sprintf("umoci %s", umoci.FullVersion()) + username := ctx.String("username") + password := ctx.String("password") + traceRequests := ctx.Bool("trace-requests") + return reggie.NewClient(registryAddress, + reggie.WithDefaultName(remote.namespace), + reggie.WithUserAgent(userAgent), + reggie.WithUsernamePassword(username, password), + reggie.WithDebug(traceRequests)) +} diff --git a/cmd/umoci/main.go b/cmd/umoci/main.go index e3b614657..c06cc93fc 100644 --- a/cmd/umoci/main.go +++ b/cmd/umoci/main.go @@ -116,6 +116,7 @@ func Main(args []string) error { statCommand, rawSubcommand, insertCommand, + copyCommand, } app.Metadata = map[string]interface{}{} From d2f6056482314a44724ac2151622843881a18c45 Mon Sep 17 00:00:00 2001 From: Josh Dolitsky <josh@dolit.ski> Date: Mon, 8 Feb 2021 14:31:00 -0500 Subject: [PATCH 2/2] Check in go.mod, go.sum, vendor/ Signed-off-by: Josh Dolitsky <josh@dolit.ski> --- go.mod | 3 +- go.sum | 10 +- .../bloodorangeio/reggie/.gitignore | 25 + .../github.com/bloodorangeio/reggie/LICENSE | 201 + .../github.com/bloodorangeio/reggie/Makefile | 7 + .../github.com/bloodorangeio/reggie/README.md | 260 + .../github.com/bloodorangeio/reggie/auth.go | 97 + .../github.com/bloodorangeio/reggie/client.go | 171 + .../github.com/bloodorangeio/reggie/error.go | 14 + vendor/github.com/bloodorangeio/reggie/go.mod | 9 + vendor/github.com/bloodorangeio/reggie/go.sum | 12 + .../bloodorangeio/reggie/methods.go | 28 + .../bloodorangeio/reggie/reggie.png | Bin 0 -> 1547 bytes .../bloodorangeio/reggie/request.go | 110 + .../bloodorangeio/reggie/response.go | 62 + .../bloodorangeio/reggie/v2-registry-auth.png | Bin 0 -> 11063 bytes .../github.com/go-resty/resty/v2/.gitignore | 28 + .../github.com/go-resty/resty/v2/.travis.yml | 21 + .../github.com/go-resty/resty/v2/BUILD.bazel | 36 + vendor/github.com/go-resty/resty/v2/LICENSE | 21 + vendor/github.com/go-resty/resty/v2/README.md | 819 ++ vendor/github.com/go-resty/resty/v2/WORKSPACE | 27 + vendor/github.com/go-resty/resty/v2/client.go | 946 ++ vendor/github.com/go-resty/resty/v2/go.mod | 3 + .../go-resty/resty/v2/middleware.go | 514 + .../github.com/go-resty/resty/v2/redirect.go | 101 + .../github.com/go-resty/resty/v2/request.go | 724 ++ .../github.com/go-resty/resty/v2/response.go | 160 + vendor/github.com/go-resty/resty/v2/resty.go | 40 + vendor/github.com/go-resty/resty/v2/retry.go | 180 + vendor/github.com/go-resty/resty/v2/trace.go | 111 + vendor/github.com/go-resty/resty/v2/util.go | 333 + .../mitchellh/mapstructure/.travis.yml | 8 + .../mitchellh/mapstructure/CHANGELOG.md | 21 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 217 + .../mitchellh/mapstructure/error.go | 50 + .../github.com/mitchellh/mapstructure/go.mod | 1 + .../mitchellh/mapstructure/mapstructure.go | 1149 ++ vendor/golang.org/x/net/publicsuffix/list.go | 181 + vendor/golang.org/x/net/publicsuffix/table.go | 10150 ++++++++++++++++ vendor/modules.txt | 8 + 43 files changed, 16922 insertions(+), 3 deletions(-) create mode 100644 vendor/github.com/bloodorangeio/reggie/.gitignore create mode 100644 vendor/github.com/bloodorangeio/reggie/LICENSE create mode 100644 vendor/github.com/bloodorangeio/reggie/Makefile create mode 100644 vendor/github.com/bloodorangeio/reggie/README.md create mode 100644 vendor/github.com/bloodorangeio/reggie/auth.go create mode 100644 vendor/github.com/bloodorangeio/reggie/client.go create mode 100644 vendor/github.com/bloodorangeio/reggie/error.go create mode 100644 vendor/github.com/bloodorangeio/reggie/go.mod create mode 100644 vendor/github.com/bloodorangeio/reggie/go.sum create mode 100644 vendor/github.com/bloodorangeio/reggie/methods.go create mode 100644 vendor/github.com/bloodorangeio/reggie/reggie.png create mode 100644 vendor/github.com/bloodorangeio/reggie/request.go create mode 100644 vendor/github.com/bloodorangeio/reggie/response.go create mode 100644 vendor/github.com/bloodorangeio/reggie/v2-registry-auth.png create mode 100644 vendor/github.com/go-resty/resty/v2/.gitignore create mode 100644 vendor/github.com/go-resty/resty/v2/.travis.yml create mode 100644 vendor/github.com/go-resty/resty/v2/BUILD.bazel create mode 100644 vendor/github.com/go-resty/resty/v2/LICENSE create mode 100644 vendor/github.com/go-resty/resty/v2/README.md create mode 100644 vendor/github.com/go-resty/resty/v2/WORKSPACE create mode 100644 vendor/github.com/go-resty/resty/v2/client.go create mode 100644 vendor/github.com/go-resty/resty/v2/go.mod create mode 100644 vendor/github.com/go-resty/resty/v2/middleware.go create mode 100644 vendor/github.com/go-resty/resty/v2/redirect.go create mode 100644 vendor/github.com/go-resty/resty/v2/request.go create mode 100644 vendor/github.com/go-resty/resty/v2/response.go create mode 100644 vendor/github.com/go-resty/resty/v2/resty.go create mode 100644 vendor/github.com/go-resty/resty/v2/retry.go create mode 100644 vendor/github.com/go-resty/resty/v2/trace.go create mode 100644 vendor/github.com/go-resty/resty/v2/util.go create mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 vendor/github.com/mitchellh/mapstructure/CHANGELOG.md create mode 100644 vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/mitchellh/mapstructure/go.mod create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 vendor/golang.org/x/net/publicsuffix/list.go create mode 100644 vendor/golang.org/x/net/publicsuffix/table.go diff --git a/go.mod b/go.mod index 7cd3361bf..6227500e7 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ module github.com/opencontainers/umoci -go 1.14 +go 1.15 require ( github.com/apex/log v1.4.0 + github.com/bloodorangeio/reggie v0.5.0 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/cyphar/filepath-securejoin v0.2.2 github.com/docker/go-units v0.4.0 diff --git a/go.sum b/go.sum index 9a2e6823f..125f3b989 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/bloodorangeio/reggie v0.5.0 h1:TZzqCxav8qzZCVwRDW8AQHXI3+GgVQFlYBvKJps0uQo= +github.com/bloodorangeio/reggie v0.5.0/go.mod h1:u7HqihAZy812d6ysiuDawpHJYtpGSNL2E/4Cyu/mtZg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= @@ -29,6 +31,8 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-resty/resty/v2 v2.1.0 h1:Z6IefCpUMfnvItVJaJXWv/pMiiD11So35QgwEELsldE= +github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -54,8 +58,6 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= -github.com/klauspost/compress v1.10.9 h1:pPRt1Z78crspaHISkpSSHjDlx+Tt9suHe519dsI0vF4= -github.com/klauspost/compress v1.10.9/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A= @@ -85,12 +87,15 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/distribution-spec v1.0.0-rc0.0.20200108182153-219f20cbcfa1/go.mod h1:copR2flp+jTEvQIFMb6MIx45OkrxzqyjszPDT3hx/5Q= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -156,6 +161,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= diff --git a/vendor/github.com/bloodorangeio/reggie/.gitignore b/vendor/github.com/bloodorangeio/reggie/.gitignore new file mode 100644 index 000000000..bea4b527c --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/.gitignore @@ -0,0 +1,25 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +*.html + +# Dependency directories (remove the comment below to include it) +vendor/ + +# JetBrains +.idea/ + +# Mac +.DS_Store + +# Vim +tags diff --git a/vendor/github.com/bloodorangeio/reggie/LICENSE b/vendor/github.com/bloodorangeio/reggie/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/bloodorangeio/reggie/Makefile b/vendor/github.com/bloodorangeio/reggie/Makefile new file mode 100644 index 000000000..95c6b6214 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/Makefile @@ -0,0 +1,7 @@ +.PHONY: test +test: + go test -v -race -cover -coverprofile=coverage.out -covermode=atomic ./... + +.PHONY: covhtml +covhtml: + go tool cover -html=coverage.out -o coverage.html diff --git a/vendor/github.com/bloodorangeio/reggie/README.md b/vendor/github.com/bloodorangeio/reggie/README.md new file mode 100644 index 000000000..74ef9561b --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/README.md @@ -0,0 +1,260 @@ +# Reggie + +[](https://github.com/bloodorangeio/reggie/actions?query=workflow%3Abuild) [](https://godoc.org/github.com/bloodorangeio/reggie) + + + +Reggie is a dead simple Go HTTP client designed to be used against [OCI Distribution](https://github.com/opencontainers/distribution-spec), built on top of [Resty](https://github.com/go-resty/resty). + +There is also built-in support for both basic auth and "Docker-style" token auth. + +*Note: Authentication/authorization is not part of the distribution spec, but it has been implemented similarly across registry providers targeting the Docker client.* + +## Getting Started + +First import the library: +```go +import "github.com/bloodorangeio/reggie" +``` + +Then construct a client: + +```go +client, err := reggie.NewClient("http://localhost:5000") +``` + +You may also construct the client with a number of options related to authentication, etc: + +```go +client, err := reggie.NewClient("https://r.mysite.io", + reggie.WithUsernamePassword("myuser", "mypass"), // registry credentials + reggie.WIthDefaultName("myorg/myrepo"), // default repo name + reggie.WithDebug(true)) // enable debug logging +``` + +## Making Requests + +Reggie uses a domain-specific language to supply various parts of the URI path in order to provide visual parity with [the spec](https://github.com/opencontainers/distribution-spec/blob/master/spec.md). + +For example, to list all tags for the repo `megacorp/superapp`, you might do the following: + +```go +req := client.NewRequest(reggie.GET, "/v2/<name>/tags/list", + reggie.WithName("megacorp/superapp")) +``` + +This will result in a request object built for `GET /v2/megacorp/superapp/tags/list`. + +Finally, execute the request, which will return a response object: +```go +resp, err := client.Do(req) +fmt.Println("Status Code:", resp.StatusCode()) +``` + +## Path Substitutions + +Below is a table of all of the possible URI parameter substitutions and associated methods: + + +| URI Parameter | Description | Option method | +|-|-|-| +| `<name>` | Namespace of a repository within a registry | `WithDefaultName` (`Client`) or<br>`WithName` (`Request`) | +| `<digest>` | Content-addressable identifier | `WithDigest` (`Request`) | +| `<reference>` | Tag or digest | `WithReference` (`Request`) | +| `<session_id>` | Session ID for upload | `WithSessionID` (`Request`) | + +## Auth + +All requests are first attempted without any authentication. If an endpoint returns a `401 Unauthorized`, and the client has been constructed with a username and password (via `reggie.WithUsernamePassword`), the request is retried with an `Authorization` header. + +Included in the 401 response, registries should return a `Www-Authenticate` header describing how to to authenticate. + +For more info about the `Www-Authenticate` header and general HTTP auth topics, please see IETF RFCs [7235](https://tools.ietf.org/html/rfc7235) and [6749](https://tools.ietf.org/html/rfc6749). + +### Basic Auth + + If the `Www-Authenticate` header contains the string "Basic", then the header used in the retried request will be formatted as `Authorization: Basic <credentials>`, where credentials is the base64 encoding of the username and password joined by a single colon. + +### "Docker-style" Token Auth +*Note: most commercial registries use this method.* + +If the`Www-Authenticate` contains the string "Bearer", an attempt is made to retrieve a token from an authorization service endpoint, the URL of which should be provided in the `Realm` field of the header. The header then used in the retried request will be formatted as `Authorization: Bearer <token>`, where token is the one returned from the token endpoint. + +Here is a visual of this auth flow copied from the [Docker docs](https://docs.docker.com/registry/spec/auth/token/): + + + +#### Custom Auth Scope + + It may be necessary to override the `scope` obtained from the `Www-Authenticate` header in the registry's response. This can be done on the client level: + + ``` +client, err := reggie.NewClient("http://localhost:5000", + reggie.WithAuthScope("repository:mystuff/myrepo:pull,push")) + ``` + +## Other Features + +### Method Chaining + +Each of the types provided by this package (`Client`, `Request`, & `Response`) are all built on top of types provided by Resty. In most cases, methods provided by Resty should just work on these objects (see the [godoc](https://godoc.org/github.com/go-resty/resty) for more info). + +The following commonly-used methods have been wrapped in order to allow for method chaining: + +- `req.Header` +- `req.SetQueryParam` +- `req.SetBody` + +The following is an example of using method chaining to build a request: +```go +req := client.NewRequest(reggie.PUT, lastResponse.GetRelativeLocation()). + SetHeader("Content-Length", configContentLength). + SetHeader("Content-Type", "application/octet-stream"). + SetQueryParam("digest", configDigest). + SetBody(configContent) +``` + +### Location Header Parsing + +For certain types of requests, such as chunked uploads, the `Location` header is needed in order to make follow-up requests. + +Reggie provides two helper methods to obtain the redirect location: +```go +fmt.Println("Relative location:", resp.GetRelativeLocation()) // /v2/... +fmt.Println("Absolute location:", resp.GetAbsoluteLocation()) // https://... +``` + +### Error Parsing + +On the response object, you may call the `Errors()` method which will attempt to parse the response body into a list of [OCI ErrorInfo](https://github.com/opencontainers/distribution-spec/blob/master/specs-go/v1/error.go#L36) objects: +```go +for _, e := range resp.Errors() { + fmt.Println("Code:", e.Code) + fmt.Println("Message:", e.Message) + fmt.Println("Detail:", e.Detail) +} +``` + +### HTTP Method Constants + +Simply-named constants are provided for the following HTTP request methods: +```go +reggie.GET // "GET" +reggie.PUT // "PUT" +reggie.PATCH // "PATCH" +reggie.DELETE // "DELETE" +reggie.POST // "POST" +reggie.HEAD // "HEAD" +reggie.OPTIONS // "OPTIONS" +``` + +### Custom User-Agent + +By default, requests made by Reggie will use a default value for the `User-Agent` header in order for registry providers to identify incoming requests: +``` +User-Agent: reggie/0.3.0 (https://github.com/bloodorangeio/reggie) +``` + +If you wish to use a custom value for `User-Agent`, such as "my-agent" for example, you can do the following: +```go +client, err := reggie.NewClient("http://localhost:5000", + reggie.WithUserAgent("my-agent")) +``` + +## Example + +The following is an example of a resumable blob upload and subsequent manifest upload: + +```go +package main + +import ( + "fmt" + + "github.com/bloodorangeio/reggie" + godigest "github.com/opencontainers/go-digest" +) + +func main() { + // construct client pointing to your registry + client, err := reggie.NewClient("http://localhost:5000", + reggie.WithDefaultName("myorg/myrepo"), + reggie.WithDebug(true)) + if err != nil { + panic(err) + } + + // get the session URL + req := client.NewRequest(reggie.POST, "/v2/<name>/blobs/uploads/") + resp, err := client.Do(req) + if err != nil { + panic(err) + } + + // a blob for an empty manifest config, separated into 2 chunks ("{" and "}") + blob := []byte("{}") + blobChunk1 := blob[:1] + blobChunk1Range := fmt.Sprintf("0-%d", len(blobChunk1)-1) + blobChunk2 := blob[1:] + blobChunk2Range := fmt.Sprintf("%d-%d", len(blobChunk1), len(blob)-1) + blobDigest := godigest.FromBytes(blob).String() + + // upload the first chunk + req = client.NewRequest(reggie.PATCH, resp.GetRelativeLocation()). + SetHeader("Content-Type", "application/octet-stream"). + SetHeader("Content-Length", fmt.Sprintf("%d", len(blobChunk1))). + SetHeader("Content-Range", blobChunk1Range). + SetBody(blobChunk1) + resp, err = client.Do(req) + if err != nil { + panic(err) + } + + // upload the final chunk and close the session + req = client.NewRequest(reggie.PUT, resp.GetRelativeLocation()). + SetHeader("Content-Length", fmt.Sprintf("%d", len(blobChunk2))). + SetHeader("Content-Range", blobChunk2Range). + SetHeader("Content-Type", "application/octet-stream"). + SetQueryParam("digest", blobDigest). + SetBody(blobChunk2) + resp, err = client.Do(req) + if err != nil { + panic(err) + } + + // validate the uploaded blob content + req = client.NewRequest(reggie.GET, "/v2/<name>/blobs/<digest>", + reggie.WithDigest(blobDigest)) + resp, err = client.Do(req) + if err != nil { + panic(err) + } + fmt.Printf("Blob content:\n%s\n", resp.String()) + + // upload the manifest (referencing the uploaded blob) + ref := "mytag" + manifest := []byte(fmt.Sprintf( + "{ \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\", \"config\": { \"digest\": \"%s\", "+ + "\"mediaType\": \"application/vnd.oci.image.config.v1+json\","+" \"size\": %d }, \"layers\": [], "+ + "\"schemaVersion\": 2 }", + blobDigest, len(blob))) + req = client.NewRequest(reggie.PUT, "/v2/<name>/manifests/<reference>", + reggie.WithReference(ref)). + SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). + SetBody(manifest) + resp, err = client.Do(req) + if err != nil { + panic(err) + } + + // validate the uploaded manifest content + req = client.NewRequest(reggie.GET, "/v2/<name>/manifests/<reference>", + reggie.WithReference(ref)). + SetHeader("Accept", "application/vnd.oci.image.manifest.v1+json") + resp, err = client.Do(req) + if err != nil { + panic(err) + } + fmt.Printf("Manifest content:\n%s\n", resp.String()) +} +``` diff --git a/vendor/github.com/bloodorangeio/reggie/auth.go b/vendor/github.com/bloodorangeio/reggie/auth.go new file mode 100644 index 000000000..9c473a175 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/auth.go @@ -0,0 +1,97 @@ +package reggie + +import ( + "encoding/json" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/mitchellh/mapstructure" +) + +var ( + authHeaderMatcher = regexp.MustCompile("(?i).*(bearer|basic).*") +) + +type ( + authHeader struct { + Realm string + Service string + Scope string + } + + authInfo struct { + Token string `json:"token"` + AccessToken string `json:"access_token"` + } +) + +func (client *Client) retryRequestWithAuth(originalRequest *Request, originalResponse *Response) (*Response, error) { + authHeaderRaw := originalResponse.Header().Get("Www-Authenticate") + if authHeaderRaw == "" { + return originalResponse, nil + } + + for k, _ := range originalRequest.QueryParam { + originalRequest.QueryParam.Del(k) + } + + if originalRequest.retryCallback != nil { + err := originalRequest.retryCallback(originalRequest) + if err != nil { + return nil, fmt.Errorf("retry callback returned error: %s", err) + } + } + + authenticationType := authHeaderMatcher.ReplaceAllString(authHeaderRaw, "$1") + if strings.EqualFold(authenticationType, "bearer") { + h := parseAuthHeader(authHeaderRaw) + req := client.Client.NewRequest(). + SetQueryParam("service", h.Service). + SetHeader("Accept", "application/json"). + SetHeader("User-Agent", client.Config.UserAgent). + SetBasicAuth(client.Config.Username, client.Config.Password) + if s := client.Config.AuthScope; s != "" { + req.SetQueryParam("scope", s) + } else if h.Scope != "" { + req.SetQueryParam("scope", h.Scope) + } + + authResp, err := req.Execute(GET, h.Realm) + if err != nil { + return nil, err + } + + var info authInfo + bodyBytes := authResp.Body() + err = json.Unmarshal(bodyBytes, &info) + if err != nil { + return nil, err + } + + token := info.Token + if token == "" { + token = info.AccessToken + } + originalRequest.SetAuthToken(token) + return originalRequest.Execute(originalRequest.Method, originalRequest.URL) + } else if strings.EqualFold(authenticationType, "basic") { + originalRequest.SetBasicAuth(client.Config.Username, client.Config.Password) + return originalRequest.Execute(originalRequest.Method, originalRequest.URL) + } + + return nil, errors.New("something went wrong with authorization") +} + +func parseAuthHeader(authHeaderRaw string) *authHeader { + re := regexp.MustCompile(`([a-zA-z]+)="(.+?)"`) + matches := re.FindAllStringSubmatch(authHeaderRaw, -1) + m := make(map[string]string) + for i := 0; i < len(matches); i++ { + m[matches[i][1]] = matches[i][2] + } + var h authHeader + mapstructure.Decode(m, &h) + return &h +} diff --git a/vendor/github.com/bloodorangeio/reggie/client.go b/vendor/github.com/bloodorangeio/reggie/client.go new file mode 100644 index 000000000..4514bcd88 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/client.go @@ -0,0 +1,171 @@ +package reggie + +import ( + "fmt" + "net" + "net/http" + "runtime" + "strings" + "time" + + "github.com/go-resty/resty/v2" +) + +const ( + DefaultUserAgent = "reggie/0.3.0 (https://github.com/bloodorangeio/reggie)" +) + +// Client is an HTTP(s) client to make requests against an OCI registry. +type ( + Client struct { + *resty.Client + Config *clientConfig + } + + clientConfig struct { + Address string + AuthScope string + Username string + Password string + Debug bool + DefaultName string + UserAgent string + } + + clientOption func(c *clientConfig) +) + +// NewClient builds a new Client from provided options. +func NewClient(address string, opts ...clientOption) (*Client, error) { + conf := &clientConfig{} + conf.Address = strings.TrimSuffix(address, "/") + for _, fn := range opts { + fn(conf) + } + if conf.UserAgent == "" { + conf.UserAgent = DefaultUserAgent + } + + // TODO: validate config here, return error if it aint no good + + client := Client{} + client.Client = resty.New() + client.Config = conf + client.Debug = conf.Debug + client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20)) + client.SetTransport(createTransport()) + + return &client, nil +} + +// WithUsernamePassword sets registry username and password configuration settings. +func WithUsernamePassword(username string, password string) clientOption { + return func(c *clientConfig) { + c.Username = username + c.Password = password + } +} + +// WithAuthScope overrides the scope provided by the authorization server. +func WithAuthScope(authScope string) clientOption { + return func(c *clientConfig) { + c.AuthScope = authScope + } +} + +// WithDefaultName sets the default registry namespace configuration setting. +func WithDefaultName(namespace string) clientOption { + return func(c *clientConfig) { + c.DefaultName = namespace + } +} + +// WithDebug enables or disables debug mode. +func WithDebug(debug bool) clientOption { + return func(c *clientConfig) { + c.Debug = debug + } +} + +// WithUserAgent overrides the client user agent +func WithUserAgent(userAgent string) clientOption { + return func(c *clientConfig) { + c.UserAgent = userAgent + } +} + +// SetDefaultName sets the default registry namespace to use for building a Request. +func (client *Client) SetDefaultName(namespace string) { + client.Config.DefaultName = namespace +} + +// NewRequest builds a new Request from provided options. +func (client *Client) NewRequest(method string, path string, opts ...requestOption) *Request { + restyRequest := client.Client.NewRequest() + restyRequest.Method = method + r := &requestConfig{} + for _, o := range opts { + o(r) + } + + namespace := client.Config.DefaultName + if r.Name != "" { + namespace = r.Name + } + + replacements := map[string]string{ + "<name>": namespace, + "<reference>": r.Reference, + "<digest>": r.Digest, + "<session_id>": r.SessionID, + } + + // substitute known path params + for k, v := range replacements { + if v != "" { + path = strings.Replace(path, k, v, -1) + } + } + + path = strings.TrimPrefix(path, "/") + + url := fmt.Sprintf("%s/%s", client.Config.Address, path) + restyRequest.URL = url + restyRequest.SetHeader("User-Agent", client.Config.UserAgent) + + return &Request{ + Request: restyRequest, + retryCallback: r.RetryCallback, + } +} + +// Do executes a Request and returns a Response. +func (client *Client) Do(req *Request) (*Response, error) { + resp, err := req.Execute(req.Method, req.URL) + if err != nil { + return resp, err + } + if resp.IsUnauthorized() { + resp, err = client.retryRequestWithAuth(req, resp) + } + return resp, err +} + +// adapted from Resty: https://github.com/go-resty/resty/blob/de0735f66dae7abf8fb1073b4ace3032c1491424/client.go#L928 +func createTransport() *http.Transport { + dialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + } + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: dialer.DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + DisableCompression: true, + } +} diff --git a/vendor/github.com/bloodorangeio/reggie/error.go b/vendor/github.com/bloodorangeio/reggie/error.go new file mode 100644 index 000000000..777069a64 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/error.go @@ -0,0 +1,14 @@ +package reggie + +type ( + ErrorResponse struct { + Errors []ErrorInfo `json:"errors"` + } + + // ErrorInfo describes a server error returned from a registry. + ErrorInfo struct { + Code string `json:"code"` + Message string `json:"message"` + Detail interface{} `json:"detail"` + } +) diff --git a/vendor/github.com/bloodorangeio/reggie/go.mod b/vendor/github.com/bloodorangeio/reggie/go.mod new file mode 100644 index 000000000..9a44b7496 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/go.mod @@ -0,0 +1,9 @@ +module github.com/bloodorangeio/reggie + +go 1.13 + +require ( + github.com/go-resty/resty/v2 v2.1.0 + github.com/mitchellh/mapstructure v1.1.2 + github.com/opencontainers/distribution-spec v1.0.0-rc0.0.20200108182153-219f20cbcfa1 +) diff --git a/vendor/github.com/bloodorangeio/reggie/go.sum b/vendor/github.com/bloodorangeio/reggie/go.sum new file mode 100644 index 000000000..71421dd4b --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/go.sum @@ -0,0 +1,12 @@ +github.com/go-resty/resty/v2 v2.1.0 h1:Z6IefCpUMfnvItVJaJXWv/pMiiD11So35QgwEELsldE= +github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/opencontainers/distribution-spec v1.0.0-rc0.0.20200108182153-219f20cbcfa1 h1:QMs7PvjIHfWNHJFgY2BTMSDBV14dHRqb82L2BvjO8w0= +github.com/opencontainers/distribution-spec v1.0.0-rc0.0.20200108182153-219f20cbcfa1/go.mod h1:copR2flp+jTEvQIFMb6MIx45OkrxzqyjszPDT3hx/5Q= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/bloodorangeio/reggie/methods.go b/vendor/github.com/bloodorangeio/reggie/methods.go new file mode 100644 index 000000000..02644a714 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/methods.go @@ -0,0 +1,28 @@ +package reggie + +import ( + "github.com/go-resty/resty/v2" +) + +const ( + // GET represents the HTTP GET method. + GET = resty.MethodGet + + // PUT represents the HTTP PUT method. + PUT = resty.MethodPut + + // PATCH represents the HTTP PATCH method. + PATCH = resty.MethodPatch + + // DELETE represents the HTTP DELETE method. + DELETE = resty.MethodDelete + + // POST represents the HTTP POST method. + POST = resty.MethodPost + + // HEAD represents the HTTP HEAD method. + HEAD = resty.MethodHead + + // OPTIONS represents the HTTP OPTIONS method. + OPTIONS = resty.MethodOptions +) diff --git a/vendor/github.com/bloodorangeio/reggie/reggie.png b/vendor/github.com/bloodorangeio/reggie/reggie.png new file mode 100644 index 0000000000000000000000000000000000000000..69a6f1ef0dc1c1265414ee9ef169d63301ba9ba5 GIT binary patch literal 1547 zcmdUv`9IWo9LGO%7}JEAF`5pUmA1!ZWS2?SZC0ciWyZ18xCWb}an{Na=1Z2r?jlDD z5q3p6$~AH{ZXpUAlB3PFS~YHyk+u8Se`0@lzu&LN`-j)_m)GMJ&$2X^#T>!_0A%TB zO|5q?^v|GCySvrMwFdyH0lMk8wjs`oIn91U8n{?8{AG#y3~OI;93$ZPex0?LkRO{+ zN$p$_hEE_1(h%rmO7+6Mw0vSz^x+uoz&GQQ6Y;4^J8FS$)S4YJ_3nrz`}ZKHy}Wh` z3lF)uPs(J2G$kIK6(ZRKU>y7fEyP1uf}C-pu%(p=&|nzW?E#&ljV{f(bKWkI0TOx- z%uWgq<;{y$G%G|R0)PvHpvMO}vaD+o@qr8f+Dz%uUdmLUj_XOnWlk7KkPrw^%JV^8 zK<tu?P(%_BP6Glt)_<rk5PPva53qnO*N?WZmsY{%no7HB7$@CL^!d=XHn-ro(C=UW zj<G}-F1Zu*N;NNXrDSYr`*iU-wm|x1TJFN1DP1=j1)m+W&tkh2i~~zcE)t-OG$ifk z2NebPJ~&!+e~ILHfr(%)xaFs2JmYs=b#vBwde*$ibM02}_+5&)m_*_~oXizBT`hMZ zIOZfu#HT9jn$kY4y4Rx4E)gzsr$Tf#E*1fv!P;=J$_E#H*{30+vezsXrRO(NFK&%p zw>H#YSSJ^pkKH6dHC;g+Q!2iAfPZ%97@8(G>*4#o>{rxu9Mk~#YNE16_{S{!sk+dS zuVuDdta_5vM3J?ahAfNX{swrzx^rnYroFyaA>mLYHO75NMMJBJZb-STzU(DF2+(j1 zrfsRvTYLlv;FQ~@Y60v>(c9LH!5%Q-W>u+^`q;JbZKv;Q__B5wiR^d4do!vvLD5nU zG`z1GVnM*`zM#bjEyPGO3*IAXr`z|fYw7|?>pp%>F*y-8*>v7U;j=+f{SWTu6ng_p z(Km)bVso1B6+Z{V4e#n1w>CP*9$$ANP8P<ut*cFpb7TTs`sdMAVnDLRZ5S>+TKk;` zn6AQ7wWdvRe{|LcD(X#yyX2BKv@3{DoF{K~yY#*u!3QeRkM5k20;6(gR$nd;axJ)f z?0c{(X9{IundD5nsVa#nYQN@g)Hn@K50|7rsg?v_XjeMqwHwVy(^bqo!#3t(&IuD@ zVpyU9*TH%*th}twzLTin&(Hnzm*D!Fh{E>#hc-|*DPrDAQ*<D6AmbI?sSWE^+17}1 zVF0$Zx0KY<jS-=hV@oo?LE&Z`23xLq{EcC$%lr_F;lK{QWP=b8I(B$j+s~CtYcd4l zEDL)oLiq-X0PgdI`e=UcC111<*Z_G24^T7!W$E++bZj<Uk22GscD3ddR>~5V4Y&KK z3g~{>a9p~MQ~;(+TrEngmwzYlPam-B3)S^>7%YZ0^fznm#YcXWH&P_;Cyz7h1>5j` z|CI!BK2w-OvRI5rx<72ZQNrF@3y5I_FF)J*g;mbuI?&67N1iiL;OSBJn1CG_X5y_h z{bIS&rwTFb8G%s-C#7y0(ak{%Mgvip+AO2N)Gr+>ogo|c)jI1^z&+=sMhKQ~(0L5T zAIkDanPG_BJ{jDDkt^%HAmx)L!gTjBVY`}Q?3F?um@A!)YR@+-dyqm5C9d^s?@Uv{ zfcNWpRT@~Wa-=hnoMWxO4SU1$ie?yLRG4u3Ry6r16s+r!!Z{H89duCH$;AVBK;dyF zgSt)uzmEBGcODhJpclk+Y}@ERZ=rX`=f%`qb#hZd#I!M9+lZ9TZ?5>UAsiISkO%60 z%UiA}p_V6#gVJCj-6{qtdC;hg(90cz1Lw$<c1WR**P|%>|4Q><&v?nb6_+ykyCo0k MW|pR9CY<QM0r}FWBme*a literal 0 HcmV?d00001 diff --git a/vendor/github.com/bloodorangeio/reggie/request.go b/vendor/github.com/bloodorangeio/reggie/request.go new file mode 100644 index 000000000..6be5ae014 --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/request.go @@ -0,0 +1,110 @@ +package reggie + +import ( + "fmt" + "regexp" + + "github.com/go-resty/resty/v2" +) + +type ( + // RetryCallbackFunc is a function that can mutate a request prior to it + // being retried. + RetryCallbackFunc func(*Request) error + + // Request is an HTTP request to be sent to an OCI registry. + Request struct { + *resty.Request + retryCallback RetryCallbackFunc + } + + requestConfig struct { + Name string + Reference string + Digest string + SessionID string + RetryCallback RetryCallbackFunc + } + + requestOption func(c *requestConfig) +) + +// WithName sets the namespace per a single request. +func WithName(name string) requestOption { + return func(c *requestConfig) { + c.Name = name + } +} + +// WithReference sets the reference per a single request. +func WithReference(ref string) requestOption { + return func(c *requestConfig) { + c.Reference = ref + } +} + +// WithDigest sets the digest per a single request. +func WithDigest(digest string) requestOption { + return func(c *requestConfig) { + c.Digest = digest + } +} + +// WithSessionID sets the session ID per a single request. +func WithSessionID(id string) requestOption { + return func(c *requestConfig) { + c.SessionID = id + } +} + +// WithRetryCallback specifies a callback that will be invoked before a request +// is retried. This is useful for, e.g., ensuring an io.Reader used for the body +// will produce the right content on retry. +func WithRetryCallback(cb RetryCallbackFunc) requestOption { + return func(c *requestConfig) { + c.RetryCallback = cb + } +} + +// SetBody wraps the resty SetBody and returns the request, allowing method chaining +func (req *Request) SetBody(body interface{}) *Request { + req.Request.SetBody(body) + return req +} + +// SetHeader wraps the resty SetHeader and returns the request, allowing method chaining +func (req *Request) SetHeader(header, content string) *Request { + req.Request.SetHeader(header, content) + return req +} + +// SetQueryParam wraps the resty SetQueryParam and returns the request, allowing method chaining +func (req *Request) SetQueryParam(param, content string) *Request { + req.Request.SetQueryParam(param, content) + return req +} + +// Execute validates a Request and executes it. +func (req *Request) Execute(method, url string) (*Response, error) { + err := validateRequest(req) + if err != nil { + return nil, err + } + + restyResponse, err := req.Request.Execute(method, url) + if err != nil { + return nil, err + } + + resp := &Response{restyResponse} + return resp, err +} + +func validateRequest(req *Request) error { + re := regexp.MustCompile("<name>|<reference>|<digest>|<session_id>|//{2,}") + matches := re.FindAllString(req.URL, -1) + if len(matches) == 0 { + return nil + } + return fmt.Errorf("request is invalid") +} diff --git a/vendor/github.com/bloodorangeio/reggie/response.go b/vendor/github.com/bloodorangeio/reggie/response.go new file mode 100644 index 000000000..5f41c253c --- /dev/null +++ b/vendor/github.com/bloodorangeio/reggie/response.go @@ -0,0 +1,62 @@ +package reggie + +import ( + "encoding/json" + "errors" + "net/http" + "net/url" + + "github.com/go-resty/resty/v2" +) + +type ( + // Response is an HTTP response returned from an OCI registry. + Response struct { + *resty.Response + } +) + +// GetRelativeLocation returns the path component of the URL contained +// in the `Location` header of the response. +func (resp *Response) GetRelativeLocation() string { + loc := resp.Header().Get("Location") + u, err := url.Parse(loc) + if err != nil { + return "" + } + + path := u.Path + if q := u.RawQuery; q != "" { + path += "?" + q + } + + return path +} + +// GetAbsoluteLocation returns the full URL, including protocol and host, +// of the location contained in the `Location` header of the response. +func (resp *Response) GetAbsoluteLocation() string { + return resp.Header().Get("Location") +} + +// IsUnauthorized returns whether or not the response is a 401 +func (resp *Response) IsUnauthorized() bool { + return resp.StatusCode() == http.StatusUnauthorized +} + +// Errors attempts to parse a response as OCI-compliant errors array +func (resp *Response) Errors() ([]ErrorInfo, error) { + errorResponse := &ErrorResponse{} + bodyBytes := []byte(resp.String()) + err := json.Unmarshal(bodyBytes, errorResponse) + if err != nil { + return nil, err + } else if len(errorResponse.Errors) == 0 { + return nil, errors.New("body was valid json but could not be parsed") + } + errorList := []ErrorInfo{} + for _, errorInfo := range errorResponse.Errors { + errorList = append(errorList, errorInfo) + } + return errorList, nil +} diff --git a/vendor/github.com/bloodorangeio/reggie/v2-registry-auth.png b/vendor/github.com/bloodorangeio/reggie/v2-registry-auth.png new file mode 100644 index 0000000000000000000000000000000000000000..3b05d04b5bd6c9830266a5c53c9362251551a0e5 GIT binary patch literal 11063 zcma)i1yoe+_wEow*C>q&4oElBjYEob=Ku;w2uKPHrRdOt2uOo;4I$nANr&XnNOuf5 zz#aYm|KGZI-F4$^X4cC-`#rJWXFtzAaKf}Slu3!`i2wiqsj3P@2LQmD#(eAv@Gzd! z``fz!0OzeLL|)GaYqvcZ;{ya`-W1XlV*eTb-#6QhM?s9QL)e47<7SdFoRK0!-l0{_ z$eMqDjzl+n!|hlZnhjAYl|5U#ZwesgfirUN+sl8xyk{4tvOpZ93NKcGKY{3dl~yJ= zUNSN^5YZYRKz<k*vU=FwOps+>W#Y^LFL-ht4Q8Ud)RKN#V`OvtGj&z3w}m<Glez_y z9byJX6GX>V)4#x+-#0rr+wU!NA(lXnq>LG!N{5$xV5(Iv4_B~Hl(MjN+V9A<mOwE) zIjC&~oF&}a*!6vMZtP#Y`<cY_Az|C2{_LLiq-z>_TZzuFIv}DrCEDz(sb-fHbx`o? z#y_<SFxi_+8ViY4-~D=WIxN=(p%k8LOaIFW26OzVPLp>|<sL`@<1$~I*A=rmX>ZO$ zT#FJ2-?#H`UD8<A*VvytCRx`FM&a}InT4vU-F}Tb?WS2o53&1VZHT@QvK+Q-G85$8 z*ChT$huT@B)2Z|DkA=5nYsF~8ClM{Twj^YRfgzkIQ<dVubn50$+^#bB6e3C|ewfow zevp+f?5iGES70d+S9+YfSm*IY>dn3biHY3OXHUPTuu(%^yy&m}@024FN)tX*QxIrn z>kP68_rm{qo|R;m;b$d1RV`qIg;QjP?ug)Hd<>S?zTd?TS@o7hv+!!YvH}R#wxIX( zX}?p<(@B#~Tu^Ory%5R=HasP{&^$xcF1`>*arUHBlv(nb!1;n6VVIPY3odG*f06eR z>>H-Q!5DCSxfCh>*6OoIaDGJS$i1+CR8^kl<oG%hyEC31u6fHYFlC2Rs=d1z^wt#F z8)3k~ZSXlsJ1@JZZ5)2V<n_tjqI>oQ|A9QswzPkKzjWH@7o8}}!t*dzUb7f1Z1Z3C zzeHl;>pETd71O&@O6sN|@5mdL$aM~}b|iW?RSSC%Vs96&V6;pl-J8b!xuf<{1MHPp z%CIQ>lSdu`o?EskHRyxyY`OHUD^OQCQHRdvpB8B&0Fod%3fw!-xkX3@v-?k#puPP) zgR14)!!wt{B4pq?fh+EM?NY56_Jd$TZUSzClC}_x*{Vb3F$Sc@rN$Mp!6wESS2+{L z=<XX)U@RDjvB9Lju|$8SIrU&7sc{YdP7`AN8~b-!iooAksz1}FbN+LRp<1)uq?40} z@)TWx(f=v5zk{C{{Febb6NL?a6%_~vvWS^^zw!AhNzW`4qco~{(4u-idfw;gMGGsB zk&UG0Jlg)|C(^}iNix_I`#Qx5J@>W7cDS&uK@%!WFuZh?(o3=uulXx5!2iPj=GI*n z*UlV2vQh)~X$D>07)a|a@x~4NS~cR4P|bw>NJnzb&h1d;2G2{vFD!Sg0$synJfCDt z7)9l+*@`rvX>GT7&)7RZ#z27)iKGSBlm>R(NGH0gwX1cv*4%?1PZ&x(Yj368?|6fI zDfE2Gw0DLkTQ-<3Ufj0!hsT#~)~!{^vX!Gj>4Mmw2VysFXc*%Pv7W|kj@fPI)Z@8+ z1%b<cY<yGyw)?el;j-o;i}XNh+<UYKcHF=J&6}-!e*^cdm##wrn{>gmj|FQ&Xszoz ze(^n{KK!VZtu4RJK3xVOcMfd!H<@Y9(q2?UnWbp=^CTau;hDxC-Q-Px+fs{@GlK>l z(m_QVo%|!8NuOVxh8NoPy_}OyZTk~dLo6IRJLZn>TcxrGB&Jc<nkf6;+1IP*S)P~m z<8Bf6jRp*M#cZ<_K4p<q8M&?EsB;;XM!)*`jhqRz^s+7<M~3(j_(P?BNLc2|H}286 zd=1SdERt2^*e8+52-(U$g4k@pQ-7veKnG#TwRrGNFrJ0D1JDJkwU+!P+P(0^=4%>X zqwojv5;gddD&5>?UR@E03RuI>N8y$uaT({0T!G3uM^%w$$_Tl3rN5$D_;U)Ab)amU zVrtwdbui@jW(0ZPH+=t-_U~p_E4{7X<m8O;Pl97kox3!5FP_IE)GVJ+Q9m&unN(wd ziS|4R11%nvR*S5MX54)>O>Mi!9|W(yUk8Y6n0+zpBiK3z41ep7lN8^KB@(QX$utd8 zm6LC-l&Jnrigh4vvM=y*&h%{0vNwzgug#~O(1(tmB|SWu+Shl1<|Z6L%k@*S!DHuZ z3DU{y_T|u-ou3!Ovqj=*Y3gzW=&Z}On5Duy_*lA4rc!?im%C+|y$UZ2Dh^1u{~jaQ z?)0#HAVT`V31C`=m`urlzO5kucjtZ%6Wcq0UWPe-m!P3zwlw@WBEWA4zot~Xm9K4^ z&lRVbr9Cx7aMVI}$FwY^U5BI(JDdZ!glz}roXCq)g*^zGNN?A+{Ycu^X+Q55Z#LJ< z4}mq}H}+zmd3MZHjXGV7BN<d=fYYywu{4<;1Sx&=6@9jD+2=t#)P9CMXY`L!o0e`n zJ5MU!tv||>O%a()`XC#pMZ0M7gEwraiZMX@=d=_~rQf=X`l)-Tx5Z2?H?-e`PV=L& zttva*j}9`L6gTt_bY7W`++H$&pws?--#<`D-G8NIhBoPe@q9+>oz#HXvexBAY$=|E zvDrjvr{Nq{32cDbhi?a^=aMlf)Rs^xvT#URWT956iDi&LR5ZQ_$lYxsGF`%3or$Tq zP})<nethx<RxQ97jI%h^TomHJG6Czyt~rLoK2UyM)_N0;Td>!Di$<A3M6vo0Y58C2 z_dRZzqUo$BH2QdU**`_Yxs2@<1LS7-kuRRfWvVw6uN^{lz4I<YxrY8wsyNnV2|x9O zv=*?_;6R;u)+`fA3|Yb-0XS+@I)3F2$UB-Qyt7Fkq$<h4E(wSah_WlYM=*A!LVK(a zeDs~s=18+griZBIYW&j~c2c_88yNc0PI=3k??Jm@-75WRh4QFun2vUQ_EQQcM7#JZ z-9fuVz7bf|j{)_Zu=?m`j!muJlKF4adha*lNR+u>IW@A~0w>6wP(FMU-u^h5xa503 zv3zd3E#ppqSGWglmtvnSNi15I^bo%d@jgjgl|HnaF)nx9?L1duirl(N3%IE4*-N)c zLoK^Z4fvG|H&zCjgSI#lwODf*Vz-nngJ`gHmVmpjVt~7Seb`=#FWCfjTR>E^RTo-; z**aqzce@i<gqY^)efe#vWoPGySNwy}YdUUPZrYOe5R9D(8S!K6JrHAqcI8lv;SpmD zISg&b7%4RgHAzjz-%$ELvvw{2?sohed4t(WO)~j6^8a*DSU>c!>~w`YdHGvhC`FLV z`G5?vz&W(~e-f2>4XOmY0hYxcG+R|n?a_$hBlxcMaW*QBi9l3dX`eK9a$mB40ZCfh z4ds^seyeYhDN!rbgPByWQIJEtMqPgWN~B%DX{&pu$B8;I=BlkY_maoy9g1&)p?QM` z%q$rVsA%tb6;G9iNqsigDhufzg8H!qrF_yZnlLr>+PV&FuEj6X`W~D!!C)8kZ#><7 z(R$ZHA}NZQPz{&5m^~gq<aNG$W&G=m%JY}x0a)@bscxo~JEvFVNX>=cvH#><MJM|* zz#4Jrp>wkG+3YPTjkYw`nj*q4SIks%$E3XaoJScVdrdv}dY{D(K4?Ni1ZiK?YSrQ` ziCf{ZXr?V!@H8sUC44UbXKJX42dL*T$bkMPL~eUOUMO%>cXNhN3$QAFbZ_nW`UUdb z$2P(O^tI6Jx>_w)W@8sA$ST3RJa2Bde{64{=$Ty8$U@NZ%!8YZcKEq%(@V>92I;*h zVL!!RO*R>|M4`upTuu>KULTZ{ELWdTnp}KOK`Zt@P)4N7c|oN_pFp(zCvwcs*(Nus z-ApmcbNIlrPTD)yS)h$R%D}s7YJ`x+N5y@#U@OAK_uaJxBx6X<8k#iV^K&8MMf~sC zxrxSwZ{u9qgeL|t62h1!E>6k~b2n2;E&O!asJw{oK7$3(S4SUr$}YmVqmZ77yXTMT z(Mgp*iKphdjI(+`y4Z+*%WIs6ayYV`{1*Ij6d!8atw4#bw^z`f<5I-!556wvZ#6Gh z8`Y{A%uy%gO;5sCguJJz`3kTYmatR;<vs8d<VX)g7DKH<GO=7OgX(yQ;FT2$hh%38 z0`N*L?%fYBDAw?fJGnNAD=1z8SC_#oq3l)S#<cqp4}ZOnp?LL*H~@}a>5znTh$Yh@ zZV#}4zCkY$`CA>3F|C?hKMlHb<)<YHk*B~_6krbl<I00@Y2>xc;s<poyP2MA<I2xK zwN9B0{7qjHR#GYo5H!5>e$Q*%@N&v*(f|Bx0YOY)cv^FwUMsY5dZ`_hg})%RfnK~5 z`bD;J0o*V;>D3o&&l;uzrCiW4PB_x(a&s}Q_@T*VR@l&dtVU<or2OsDgS8QN9WfVN zw;vP(2e22GE8vUwQZ5LeY>z6@hOy^Fv@S8rtk^kSuGa9k^9+i##gt_XlV7yblg&sb z`3q7hcd^PW*#zTwff!v)A@akA%mM9-g~Pf{iiTA;l6e<!%fs{Sil}p=V@FU$H2FoA zR>*v3EWBfX3Fp>-H8|-Ys<Ey^^FnB7L_Y>6a`ea%<VI|RW@Ei5cmz`yV9IW43?=IV znk`kV(=XwOXfIQx7b}N~(q2}>X`$gVO9o%Y9U+Vdhbl0<B&fN2Y5ipHlSc);D^aa9 zAmwRY#3R<a;vl#&$&%A5QU9zJmF`^O<+;He6L_my<XLKXQr0yP&-KjhW0{xF2X7;- zm``;OOAe4K!qA9Hzy{yveYCHhSa;T$Scd>7$|qV^PsWnQ)F%k&&IjHS&enwj@)s+g z5Sypk7_A<pSuJjCK_h#8;KUwJO}kWsPiNbohzx|m6`Oi*uor!%s^x+om%TEx>UTkQ zv^bg?jhTUpL&tW=de+suW(RSkjVrYd@7&4nllafdc)1288cjHX@@ZL{hnm^>N5%~^ zV3DJPqB{(vZo!Z0W(e$z+Rd9f<7~r?x~Y7DV>{o(somiB^|rN_h0|+yQ&2)E@w2VR zML4?+HJ_XTm|LP6s^GDX_H_H0zdepglEbGbW>%)szB1Af6kym)vP=3;5K>I}iS^KY z2QFp}iSmq2Uez4ZBPwG0{Ed2XaZq(PVOOoZL*)_XP4c-KnDEBw$JtG!>aKntBY3C- zQLwikKCSmsY-|?wPO|y>N=|pNN`RB?O0|6FJ0$glN#2nu`afwDW@K_b1U}OwHu7}F z_ghyEz5f6MnAEIdb8rtW_0{~tR!efk;ZuC4ffc|zLSb_0DF1IVy!`x@)B#muk5kIQ zBCcT;S&MrYH)Ivzk3WLLIV}~>b6*Jei*@E*df@ApOg0hjWO>19ZS2Sby%{vE@bH}= z6{YH28SmKVyMdDfwfJ?AR<xE8<ej39ZS$lX3P13i^1wBi%gjo-tE7gON-Umwz9i<{ zsP|q%IW$1JmrHNk?e6Ll!qS|OqLK~^iSqd<Ah9iU)n%LWBK3BA@w@HZW8Oo5aGb^S zh5Y%R8aOr)3Hw*alh<tzSE7<LhJ)ccaTd($9bn$0%zs>JI$2qbcqhClM**go^?#^d z!Ia&tuge7taMzdIT_%|qe<K;rp4;&*>(uvyG!OL=MdD^+MwfFA5rRMYq=uPd^z(ch zj{4}-TM(aXxEf5!C#pyhG2UvJ(TP1QWv!9oj5*n$q~G><J1ss(B_Ds`oLTH?LnOHo z^-+{j4^_=CyTVt`q+?uzLyw)6M@>`_%#jd(n|-SgBrt9<+{-7-MsF?S-4C6y9m;-i zi~O_H?}jfw7af&7pCJD65Cs{q$anRH@vboFFVpsJqnZ?-Y2v7tTbu|5a#){v5#>(F z<k7+}KB8QMv#vY@da8CkZeJotwYqjaT*G)!NKEzDX}ku0Os}c##9GKq?iPw+hvM6) z_(riiG8h^eWC*LfDxY|k>0UaezoYzo+Mvze+~UClE{_ptn0e{(9Ru6Oe}r6GRDAcA ziHgB1J^I1J^V}(s7=+dmOP%CJ<V-!*Q0$7j0-C&S5bJF5n(h{F5SBf8h`}qU)T>tR z`H)~)dFdr*>XH`BpilI^;^s0e>-35Mq1dHv@^;en>FJLkZy%$jZ+zkGHgLDmsUeU+ zRVXOth>SRSU&3?Yg^>1uMTKD<&_YrfLSwUAj5(jy>y|W=xPZ$i4?($jpE3FG^Ot-9 zGYyWOXXV*~=S&?OO&;6>?bLMu9Lijf4%)r@U;Gho>T{;B^}Rs?T|i$T=Luf&fe7og zRz|O<*O=1SPO8DYBIV}*J=&U0ic7Nl+{MEn4XrRtn(Rv-4OJ9d@R@qRcPE;z$|Guh zz$^VI;swM)*AoeF_M~CfdFJ}F--YYNhxFgEhy8WC5@$NY1be2ni{aCphn%Md5oEE7 zW-ETEnJ(N~#eo))H_RA1OO?jdpv<|62Ry!D+b^VcGd#(8>)n_mM4n3HNTK<on6hRk zRT6fYYY4M|q$<L(PC*kwInGxeQ`;dBtzB(<+#o|-*JdNYpo+++4TrCknL^dnxkN3= zX=savAF7w{?}X<}P2@}=xK^$;YuaAE^$H@K{AI^*Q1ROY_W`8_qOqk2PP<H6q&^gI zEN7;dVMqI&3)`p%pX8TI5XTi}=O#1~2Q}L*?t97nTl8Q~DUx5O2XqF3U{$>iE_97d z<hf#g+1i$d#0PJE<w*Eq!8}_CAyy~fpsgvmb$Jdm5a<q9@#R^ixCWbm&t>}&_S~gt zg(&RqgV<A(rCMg|Ayeodm3yHVz%}mPr0^upVq>S4IlB$}&K%`C8|N8JrQup2V;)(- zXTq~33|5<aRq7g&$TRz)T6c-zpytBhfmKeVosSi-VwY|3R0Ad(S|{_}l-|T7$)pe@ zDG|#+977g38w=ry&tpPkWG(j^PJ9YUd1&Qwb{)x_{bG^9irCO-(w~orB(ynoeCz|e ztEe#MM1ztsL^-QM9;SknXDqpdRf(tDgc?tkAafk$r!5^EWP=u$jV)_|LU9&;bsa@Y zVeo68m~QN?i;DH@vNp$qgBIurcbvs1F)C1$N08`d4l_#Wn)dq_!!5V>R2ZzT*gkA( zS81*>6+G30tz7=r_f56dq$3xg21V7t&+9CiZql++HgusQPLtMDhDKVgWV{uR!SpVq zx^o<#e_7bKRAUn}??c0dM<MyNoHqD2r65quA=wSK>R#4*qXn&YzzBD8tc4$@{*LO& z+(L@bUo({?dfeLOt5kgFd&D_Q?}5xymtSXb$v;mn{X{I4-kxcE{iNAIthdG>9Bv9s z_Fe+mc)U{WMewZLJC|o^t}%c(K|_$+x)`yuQ|)ELA2b*!o@P(7SblI`Z2{R`d0>v( zTD?auyhwo1E*$Qp#~bVm6L`dBgOj*v-wbEhFK8Ky+u^{hBm$Eb#oVAIB#vw3L(tKn z5j+1coO8D@#lf0LF8`?@`6_l-0Bf@nBzV39h{*r#hZ1C+R=`|bOFJ{@=*29r>tLS4 zC@P)}IH|C}<?2fF`PAfUR`Xi1ODJ-b!&Q1s{&|aGs}|z%(CE0qzlGsq5;{d&IK`QV z5qOxHwK9zJ!Rj<OB(y4L>KL4Dw&Fh$mzCcL+^;-yjg1$&j|?5(5lF{|KuV}h;QS8l zBf5o+CGQay){Oeg-Q@36`evEIk5=y8AZosd<`SB&sqNa}ITFW|vw>Ie_*_pEKJ5P9 zTY1pPQQ_j@JFnrJmJ5G+u=_O-IImJG(B6#w<ZM{+%lHoQ133I5@`aM=cJ=$`r@~0; zvU1#iWHxf9Ua41bgRPZ_LFudOudeE4o5rS#U;LE}$bjo(1sa<N_L<lW#eJ5};bgpD zEbREeeS8q34!^l6rwE^zJq5!QPEUAR$Cf9#G8pV&4*v{3_EhKB%Fx*3klpfpMu+M0 zC_viR3LhwA$=!m}uec}TqA?IknmVNiRhZj9?l?)HjAdMX6&x?y{;)LRj~62Z82LCe z)v>-)X@0c&ka{5H59d!XfwMcfr1(4zyc(Z8Idcp(d^%(?=16X6r2hpD56D_iLnSnk z-L$j`r|>SU6keFcV6dP46XjeSYVqkz7)gN8DjeofFXxaEHGjkYJ%X!*iwV3UpH=<o zQ{B5wj_XuWS;s~LlB1&bMK5M>c!~7x3dwb{Gu?gve2Ye(h%&Ejn-98DO8U1*`%9Nb z5NM4xh&Z0~X&WAEU9Jq3#-Wa6+L8=s<Y8u8?P$)FAUON+{Wgpu$W=*q(=`CgaHS_@ zcFOjawjSh85hY$|Xk(5*-q~B%7P4OC8cx$)<5;apeqATm>g3Ba^3Q$HXpm>{;oIng zphwH6SBr+Nvp=G^xL+rd?XLj7i>o0vrbTc-AU?N9wd;c*-X)%dvOCxq26G(0o+Bs7 z`pZ1|QSZ`On`?|Ar>@cF?5_A8{b-|J;u0&W37U8Y?gC8=NMC<?K8H8g$<SJg@YlXE zmEwN}0%1TSjcPDd<}nLq&14hn2^)6*a9?k&)=_v2Q^S-luKl|V&X^7@IvE1tUJB!@ z4JAy7fNi8TD{?n@ebjF)jc_NKaKtp?6K{p=f6&<|zW{?1_<IT$?a1vmsjr75O>s`m zCA-#X^3W)2WVH#VQ;!0#kRZj<sxSrH)Lk}%`S(na>C{i(g!^s48b?eecGw7q!wbqk zjMKM}%5a~id5`aUxCKp#b%*nvlemniw(gtdP3fCu<!gXI!Vk*JLsHnJsxDeO7#`$U zo=5O-WLRhlJk1A#@tq2z^)TInZ?YrdL4|pNrFUkUQeXZQq3^m8<abagXdzQ4gQ&NP z-q)ecN~{Y={i9znuP!&0c{dDh--d<6v|FKxrrh><m}2LW@`Rb5MDgpi%0MyV1qQbq zO=V$nCu<X)zK+o<X4E#OD5tw{=czF@hDupsbc>V*fk<HweU)K&bzOWHAo8c<nCG!r z3`0^f9vV75X<pd;^Kf;@cB%+@su)b)ppTAhUB*0}nYqumQ#x)}g=HLJF&^=$B1Eq? zuNL_(uxkG+P#BGW8xnH?;!57RrWX|?J;X9BBag`#Q5@SD#NVY%tm6V_zb0~eS#(IC ziw=pk^@}zXzQsCrxo}bE?@q9#!)UYF-O&-kXapM+yPighGVYSK!raI93W=Za9o8{U zfYXxW3Ug#UO6XP|;(ucMYVB@Dl6bl<RwjB#A#<R2;O}N;E2Z{LK>5|1m_CwG0U^w` z=zptvgLrxV+_1gO{XkXosI>V^tl{ca>foEDy|9<Zp%8EuaU8-Iq<y!bQ`l5{N{`pr zO%4!#@3A!aQ*V39owt6wYE*~@-MlnvC}mJOe?@YVXf|Fnc8>JxGLrQ<ead5_-efm( zzr}BHIiT3t8(r;{CSf_5>b->>bQF~=a;<jvPsa6Oel-hN=4RjfHqO!X8jTK--SZwh z0s=H920ZuQ^SK5;8vs$w_@cI384r-%0Ij$B{ThpJwVw@?e%lp69^{CUz1~|P1Z;Lw zeX&LS&i<HWv+Z381cq{9oBMYSU|R<Tu9PC`G9Rxe`M!W~rrq+4bSn>VGvT=kJR6Wl zZCh`oMzR6qpddnS0EH0*n;3vg{bwAk`0qHj4g23Qg((3yI2Z`Pj`(iJd)lAz&a@wn zOC8j9>z!7y2?|`H+qm4B^*SkSpuSw_?A5amT-`U_j`%pIookaWaTh$2bWNo>vZ?}g zC&nCt8j=zmo#g7W-ik^eGC>f3mu6-3zqAP*ByX?@w?udCWDytCO!@9P8vGQ>s{J`G zu_r|TN?Oy!MciY6#PS$@z4oZ;Ok3(*!X#4Nx4L3p9A?2jdG+|&Mz+8XK8a+DG@FEN z8e-`AFsVxnE_Eg)0eA4%J>Szw!^NY7+wj<q@6MFG(q)<UX9Yo9AzS3)$6_#2peoX0 zzUWJB49O2#M@tj$lb{tXC|^@$eT`uq<$z#}u}w9U^LI?sS^Zi5l5O;8?gsRsWyR^B z<U&rbFxf-X-ideY=`|XwBfiqgi=PGrJQkGGT$8iQ4nkYeAH9rwBmQLTp3%IQekM2j z=pm;bk>O@`VGOuxtusbi^_oE15Tsi^P{rFI_`@Q$Xfuf?fIeSpZI@X1(KWY@WR0GG zb!h_6=2h0?Q(@m*2^W}Uc5f{s_2)M1c)Z{z<wW@%*`L|jv-X^9^Lwd&>F{QnAlf*f zSwRkI9N%pUHj_~Ly`zT284s1^qaImqXeG35f1iAsQoWie;l)ypS#&C$ZY>&_c@us3 zu6MYvS!>3x%77{RT6lG-Z6wjRbj0B%wd1LxMtIs;;pZ){qBE=3)(Q6?C7!bxQS#cn zJ4v1oqKsoqAM7O{-ryrkZ9*4&N(8ox-<Up6dF3cY{W=X1W!yU|;EXn@nJG!w^ZWQG z8`;g!UR$^D?}NAMib?|2BgsTrwm#triUL=565%Pg$g@J2y=AiTtjL))yDn1i<p5^? zEKx&r7OF<0mE3?t*w%d0Ig;9np|}USS|#8Zm~~@s8ubkM$zmWB*K6<(pfUIMzk~a~ zf&L$G1I{#_!ILDnUEr$^i~uSu_bhkP{NC=Ygus2LO7tXdj59kgl8og@l04T#69e0T zJhc$13%E_I*HDyq1rXr%JWofKj81xwoY$fLvGqoFaA2O!79!Q1q234wkk9(%r)-F* z|DEnZzGKF76BsyK23P)IwW(JIAN^Hh<7PJ%IXpoCfEHhoGQ4mYDUZFiy56P&og5$E z8QV3Jw!CRrxO$)FPHG;73!uk)^ReOwjJr2#jtCF%k5vsZy7aA`Eang6{QM*MBHmyB zyo5lB7tqLA?ozLYh52QO6#YgYdiR^E;42OQAg8)?UW|S1z68MsP~ic5+`hzINb-4M zW);wS?hQ*DbWbD@o9ANY0T%wu##B6jsT?!FrN(>_aR1LPIVdLLKP~`<J21KaZx@9T zCiFk9APkLQmgB!%e-HK_SAm4rtVe(8zKQqyD4D{=%;kdyd&4OBbh-Ab3%!U#rJ#|F zDF2=V3t;4j)hg@x+S=Nk`!0vwADX#Ptunj<#<b`F!7Fq4mWSP6>@L?Ix*QKqn%`|; zxKuRN9a&Eg1UMNMd!=cTNuiTkPh)QD$ped&Ku25NttW{V$n_Y^0yD&xiUUdvwX`m_ zE)C7@XlNw5s(18xB+&X=Mmx+KX3uC`08C#s76Ui6+0cF6qynP0m6CfkQwNuqq0%@H zd-^d<+ZG@Xy)(HTK$^|Hg+Q9m<nMS<4Foi%0O%=)o#m-8P4(P8w|w(+^n|!~ZUh_P zvwE&fv-_14ue~^{b>pLE*xsyX0#G6{<{PjJ(0UOzRiC+*1pmXf?Gb4*#2&PaLd0+^ zvw^o-kef6o|HW^_nB;?l2eJP{+@_v9$3oQ7Iy}8&8CI%1Dd*gN9hOryDU1@fN`<S% z#}$u*flTFM#lPtSuPzg>vLAb2?882B$@%IA5t++XBZ>mXv73kYG9~j=0vBFQZFdW0 zIa3<Lq8ye>3nbEqs(+wVpjZUlA43WZEf=LS#qJC8aM?1m&Na@eYYR+fm~TeSXZY+C zYe7-^u~i#C1G?}3;439pG`rR+r@ZEs#=kB+VKiFxK?ReZEsS}o4<=Uu4SK_5-fWb3 z(x)ttv_G1vcQiA}cauJz-S9Q*J<CspWwjpmt<Pq_TK^Co5r*h=mVc<s@EC<E1^;OK zkey9eKDf?Z9-i5)t&349??<yk{MnCX1yNRLpgltMy=QSFJcXNI-g@q{fy+OgH{ z29RnqjDkqu+m_?jpfS0_E~ZQAuxXF@IHh1SJ21qX*?7===P+E299cJ}F{d+OoVW7? z8q`KQ8#r&Hd9nqYG_jvUvHHj`7n5AU8Qrkvm?c03ZuBeye412r0Xe3)o%2M=h+flH z78~0>eUnU;$X4D^U1B;nx`)vrjDnih^S#v}*z+oUbF%HGs8VHkJzucmdr7)SsfDP` z`Nd<<Sc=5x)HnDR&c3jazCX%ruQMd?RU@is&zXd}k=r3P8RpQMwYnp)w{d8rIcC^6 zUyRCH#r<fz8(wpk%Sf_2S#!p<=RGu=-{Y87elmLgGy45szMWr~P}Eei%M}s&<@5rn zX!*0afL)FHC32x=!fD#}ofo&Fu{P13GBSy}oZIB7@W+v(y`)%oo!`%598+UqTT*)$ zUc7>*u<-Qa^v-+{kP$}8F-^c<82;%D{x$^Qf4c+>QlQTNKh%p${Vxsw%hZ_h|H|4j z_6$`L7{tO9v5DoN{cp3x(9>Vgk%}=F_?EYI>cc$gQqL2vrzLDhKTG~db)TL782t_8 zi;kU=nObczk6EaoJy~J1IG?KCGswD$POsN;nDIW4Z0fUdv|%j=P$1j3!J|cvvDsO~ z`R0&*>rkB6!^8TXS$sD~Vv+SLHqHx2c_Vj1XLqXlYEUeu$>51dHmPU*`xv$v*&Xz5 z%57y7SYFU#sxHxTY#w~OOZ`J3;3UXedU#PBw%`yvv1;y1cBa{c`Z^fBC&2TmrzFDV z=gGlN2j8Cf-4uqs92oCxhDn}g5@qwFAE}bxBftjbPCFHqa4Uj*-xJ8gKYzd`B%maq zkbZ_3VU9mIK5}pDjcza(>#UQk5^}#47rG4`8i;RK@<ViGH2Yug4E7GsuHNb6Cg6~G zed7uk$vf%cwS;}NJdpMeVT?*>-!?jP<7Fe{mg&Wx?)|hCc=H|+E}dNt50hE3wzN;I z{-)SaBJDX{8{>F!J8sx_5h{>m6ZXw(pVa>=K32tX?i@C<P&fYtuE+<Hd+!hXY8C_0 z>SG~*Ezz5R+wC-nY6AOZlu^#K##!7_7@Vn}1(nZdVY)8rDJ~+`_P*|z$ITrWZN9<u zXm6v=k%0SxilJ;d5iExWzuTE|6eSN=ZhlnVwyinUS^aZ>K7O=#n%8o1<JL`Pc2LFe z@u09FB}!K2$iXO8Xu$hG7Efq3e7r)6wyySvay_sHb6GmXCAcic&&{3`(!!GWzKmM7 zAg!K(Oz#zOiN0Z5zW-1=W2V3kGM6yRWpSqnMU`q7b!C83K{?j8@dasUdJe%yFwOyE zyk{k(+Dx7o3TE(Wr)H}9f_?_zR12jMv)cF3$arz4nT)%3Ju3})5w3;(Eg`$%qdl$_ zjWm(xJmnTh1!{k);q4+_!RM8UzvC`wW8f^nL8oTy-Z~|A3oNyv)fEFs`MoP0T)&+Q zd#Yg4R!#?^aQD3Q_lg|lXJIHYV<?sI6kedKeR~3GcK9Y1%qG(7P0rq7e7D>$Iz@r3 z7flT;!vfvzQmjR(Sle>n6vD3SW9&Bq9D?_L6^^rF6K}m+V;eP?QNabDNt0HD{ATf6 zgw_iVIYMTy@Kk4tp+Bhwn>{?)3MI(8)EIWQh%I`+hEub){Jbru;G*fwN7n<2V{DGZ z?G$#ClEa+W2I_t-;Scc%*YSA$@u~eopu6Pcc_NLH%7<eycagYzIMIp&aOzKVeJ#dU z=_%G*=nBF-ALW}>VUb(hTJ2i!u772epOS3E{E^gYYOCw0o7%uj7o55G`>!U4z5F?J zTf^GCwtp2aLZ6h3$`EYJHM3kGb|Wo72nU-bxs%#6DwgB&8-GOE?sd)U8~EZ60scTT zirx0d11+t0Zw`2)^9WV|(YLaumUHtDvD@b7=hOKA!6n5Z1rUZ1?~{!u)~}TOd7X0m zq~S-B;vDS~slk@1{%sU*VAdPgzD3vZn>g0DYqCOjh^BUIFXOo6@>8KeOUq?dg96V! zd>wDi;c@@LoSZxk*eY)VCwY}Zsjkdt@XB%f7a9v+`7g=EYmTDLVekm7A0@)wI+rjR z@tkE<wW=CFUq4yJu2g`Dp^M96TG}U#rt=O~VP)ckvMZyq$uhf8lVXq9W3aVamX`lF zm&1{AmfY%&36ni-2uWBCfSa50IpXYr_|4kgof$XB;JRf+K>w6U^WqnH637{tBxwK7 z$n}KD>72-a+1)56V}y8)JFSbmMPKLKTj73My6)l)B*dnsOC7#<Fh5r$|ifGl>7S zw<<lq{UMUheSMyLYKOQ|q13zqt)~NtuVh7kVL>VNUf;*GX#dZx%{wvWNfefB^T3}_ NRYeU*nF2KAe*o#eDF^@n literal 0 HcmV?d00001 diff --git a/vendor/github.com/go-resty/resty/v2/.gitignore b/vendor/github.com/go-resty/resty/v2/.gitignore new file mode 100644 index 000000000..8aa2df43d --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +coverage.out +coverage.txt +go.sum diff --git a/vendor/github.com/go-resty/resty/v2/.travis.yml b/vendor/github.com/go-resty/resty/v2/.travis.yml new file mode 100644 index 000000000..103aa35de --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/.travis.yml @@ -0,0 +1,21 @@ +language: go + +sudo: false + +go: # use travis ci resource effectively, keep always latest 2 versions and tip :) + - 1.12.x + - 1.13.x + - tip + +install: + - go get -v -t ./... + +script: + - go test ./... -race -coverprofile=coverage.txt -covermode=atomic + +after_success: + - bash <(curl -s https://codecov.io/bash) + +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/go-resty/resty/v2/BUILD.bazel b/vendor/github.com/go-resty/resty/v2/BUILD.bazel new file mode 100644 index 000000000..6c47cbbbf --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/BUILD.bazel @@ -0,0 +1,36 @@ +package(default_visibility = ["//visibility:private"]) + +load("@bazel_gazelle//:def.bzl", "gazelle") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +gazelle( + name = "gazelle", + command = "fix", + prefix = "github.com/go-resty/resty/v2", +) + +go_library( + name = "go_default_library", + srcs = glob( + ["*.go"], + exclude = ["*_test.go"], + ), + importpath = "github.com/go-resty/resty/v2", + visibility = ["//visibility:public"], + deps = ["@org_golang_x_net//publicsuffix:go_default_library"], +) + +go_test( + name = "go_default_test", + srcs = + glob( + ["*_test.go"], + exclude = ["example_test.go"], + ), + data = glob([".testdata/*"]), + embed = [":go_default_library"], + importpath = "github.com/go-resty/resty/v2", + deps = [ + "@org_golang_x_net//proxy:go_default_library", + ], +) diff --git a/vendor/github.com/go-resty/resty/v2/LICENSE b/vendor/github.com/go-resty/resty/v2/LICENSE new file mode 100644 index 000000000..5cf0a2f99 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2019 Jeevanandam M., https://myjeeva.com <jeeva@myjeeva.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-resty/resty/v2/README.md b/vendor/github.com/go-resty/resty/v2/README.md new file mode 100644 index 000000000..dc0f2aaa6 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/README.md @@ -0,0 +1,819 @@ +<p align="center"> +<h1 align="center">Resty</h1> +<p align="center">Simple HTTP and REST client library for Go (inspired by Ruby rest-client)</p> +<p align="center"><a href="#features">Features</a> section describes in detail about Resty capabilities</p> +</p> +<p align="center"> +<p align="center"><a href="https://travis-ci.org/go-resty/resty"><img src="https://travis-ci.org/go-resty/resty.svg?branch=master" alt="Build Status"></a> <a href="https://codecov.io/gh/go-resty/resty/branch/master"><img src="https://codecov.io/gh/go-resty/resty/branch/master/graph/badge.svg" alt="Code Coverage"></a> <a href="https://goreportcard.com/report/go-resty/resty"><img src="https://goreportcard.com/badge/go-resty/resty" alt="Go Report Card"></a> <a href="https://github.com/go-resty/resty/releases/latest"><img src="https://img.shields.io/badge/version-2.1.0-blue.svg" alt="Release Version"></a> <a href="https://godoc.org/github.com/go-resty/resty"><img src="https://godoc.org/github.com/go-resty/resty?status.svg" alt="GoDoc"></a> <a href="LICENSE"><img src="https://img.shields.io/github/license/go-resty/resty.svg" alt="License"></a></p> +</p> +<p align="center"> +<h4 align="center">Resty Communication Channels</h4> +<p align="center"><a href="https://gitter.im/go_resty/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img src="https://badges.gitter.im/go_resty/community.svg" alt="Chat on Gitter - Resty Community"></a> <a href="https://twitter.com/go_resty"><img src="https://img.shields.io/badge/twitter-@go__resty-55acee.svg" alt="Twitter @go_resty"></a></p> +</p> + +## News + + * v2.1.0 [released](https://github.com/go-resty/resty/releases/tag/v2.1.0) and tagged on Oct 10, 2019. + * v2.0.0 [released](https://github.com/go-resty/resty/releases/tag/v2.0.0) and tagged on Jul 16, 2019. + * v1.12.0 [released](https://github.com/go-resty/resty/releases/tag/v1.12.0) and tagged on Feb 27, 2019. + * v1.0 released and tagged on Sep 25, 2017. - Resty's first version was released on Sep 15, 2015 then it grew gradually as a very handy and helpful library. Its been a two years since first release. I'm very thankful to Resty users and its [contributors](https://github.com/go-resty/resty/graphs/contributors). + +## Features + + * GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS, etc. + * Simple and chainable methods for settings and request + * [Request](https://godoc.org/github.com/go-resty/resty#Request) Body can be `string`, `[]byte`, `struct`, `map`, `slice` and `io.Reader` too + * Auto detects `Content-Type` + * Buffer less processing for `io.Reader` + * Request Body can be read multiple times via `Request.RawRequest.GetBody()` + * [Response](https://godoc.org/github.com/go-resty/resty#Response) object gives you more possibility + * Access as `[]byte` array - `response.Body()` OR Access as `string` - `response.String()` + * Know your `response.Time()` and when we `response.ReceivedAt()` + * Automatic marshal and unmarshal for `JSON` and `XML` content type + * Default is `JSON`, if you supply `struct/map` without header `Content-Type` + * For auto-unmarshal, refer to - + - Success scenario [Request.SetResult()](https://godoc.org/github.com/go-resty/resty#Request.SetResult) and [Response.Result()](https://godoc.org/github.com/go-resty/resty#Response.Result). + - Error scenario [Request.SetError()](https://godoc.org/github.com/go-resty/resty#Request.SetError) and [Response.Error()](https://godoc.org/github.com/go-resty/resty#Response.Error). + - Supports [RFC7807](https://tools.ietf.org/html/rfc7807) - `application/problem+json` & `application/problem+xml` + * Easy to upload one or more file(s) via `multipart/form-data` + * Auto detects file content type + * Request URL [Path Params (aka URI Params)](https://godoc.org/github.com/go-resty/resty#Request.SetPathParams) + * Backoff Retry Mechanism with retry condition function [reference](retry_test.go) + * Resty client HTTP & REST [Request](https://godoc.org/github.com/go-resty/resty#Client.OnBeforeRequest) and [Response](https://godoc.org/github.com/go-resty/resty#Client.OnAfterResponse) middlewares + * `Request.SetContext` supported + * Authorization option of `BasicAuth` and `Bearer` token + * Set request `ContentLength` value for all request or particular request + * Custom [Root Certificates](https://godoc.org/github.com/go-resty/resty#Client.SetRootCertificate) and Client [Certificates](https://godoc.org/github.com/go-resty/resty#Client.SetCertificates) + * Download/Save HTTP response directly into File, like `curl -o` flag. See [SetOutputDirectory](https://godoc.org/github.com/go-resty/resty#Client.SetOutputDirectory) & [SetOutput](https://godoc.org/github.com/go-resty/resty#Request.SetOutput). + * Cookies for your request and CookieJar support + * SRV Record based request instead of Host URL + * Client settings like `Timeout`, `RedirectPolicy`, `Proxy`, `TLSClientConfig`, `Transport`, etc. + * Optionally allows GET request with payload, see [SetAllowGetMethodPayload](https://godoc.org/github.com/go-resty/resty#Client.SetAllowGetMethodPayload) + * Supports registering external JSON library into resty, see [how to use](https://github.com/go-resty/resty/issues/76#issuecomment-314015250) + * Exposes Response reader without reading response (no auto-unmarshaling) if need be, see [how to use](https://github.com/go-resty/resty/issues/87#issuecomment-322100604) + * Option to specify expected `Content-Type` when response `Content-Type` header missing. Refer to [#92](https://github.com/go-resty/resty/issues/92) + * Resty design + * Have client level settings & options and also override at Request level if you want to + * Request and Response middlewares + * Create Multiple clients if you want to `resty.New()` + * Supports `http.RoundTripper` implementation, see [SetTransport](https://godoc.org/github.com/go-resty/resty#Client.SetTransport) + * goroutine concurrent safe + * Resty Client trace, see [Client.EnableTrace](https://godoc.org/github.com/go-resty/resty#Client.EnableTrace) and [Request.EnableTrace](https://godoc.org/github.com/go-resty/resty#Request.EnableTrace) + * Debug mode - clean and informative logging presentation + * Gzip - Go does it automatically also resty has fallback handling too + * Works fine with `HTTP/2` and `HTTP/1.1` + * [Bazel support](#bazel-support) + * Easily mock Resty for testing, [for e.g.](#mocking-http-requests-using-httpmock-library) + * Well tested client library + +### Included Batteries + + * Redirect Policies - see [how to use](#redirect-policy) + * NoRedirectPolicy + * FlexibleRedirectPolicy + * DomainCheckRedirectPolicy + * etc. [more info](redirect.go) + * Retry Mechanism [how to use](#retries) + * Backoff Retry + * Conditional Retry + * SRV Record based request instead of Host URL [how to use](resty_test.go#L1412) + * etc (upcoming - throw your idea's [here](https://github.com/go-resty/resty/issues)). + + +#### Supported Go Versions + +Initially Resty started supporting `go modules` since `v1.10.0` release. + +Starting Resty v2 and higher versions, it fully embraces [go modules](https://github.com/golang/go/wiki/Modules) package release. It requires a Go version capable of understanding `/vN` suffixed imports: + +- 1.9.7+ +- 1.10.3+ +- 1.11+ + + +## It might be beneficial for your project :smile: + +Resty author also published following projects for Go Community. + + * [aah framework](https://aahframework.org) - A secure, flexible, rapid Go web framework. + * [THUMBAI](https://thumbai.app) - Go Mod Repository, Go Vanity Service and Simple Proxy Server. + * [go-model](https://github.com/jeevatkm/go-model) - Robust & Easy to use model mapper and utility methods for Go `struct`. + + +## Installation + +```bash +# Go Modules +require github.com/go-resty/resty/v2 v2.1.0 +``` + +## Usage + +The following samples will assist you to become as comfortable as possible with resty library. + +```go +// Import resty into your code and refer it as `resty`. +import "github.com/go-resty/resty/v2" +``` + +#### Simple GET + +```go +// Create a Resty Client +client := resty.New() + +resp, err := client.R(). + EnableTrace(). + Get("https://httpbin.org/get") + +// Explore response object +fmt.Println("Response Info:") +fmt.Println("Error :", err) +fmt.Println("Status Code:", resp.StatusCode()) +fmt.Println("Status :", resp.Status()) +fmt.Println("Time :", resp.Time()) +fmt.Println("Received At:", resp.ReceivedAt()) +fmt.Println("Body :\n", resp) +fmt.Println() + +// Explore trace info +fmt.Println("Request Trace Info:") +ti := resp.Request.TraceInfo() +fmt.Println("DNSLookup :", ti.DNSLookup) +fmt.Println("ConnTime :", ti.ConnTime) +fmt.Println("TLSHandshake :", ti.TLSHandshake) +fmt.Println("ServerTime :", ti.ServerTime) +fmt.Println("ResponseTime :", ti.ResponseTime) +fmt.Println("TotalTime :", ti.TotalTime) +fmt.Println("IsConnReused :", ti.IsConnReused) +fmt.Println("IsConnWasIdle:", ti.IsConnWasIdle) +fmt.Println("ConnIdleTime :", ti.ConnIdleTime) + +/* Output +Response Info: +Error : <nil> +Status Code: 200 +Status : 200 OK +Time : 465.301137ms +Received At: 2019-06-16 01:52:33.772456 -0800 PST m=+0.466672260 +Body : + { + "args": {}, + "headers": { + "Accept-Encoding": "gzip", + "Host": "httpbin.org", + "User-Agent": "go-resty/2.0.0 (https://github.com/go-resty/resty)" + }, + "origin": "0.0.0.0", + "url": "https://httpbin.org/get" +} + +Request Trace Info: +DNSLookup : 2.21124ms +ConnTime : 393.875795ms +TLSHandshake : 319.313546ms +ServerTime : 71.109256ms +ResponseTime : 94.466µs +TotalTime : 465.301137ms +IsConnReused : false +IsConnWasIdle: false +ConnIdleTime : 0s +*/ +``` + +#### Enhanced GET + +```go +// Create a Resty Client +client := resty.New() + +resp, err := client.R(). + SetQueryParams(map[string]string{ + "page_no": "1", + "limit": "20", + "sort":"name", + "order": "asc", + "random":strconv.FormatInt(time.Now().Unix(), 10), + }). + SetHeader("Accept", "application/json"). + SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F"). + Get("/search_result") + + +// Sample of using Request.SetQueryString method +resp, err := client.R(). + SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more"). + SetHeader("Accept", "application/json"). + SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F"). + Get("/show_product") +``` + +#### Various POST method combinations + +```go +// Create a Resty Client +client := resty.New() + +// POST JSON string +// No need to set content type, if you have client level setting +resp, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetBody(`{"username":"testuser", "password":"testpass"}`). + SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}). + Post("https://myapp.com/login") + +// POST []byte array +// No need to set content type, if you have client level setting +resp, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)). + SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}). + Post("https://myapp.com/login") + +// POST Struct, default is JSON content type. No need to set one +resp, err := client.R(). + SetBody(User{Username: "testuser", Password: "testpass"}). + SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}). + SetError(&AuthError{}). // or SetError(AuthError{}). + Post("https://myapp.com/login") + +// POST Map, default is JSON content type. No need to set one +resp, err := client.R(). + SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}). + SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}). + SetError(&AuthError{}). // or SetError(AuthError{}). + Post("https://myapp.com/login") + +// POST of raw bytes for file upload. For example: upload file to Dropbox +fileBytes, _ := ioutil.ReadFile("/Users/jeeva/mydocument.pdf") + +// See we are not setting content-type header, since go-resty automatically detects Content-Type for you +resp, err := client.R(). + SetBody(fileBytes). + SetContentLength(true). // Dropbox expects this value + SetAuthToken("<your-auth-token>"). + SetError(&DropboxError{}). // or SetError(DropboxError{}). + Post("https://content.dropboxapi.com/1/files_put/auto/resty/mydocument.pdf") // for upload Dropbox supports PUT too + +// Note: resty detects Content-Type for request body/payload if content type header is not set. +// * For struct and map data type defaults to 'application/json' +// * Fallback is plain text content type +``` + +#### Sample PUT + +You can use various combinations of `PUT` method call like demonstrated for `POST`. + +```go +// Note: This is one sample of PUT method usage, refer POST for more combination + +// Create a Resty Client +client := resty.New() + +// Request goes as JSON content type +// No need to set auth token, error, if you have client level settings +resp, err := client.R(). + SetBody(Article{ + Title: "go-resty", + Content: "This is my article content, oh ya!", + Author: "Jeevanandam M", + Tags: []string{"article", "sample", "resty"}, + }). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + SetError(&Error{}). // or SetError(Error{}). + Put("https://myapp.com/article/1234") +``` + +#### Sample PATCH + +You can use various combinations of `PATCH` method call like demonstrated for `POST`. + +```go +// Note: This is one sample of PUT method usage, refer POST for more combination + +// Create a Resty Client +client := resty.New() + +// Request goes as JSON content type +// No need to set auth token, error, if you have client level settings +resp, err := client.R(). + SetBody(Article{ + Tags: []string{"new tag1", "new tag2"}, + }). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + SetError(&Error{}). // or SetError(Error{}). + Patch("https://myapp.com/articles/1234") +``` + +#### Sample DELETE, HEAD, OPTIONS + +```go +// Create a Resty Client +client := resty.New() + +// DELETE a article +// No need to set auth token, error, if you have client level settings +resp, err := client.R(). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + SetError(&Error{}). // or SetError(Error{}). + Delete("https://myapp.com/articles/1234") + +// DELETE a articles with payload/body as a JSON string +// No need to set auth token, error, if you have client level settings +resp, err := client.R(). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + SetError(&Error{}). // or SetError(Error{}). + SetHeader("Content-Type", "application/json"). + SetBody(`{article_ids: [1002, 1006, 1007, 87683, 45432] }`). + Delete("https://myapp.com/articles") + +// HEAD of resource +// No need to set auth token, if you have client level settings +resp, err := client.R(). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + Head("https://myapp.com/videos/hi-res-video") + +// OPTIONS of resource +// No need to set auth token, if you have client level settings +resp, err := client.R(). + SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). + Options("https://myapp.com/servers/nyc-dc-01") +``` + +### Multipart File(s) upload + +#### Using io.Reader + +```go +profileImgBytes, _ := ioutil.ReadFile("/Users/jeeva/test-img.png") +notesBytes, _ := ioutil.ReadFile("/Users/jeeva/text-file.txt") + +// Create a Resty Client +client := resty.New() + +resp, err := client.R(). + SetFileReader("profile_img", "test-img.png", bytes.NewReader(profileImgBytes)). + SetFileReader("notes", "text-file.txt", bytes.NewReader(notesBytes)). + SetFormData(map[string]string{ + "first_name": "Jeevanandam", + "last_name": "M", + }). + Post("http://myapp.com/upload") +``` + +#### Using File directly from Path + +```go +// Create a Resty Client +client := resty.New() + +// Single file scenario +resp, err := client.R(). + SetFile("profile_img", "/Users/jeeva/test-img.png"). + Post("http://myapp.com/upload") + +// Multiple files scenario +resp, err := client.R(). + SetFiles(map[string]string{ + "profile_img": "/Users/jeeva/test-img.png", + "notes": "/Users/jeeva/text-file.txt", + }). + Post("http://myapp.com/upload") + +// Multipart of form fields and files +resp, err := client.R(). + SetFiles(map[string]string{ + "profile_img": "/Users/jeeva/test-img.png", + "notes": "/Users/jeeva/text-file.txt", + }). + SetFormData(map[string]string{ + "first_name": "Jeevanandam", + "last_name": "M", + "zip_code": "00001", + "city": "my city", + "access_token": "C6A79608-782F-4ED0-A11D-BD82FAD829CD", + }). + Post("http://myapp.com/profile") +``` + +#### Sample Form submission + +```go +// Create a Resty Client +client := resty.New() + +// just mentioning about POST as an example with simple flow +// User Login +resp, err := client.R(). + SetFormData(map[string]string{ + "username": "jeeva", + "password": "mypass", + }). + Post("http://myapp.com/login") + +// Followed by profile update +resp, err := client.R(). + SetFormData(map[string]string{ + "first_name": "Jeevanandam", + "last_name": "M", + "zip_code": "00001", + "city": "new city update", + }). + Post("http://myapp.com/profile") + +// Multi value form data +criteria := url.Values{ + "search_criteria": []string{"book", "glass", "pencil"}, +} +resp, err := client.R(). + SetFormDataFromValues(criteria). + Post("http://myapp.com/search") +``` + +#### Save HTTP Response into File + +```go +// Create a Resty Client +client := resty.New() + +// Setting output directory path, If directory not exists then resty creates one! +// This is optional one, if you're planning using absoule path in +// `Request.SetOutput` and can used together. +client.SetOutputDirectory("/Users/jeeva/Downloads") + +// HTTP response gets saved into file, similar to curl -o flag +_, err := client.R(). + SetOutput("plugin/ReplyWithHeader-v5.1-beta.zip"). + Get("http://bit.ly/1LouEKr") + +// OR using absolute path +// Note: output directory path is not used for absoulte path +_, err := client.R(). + SetOutput("/MyDownloads/plugin/ReplyWithHeader-v5.1-beta.zip"). + Get("http://bit.ly/1LouEKr") +``` + +#### Request URL Path Params + +Resty provides easy to use dynamic request URL path params. Params can be set at client and request level. Client level params value can be overridden at request level. + +```go +// Create a Resty Client +client := resty.New() + +client.R().SetPathParams(map[string]string{ + "userId": "sample@sample.com", + "subAccountId": "100002", +}). +Get("/v1/users/{userId}/{subAccountId}/details") + +// Result: +// Composed URL - /v1/users/sample@sample.com/100002/details +``` + +#### Request and Response Middleware + +Resty provides middleware ability to manipulate for Request and Response. It is more flexible than callback approach. + +```go +// Create a Resty Client +client := resty.New() + +// Registering Request Middleware +client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error { + // Now you have access to Client and current Request object + // manipulate it as per your need + + return nil // if its success otherwise return error + }) + +// Registering Response Middleware +client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error { + // Now you have access to Client and current Response object + // manipulate it as per your need + + return nil // if its success otherwise return error + }) +``` + +#### Redirect Policy + +Resty provides few ready to use redirect policy(s) also it supports multiple policies together. + +```go +// Create a Resty Client +client := resty.New() + +// Assign Client Redirect Policy. Create one as per you need +client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(15)) + +// Wanna multiple policies such as redirect count, domain name check, etc +client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20), + resty.DomainCheckRedirectPolicy("host1.com", "host2.org", "host3.net")) +``` + +##### Custom Redirect Policy + +Implement [RedirectPolicy](redirect.go#L20) interface and register it with resty client. Have a look [redirect.go](redirect.go) for more information. + +```go +// Create a Resty Client +client := resty.New() + +// Using raw func into resty.SetRedirectPolicy +client.SetRedirectPolicy(resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error { + // Implement your logic here + + // return nil for continue redirect otherwise return error to stop/prevent redirect + return nil +})) + +//--------------------------------------------------- + +// Using struct create more flexible redirect policy +type CustomRedirectPolicy struct { + // variables goes here +} + +func (c *CustomRedirectPolicy) Apply(req *http.Request, via []*http.Request) error { + // Implement your logic here + + // return nil for continue redirect otherwise return error to stop/prevent redirect + return nil +} + +// Registering in resty +client.SetRedirectPolicy(CustomRedirectPolicy{/* initialize variables */}) +``` + +#### Custom Root Certificates and Client Certificates + +```go +// Create a Resty Client +client := resty.New() + +// Custom Root certificates, just supply .pem file. +// you can add one or more root certificates, its get appended +client.SetRootCertificate("/path/to/root/pemFile1.pem") +client.SetRootCertificate("/path/to/root/pemFile2.pem") +// ... and so on! + +// Adding Client Certificates, you add one or more certificates +// Sample for creating certificate object +// Parsing public/private key pair from a pair of files. The files must contain PEM encoded data. +cert1, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key") +if err != nil { + log.Fatalf("ERROR client certificate: %s", err) +} +// ... + +// You add one or more certificates +client.SetCertificates(cert1, cert2, cert3) +``` + +#### Proxy Settings - Client as well as at Request Level + +Default `Go` supports Proxy via environment variable `HTTP_PROXY`. Resty provides support via `SetProxy` & `RemoveProxy`. +Choose as per your need. + +**Client Level Proxy** settings applied to all the request + +```go +// Create a Resty Client +client := resty.New() + +// Setting a Proxy URL and Port +client.SetProxy("http://proxyserver:8888") + +// Want to remove proxy setting +client.RemoveProxy() +``` + +#### Retries + +Resty uses [backoff](http://www.awsarchitectureblog.com/2015/03/backoff.html) +to increase retry intervals after each attempt. + +Usage example: + +```go +// Create a Resty Client +client := resty.New() + +// Retries are configured per client +client. + // Set retry count to non zero to enable retries + SetRetryCount(3). + // You can override initial retry wait time. + // Default is 100 milliseconds. + SetRetryWaitTime(5 * time.Second). + // MaxWaitTime can be overridden as well. + // Default is 2 seconds. + SetRetryMaxWaitTime(20 * time.Second). + // SetRetryAfter sets callback to calculate wait time between retries. + // Default (nil) implies exponential backoff with jitter + SetRetryAfter(func(client *Client, resp *Response) (time.Duration, error) { + return 0, errors.New("quota exceeded") + }) +``` + +Above setup will result in resty retrying requests returned non nil error up to +3 times with delay increased after each attempt. + +You can optionally provide client with custom retry conditions: + +```go +// Create a Resty Client +client := resty.New() + +client.AddRetryCondition( + // RetryConditionFunc type is for retry condition function + // input: non-nil Response OR request execution error + func(r *resty.Response, err error) bool { + return r.StatusCode() == http.StatusTooManyRequests + }, +) +``` + +Above example will make resty retry requests ended with `429 Too Many Requests` +status code. + +Multiple retry conditions can be added. + +It is also possible to use `resty.Backoff(...)` to get arbitrary retry scenarios +implemented. [Reference](retry_test.go). + +#### Allow GET request with Payload + +```go +// Create a Resty Client +client := resty.New() + +// Allow GET request with Payload. This is disabled by default. +client.SetAllowGetMethodPayload(true) +``` + +#### Wanna Multiple Clients + +```go +// Here you go! +// Client 1 +client1 := resty.New() +client1.R().Get("http://httpbin.org") +// ... + +// Client 2 +client2 := resty.New() +client2.R().Head("http://httpbin.org") +// ... + +// Bend it as per your need!!! +``` + +#### Remaining Client Settings & its Options + +```go +// Create a Resty Client +client := resty.New() + +// Unique settings at Client level +//-------------------------------- +// Enable debug mode +client.SetDebug(true) + +// Assign Client TLSClientConfig +// One can set custom root-certificate. Refer: http://golang.org/pkg/crypto/tls/#example_Dial +client.SetTLSClientConfig(&tls.Config{ RootCAs: roots }) + +// or One can disable security check (https) +client.SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true }) + +// Set client timeout as per your need +client.SetTimeout(1 * time.Minute) + + +// You can override all below settings and options at request level if you want to +//-------------------------------------------------------------------------------- +// Host URL for all request. So you can use relative URL in the request +client.SetHostURL("http://httpbin.org") + +// Headers for all request +client.SetHeader("Accept", "application/json") +client.SetHeaders(map[string]string{ + "Content-Type": "application/json", + "User-Agent": "My custom User Agent String", + }) + +// Cookies for all request +client.SetCookie(&http.Cookie{ + Name:"go-resty", + Value:"This is cookie value", + Path: "/", + Domain: "sample.com", + MaxAge: 36000, + HttpOnly: true, + Secure: false, + }) +client.SetCookies(cookies) + +// URL query parameters for all request +client.SetQueryParam("user_id", "00001") +client.SetQueryParams(map[string]string{ // sample of those who use this manner + "api_key": "api-key-here", + "api_secert": "api-secert", + }) +client.R().SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more") + +// Form data for all request. Typically used with POST and PUT +client.SetFormData(map[string]string{ + "access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F", + }) + +// Basic Auth for all request +client.SetBasicAuth("myuser", "mypass") + +// Bearer Auth Token for all request +client.SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F") + +// Enabling Content length value for all request +client.SetContentLength(true) + +// Registering global Error object structure for JSON/XML request +client.SetError(&Error{}) // or resty.SetError(Error{}) +``` + +#### Unix Socket + +```go +unixSocket := "/var/run/my_socket.sock" + +// Create a Go's http.Transport so we can set it in resty. +transport := http.Transport{ + Dial: func(_, _ string) (net.Conn, error) { + return net.Dial("unix", unixSocket) + }, +} + +// Create a Resty Client +client := resty.New() + +// Set the previous transport that we created, set the scheme of the communication to the +// socket and set the unixSocket as the HostURL. +client.SetTransport(&transport).SetScheme("http").SetHostURL(unixSocket) + +// No need to write the host's URL on the request, just the path. +client.R().Get("/index.html") +``` + +#### Bazel support + +Resty can be built, tested and depended upon via [Bazel](https://bazel.build). +For example, to run all tests: + +```shell +bazel test :go_default_test +``` + +#### Mocking http requests using [httpmock](https://github.com/jarcoal/httpmock) library + +In order to mock the http requests when testing your application you +could use the `httpmock` library. + +When using the default resty client, you should pass the client to the library as follow: + +```go +// Create a Resty Client +client := resty.New() + +// Get the underlying HTTP Client and set it to Mock +httpmock.ActivateNonDefault(client.GetClient()) +``` + +More detailed example of mocking resty http requests using ginko could be found [here](https://github.com/jarcoal/httpmock#ginkgo--resty-example). + +## Versioning + +Resty releases versions according to [Semantic Versioning](http://semver.org) + + * Resty v2 does not use `gopkg.in` service for library versioning. + * Resty fully adapted to `go mod` capabilities since `v1.10.0` release. + * Resty v1 series was using `gopkg.in` to provide versioning. `gopkg.in/resty.vX` points to appropriate tagged versions; `X` denotes version series number and it's a stable release for production use. For e.g. `gopkg.in/resty.v0`. + * Development takes place at the master branch. Although the code in master should always compile and test successfully, it might break API's. I aim to maintain backwards compatibility, but sometimes API's and behavior might be changed to fix a bug. + +## Contribution + +I would welcome your contribution! If you find any improvement or issue you want to fix, feel free to send a pull request, I like pull requests that include test cases for fix/enhancement. I have done my best to bring pretty good code coverage. Feel free to write tests. + +BTW, I'd like to know what you think about `Resty`. Kindly open an issue or send me an email; it'd mean a lot to me. + +## Creator + +[Jeevanandam M.](https://github.com/jeevatkm) (jeeva@myjeeva.com) + +## Contributors + +Have a look on [Contributors](https://github.com/go-resty/resty/graphs/contributors) page. + +## License + +Resty released under MIT license, refer [LICENSE](LICENSE) file. diff --git a/vendor/github.com/go-resty/resty/v2/WORKSPACE b/vendor/github.com/go-resty/resty/v2/WORKSPACE new file mode 100644 index 000000000..5459d6321 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/WORKSPACE @@ -0,0 +1,27 @@ +workspace(name = "resty") + +git_repository( + name = "io_bazel_rules_go", + remote = "https://github.com/bazelbuild/rules_go.git", + tag = "0.13.0", +) + +git_repository( + name = "bazel_gazelle", + remote = "https://github.com/bazelbuild/bazel-gazelle.git", + tag = "0.13.0", +) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_rules_dependencies", + "go_register_toolchains", +) + +go_rules_dependencies() + +go_register_toolchains() + +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") + +gazelle_dependencies() diff --git a/vendor/github.com/go-resty/resty/v2/client.go b/vendor/github.com/go-resty/resty/v2/client.go new file mode 100644 index 000000000..5a6e63317 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/client.go @@ -0,0 +1,946 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "bytes" + "compress/gzip" + "crypto/tls" + "crypto/x509" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "math" + "net" + "net/http" + "net/url" + "reflect" + "regexp" + "runtime" + "strings" + "sync" + "time" +) + +const ( + // MethodGet HTTP method + MethodGet = "GET" + + // MethodPost HTTP method + MethodPost = "POST" + + // MethodPut HTTP method + MethodPut = "PUT" + + // MethodDelete HTTP method + MethodDelete = "DELETE" + + // MethodPatch HTTP method + MethodPatch = "PATCH" + + // MethodHead HTTP method + MethodHead = "HEAD" + + // MethodOptions HTTP method + MethodOptions = "OPTIONS" +) + +var ( + hdrUserAgentKey = http.CanonicalHeaderKey("User-Agent") + hdrAcceptKey = http.CanonicalHeaderKey("Accept") + hdrContentTypeKey = http.CanonicalHeaderKey("Content-Type") + hdrContentLengthKey = http.CanonicalHeaderKey("Content-Length") + hdrContentEncodingKey = http.CanonicalHeaderKey("Content-Encoding") + hdrAuthorizationKey = http.CanonicalHeaderKey("Authorization") + + plainTextType = "text/plain; charset=utf-8" + jsonContentType = "application/json" + formContentType = "application/x-www-form-urlencoded" + + jsonCheck = regexp.MustCompile(`(?i:(application|text)/(json|.*\+json|json\-.*)(;|$))`) + xmlCheck = regexp.MustCompile(`(?i:(application|text)/(xml|.*\+xml)(;|$))`) + + hdrUserAgentValue = "go-resty/" + Version + " (https://github.com/go-resty/resty)" + bufPool = &sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} +) + +// Client struct is used to create Resty client with client level settings, +// these settings are applicable to all the request raised from the client. +// +// Resty also provides an options to override most of the client settings +// at request level. +type Client struct { + HostURL string + QueryParam url.Values + FormData url.Values + Header http.Header + UserInfo *User + Token string + Cookies []*http.Cookie + Error reflect.Type + Debug bool + DisableWarn bool + AllowGetMethodPayload bool + RetryCount int + RetryWaitTime time.Duration + RetryMaxWaitTime time.Duration + RetryConditions []RetryConditionFunc + RetryAfter RetryAfterFunc + JSONMarshal func(v interface{}) ([]byte, error) + JSONUnmarshal func(data []byte, v interface{}) error + + jsonEscapeHTML bool + setContentLength bool + closeConnection bool + notParseResponse bool + trace bool + debugBodySizeLimit int64 + outputDirectory string + scheme string + pathParams map[string]string + log Logger + httpClient *http.Client + proxyURL *url.URL + beforeRequest []func(*Client, *Request) error + udBeforeRequest []func(*Client, *Request) error + preReqHook func(*Client, *http.Request) error + afterResponse []func(*Client, *Response) error + requestLog func(*RequestLog) error + responseLog func(*ResponseLog) error +} + +// User type is to hold an username and password information +type User struct { + Username, Password string +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Client methods +//___________________________________ + +// SetHostURL method is to set Host URL in the client instance. It will be used with request +// raised from this client with relative URL +// // Setting HTTP address +// client.SetHostURL("http://myjeeva.com") +// +// // Setting HTTPS address +// client.SetHostURL("https://myjeeva.com") +func (c *Client) SetHostURL(url string) *Client { + c.HostURL = strings.TrimRight(url, "/") + return c +} + +// SetHeader method sets a single header field and its value in the client instance. +// These headers will be applied to all requests raised from this client instance. +// Also it can be overridden at request level header options. +// +// See `Request.SetHeader` or `Request.SetHeaders`. +// +// For Example: To set `Content-Type` and `Accept` as `application/json` +// +// client. +// SetHeader("Content-Type", "application/json"). +// SetHeader("Accept", "application/json") +func (c *Client) SetHeader(header, value string) *Client { + c.Header.Set(header, value) + return c +} + +// SetHeaders method sets multiple headers field and its values at one go in the client instance. +// These headers will be applied to all requests raised from this client instance. Also it can be +// overridden at request level headers options. +// +// See `Request.SetHeaders` or `Request.SetHeader`. +// +// For Example: To set `Content-Type` and `Accept` as `application/json` +// +// client.SetHeaders(map[string]string{ +// "Content-Type": "application/json", +// "Accept": "application/json", +// }) +func (c *Client) SetHeaders(headers map[string]string) *Client { + for h, v := range headers { + c.Header.Set(h, v) + } + return c +} + +// SetCookieJar method sets custom http.CookieJar in the resty client. Its way to override default. +// +// For Example: sometimes we don't want to save cookies in api contacting, we can remove the default +// CookieJar in resty client. +// +// client.SetCookieJar(nil) +func (c *Client) SetCookieJar(jar http.CookieJar) *Client { + c.httpClient.Jar = jar + return c +} + +// SetCookie method appends a single cookie in the client instance. +// These cookies will be added to all the request raised from this client instance. +// client.SetCookie(&http.Cookie{ +// Name:"go-resty", +// Value:"This is cookie value", +// }) +func (c *Client) SetCookie(hc *http.Cookie) *Client { + c.Cookies = append(c.Cookies, hc) + return c +} + +// SetCookies method sets an array of cookies in the client instance. +// These cookies will be added to all the request raised from this client instance. +// cookies := []*http.Cookie{ +// &http.Cookie{ +// Name:"go-resty-1", +// Value:"This is cookie 1 value", +// }, +// &http.Cookie{ +// Name:"go-resty-2", +// Value:"This is cookie 2 value", +// }, +// } +// +// // Setting a cookies into resty +// client.SetCookies(cookies) +func (c *Client) SetCookies(cs []*http.Cookie) *Client { + c.Cookies = append(c.Cookies, cs...) + return c +} + +// SetQueryParam method sets single parameter and its value in the client instance. +// It will be formed as query string for the request. +// +// For Example: `search=kitchen%20papers&size=large` +// in the URL after `?` mark. These query params will be added to all the request raised from +// this client instance. Also it can be overridden at request level Query Param options. +// +// See `Request.SetQueryParam` or `Request.SetQueryParams`. +// client. +// SetQueryParam("search", "kitchen papers"). +// SetQueryParam("size", "large") +func (c *Client) SetQueryParam(param, value string) *Client { + c.QueryParam.Set(param, value) + return c +} + +// SetQueryParams method sets multiple parameters and their values at one go in the client instance. +// It will be formed as query string for the request. +// +// For Example: `search=kitchen%20papers&size=large` +// in the URL after `?` mark. These query params will be added to all the request raised from this +// client instance. Also it can be overridden at request level Query Param options. +// +// See `Request.SetQueryParams` or `Request.SetQueryParam`. +// client.SetQueryParams(map[string]string{ +// "search": "kitchen papers", +// "size": "large", +// }) +func (c *Client) SetQueryParams(params map[string]string) *Client { + for p, v := range params { + c.SetQueryParam(p, v) + } + return c +} + +// SetFormData method sets Form parameters and their values in the client instance. +// It's applicable only HTTP method `POST` and `PUT` and requets content type would be set as +// `application/x-www-form-urlencoded`. These form data will be added to all the request raised from +// this client instance. Also it can be overridden at request level form data. +// +// See `Request.SetFormData`. +// client.SetFormData(map[string]string{ +// "access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F", +// "user_id": "3455454545", +// }) +func (c *Client) SetFormData(data map[string]string) *Client { + for k, v := range data { + c.FormData.Set(k, v) + } + return c +} + +// SetBasicAuth method sets the basic authentication header in the HTTP request. For Example: +// Authorization: Basic <base64-encoded-value> +// +// For Example: To set the header for username "go-resty" and password "welcome" +// client.SetBasicAuth("go-resty", "welcome") +// +// This basic auth information gets added to all the request rasied from this client instance. +// Also it can be overridden or set one at the request level is supported. +// +// See `Request.SetBasicAuth`. +func (c *Client) SetBasicAuth(username, password string) *Client { + c.UserInfo = &User{Username: username, Password: password} + return c +} + +// SetAuthToken method sets bearer auth token header in the HTTP request. For Example: +// Authorization: Bearer <auth-token-value-comes-here> +// +// For Example: To set auth token BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F +// +// client.SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F") +// +// This bearer auth token gets added to all the request rasied from this client instance. +// Also it can be overridden or set one at the request level is supported. +// +// See `Request.SetAuthToken`. +func (c *Client) SetAuthToken(token string) *Client { + c.Token = token + return c +} + +// R method creates a new request instance, its used for Get, Post, Put, Delete, Patch, Head, Options, etc. +func (c *Client) R() *Request { + r := &Request{ + QueryParam: url.Values{}, + FormData: url.Values{}, + Header: http.Header{}, + Cookies: make([]*http.Cookie, 0), + + client: c, + multipartFiles: []*File{}, + multipartFields: []*MultipartField{}, + pathParams: map[string]string{}, + jsonEscapeHTML: true, + } + return r +} + +// NewRequest is an alias for method `R()`. Creates a new request instance, its used for +// Get, Post, Put, Delete, Patch, Head, Options, etc. +func (c *Client) NewRequest() *Request { + return c.R() +} + +// OnBeforeRequest method appends request middleware into the before request chain. +// Its gets applied after default Resty request middlewares and before request +// been sent from Resty to host server. +// client.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error { +// // Now you have access to Client and Request instance +// // manipulate it as per your need +// +// return nil // if its success otherwise return error +// }) +func (c *Client) OnBeforeRequest(m func(*Client, *Request) error) *Client { + c.udBeforeRequest = append(c.udBeforeRequest, m) + return c +} + +// OnAfterResponse method appends response middleware into the after response chain. +// Once we receive response from host server, default Resty response middleware +// gets applied and then user assigened response middlewares applied. +// client.OnAfterResponse(func(c *resty.Client, r *resty.Response) error { +// // Now you have access to Client and Response instance +// // manipulate it as per your need +// +// return nil // if its success otherwise return error +// }) +func (c *Client) OnAfterResponse(m func(*Client, *Response) error) *Client { + c.afterResponse = append(c.afterResponse, m) + return c +} + +// SetPreRequestHook method sets the given pre-request function into resty client. +// It is called right before the request is fired. +// +// Note: Only one pre-request hook can be registered. Use `client.OnBeforeRequest` for mutilple. +func (c *Client) SetPreRequestHook(h func(*Client, *http.Request) error) *Client { + if c.preReqHook != nil { + c.log.Warnf("Overwriting an existing pre-request hook: %s", functionName(h)) + } + c.preReqHook = h + return c +} + +// SetDebug method enables the debug mode on Resty client. Client logs details of every request and response. +// For `Request` it logs information such as HTTP verb, Relative URL path, Host, Headers, Body if it has one. +// For `Response` it logs information such as Status, Response Time, Headers, Body if it has one. +// client.SetDebug(true) +func (c *Client) SetDebug(d bool) *Client { + c.Debug = d + return c +} + +// SetDebugBodyLimit sets the maximum size for which the response body will be logged in debug mode. +// client.SetDebugBodyLimit(1000000) +func (c *Client) SetDebugBodyLimit(sl int64) *Client { + c.debugBodySizeLimit = sl + return c +} + +// OnRequestLog method used to set request log callback into Resty. Registered callback gets +// called before the resty actually logs the information. +func (c *Client) OnRequestLog(rl func(*RequestLog) error) *Client { + if c.requestLog != nil { + c.log.Warnf("Overwriting an existing on-request-log callback from=%s to=%s", + functionName(c.requestLog), functionName(rl)) + } + c.requestLog = rl + return c +} + +// OnResponseLog method used to set response log callback into Resty. Registered callback gets +// called before the resty actually logs the information. +func (c *Client) OnResponseLog(rl func(*ResponseLog) error) *Client { + if c.responseLog != nil { + c.log.Warnf("Overwriting an existing on-response-log callback from=%s to=%s", + functionName(c.responseLog), functionName(rl)) + } + c.responseLog = rl + return c +} + +// SetDisableWarn method disables the warning message on Resty client. +// +// For Example: Resty warns the user when BasicAuth used on non-TLS mode. +// client.SetDisableWarn(true) +func (c *Client) SetDisableWarn(d bool) *Client { + c.DisableWarn = d + return c +} + +// SetAllowGetMethodPayload method allows the GET method with payload on Resty client. +// +// For Example: Resty allows the user sends request with a payload on HTTP GET method. +// client.SetAllowGetMethodPayload(true) +func (c *Client) SetAllowGetMethodPayload(a bool) *Client { + c.AllowGetMethodPayload = a + return c +} + +// SetLogger method sets given writer for logging Resty request and response details. +// +// Compliant to interface `resty.Logger`. +func (c *Client) SetLogger(l Logger) *Client { + c.log = l + return c +} + +// SetContentLength method enables the HTTP header `Content-Length` value for every request. +// By default Resty won't set `Content-Length`. +// client.SetContentLength(true) +// +// Also you have an option to enable for particular request. See `Request.SetContentLength` +func (c *Client) SetContentLength(l bool) *Client { + c.setContentLength = l + return c +} + +// SetTimeout method sets timeout for request raised from client. +// client.SetTimeout(time.Duration(1 * time.Minute)) +func (c *Client) SetTimeout(timeout time.Duration) *Client { + c.httpClient.Timeout = timeout + return c +} + +// SetError method is to register the global or client common `Error` object into Resty. +// It is used for automatic unmarshalling if response status code is greater than 399 and +// content type either JSON or XML. Can be pointer or non-pointer. +// client.SetError(&Error{}) +// // OR +// client.SetError(Error{}) +func (c *Client) SetError(err interface{}) *Client { + c.Error = typeOf(err) + return c +} + +// SetRedirectPolicy method sets the client redirect poilicy. Resty provides ready to use +// redirect policies. Wanna create one for yourself refer to `redirect.go`. +// +// client.SetRedirectPolicy(FlexibleRedirectPolicy(20)) +// +// // Need multiple redirect policies together +// client.SetRedirectPolicy(FlexibleRedirectPolicy(20), DomainCheckRedirectPolicy("host1.com", "host2.net")) +func (c *Client) SetRedirectPolicy(policies ...interface{}) *Client { + for _, p := range policies { + if _, ok := p.(RedirectPolicy); !ok { + c.log.Errorf("%v does not implement resty.RedirectPolicy (missing Apply method)", + functionName(p)) + } + } + + c.httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { + for _, p := range policies { + if err := p.(RedirectPolicy).Apply(req, via); err != nil { + return err + } + } + return nil // looks good, go ahead + } + + return c +} + +// SetRetryCount method enables retry on Resty client and allows you +// to set no. of retry count. Resty uses a Backoff mechanism. +func (c *Client) SetRetryCount(count int) *Client { + c.RetryCount = count + return c +} + +// SetRetryWaitTime method sets default wait time to sleep before retrying +// request. +// +// Default is 100 milliseconds. +func (c *Client) SetRetryWaitTime(waitTime time.Duration) *Client { + c.RetryWaitTime = waitTime + return c +} + +// SetRetryMaxWaitTime method sets max wait time to sleep before retrying +// request. +// +// Default is 2 seconds. +func (c *Client) SetRetryMaxWaitTime(maxWaitTime time.Duration) *Client { + c.RetryMaxWaitTime = maxWaitTime + return c +} + +// SetRetryAfter sets callback to calculate wait time between retries. +// Default (nil) implies exponential backoff with jitter +func (c *Client) SetRetryAfter(callback RetryAfterFunc) *Client { + c.RetryAfter = callback + return c +} + +// AddRetryCondition method adds a retry condition function to array of functions +// that are checked to determine if the request is retried. The request will +// retry if any of the functions return true and error is nil. +func (c *Client) AddRetryCondition(condition RetryConditionFunc) *Client { + c.RetryConditions = append(c.RetryConditions, condition) + return c +} + +// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. +// +// For Example: +// // One can set custom root-certificate. Refer: http://golang.org/pkg/crypto/tls/#example_Dial +// client.SetTLSClientConfig(&tls.Config{ RootCAs: roots }) +// +// // or One can disable security check (https) +// client.SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true }) +// +// Note: This method overwrites existing `TLSClientConfig`. +func (c *Client) SetTLSClientConfig(config *tls.Config) *Client { + transport, err := c.transport() + if err != nil { + c.log.Errorf("%v", err) + return c + } + transport.TLSClientConfig = config + return c +} + +// SetProxy method sets the Proxy URL and Port for Resty client. +// client.SetProxy("http://proxyserver:8888") +// +// OR Without this `SetProxy` method, you could also set Proxy via environment variable. +// +// Refer to godoc `http.ProxyFromEnvironment`. +func (c *Client) SetProxy(proxyURL string) *Client { + transport, err := c.transport() + if err != nil { + c.log.Errorf("%v", err) + return c + } + + pURL, err := url.Parse(proxyURL) + if err != nil { + c.log.Errorf("%v", err) + return c + } + + c.proxyURL = pURL + transport.Proxy = http.ProxyURL(c.proxyURL) + return c +} + +// RemoveProxy method removes the proxy configuration from Resty client +// client.RemoveProxy() +func (c *Client) RemoveProxy() *Client { + transport, err := c.transport() + if err != nil { + c.log.Errorf("%v", err) + return c + } + c.proxyURL = nil + transport.Proxy = nil + return c +} + +// SetCertificates method helps to set client certificates into Resty conveniently. +func (c *Client) SetCertificates(certs ...tls.Certificate) *Client { + config, err := c.tlsConfig() + if err != nil { + c.log.Errorf("%v", err) + return c + } + config.Certificates = append(config.Certificates, certs...) + return c +} + +// SetRootCertificate method helps to add one or more root certificates into Resty client +// client.SetRootCertificate("/path/to/root/pemFile.pem") +func (c *Client) SetRootCertificate(pemFilePath string) *Client { + rootPemData, err := ioutil.ReadFile(pemFilePath) + if err != nil { + c.log.Errorf("%v", err) + return c + } + + config, err := c.tlsConfig() + if err != nil { + c.log.Errorf("%v", err) + return c + } + if config.RootCAs == nil { + config.RootCAs = x509.NewCertPool() + } + + config.RootCAs.AppendCertsFromPEM(rootPemData) + return c +} + +// SetOutputDirectory method sets output directory for saving HTTP response into file. +// If the output directory not exists then resty creates one. This setting is optional one, +// if you're planning using absoule path in `Request.SetOutput` and can used together. +// client.SetOutputDirectory("/save/http/response/here") +func (c *Client) SetOutputDirectory(dirPath string) *Client { + c.outputDirectory = dirPath + return c +} + +// SetTransport method sets custom `*http.Transport` or any `http.RoundTripper` +// compatible interface implementation in the resty client. +// +// Note: +// +// - If transport is not type of `*http.Transport` then you may not be able to +// take advantage of some of the Resty client settings. +// +// - It overwrites the Resty client transport instance and it's configurations. +// +// transport := &http.Transport{ +// // somthing like Proxying to httptest.Server, etc... +// Proxy: func(req *http.Request) (*url.URL, error) { +// return url.Parse(server.URL) +// }, +// } +// +// client.SetTransport(transport) +func (c *Client) SetTransport(transport http.RoundTripper) *Client { + if transport != nil { + c.httpClient.Transport = transport + } + return c +} + +// SetScheme method sets custom scheme in the Resty client. It's way to override default. +// client.SetScheme("http") +func (c *Client) SetScheme(scheme string) *Client { + if !IsStringEmpty(scheme) { + c.scheme = scheme + } + return c +} + +// SetCloseConnection method sets variable `Close` in http request struct with the given +// value. More info: https://golang.org/src/net/http/request.go +func (c *Client) SetCloseConnection(close bool) *Client { + c.closeConnection = close + return c +} + +// SetDoNotParseResponse method instructs `Resty` not to parse the response body automatically. +// Resty exposes the raw response body as `io.ReadCloser`. Also do not forget to close the body, +// otherwise you might get into connection leaks, no connection reuse. +// +// Note: Response middlewares are not applicable, if you use this option. Basically you have +// taken over the control of response parsing from `Resty`. +func (c *Client) SetDoNotParseResponse(parse bool) *Client { + c.notParseResponse = parse + return c +} + +// SetPathParams method sets multiple URL path key-value pairs at one go in the +// Resty client instance. +// client.SetPathParams(map[string]string{ +// "userId": "sample@sample.com", +// "subAccountId": "100002", +// }) +// +// Result: +// URL - /v1/users/{userId}/{subAccountId}/details +// Composed URL - /v1/users/sample@sample.com/100002/details +// It replace the value of the key while composing request URL. Also it can be +// overridden at request level Path Params options, see `Request.SetPathParams`. +func (c *Client) SetPathParams(params map[string]string) *Client { + for p, v := range params { + c.pathParams[p] = v + } + return c +} + +// SetJSONEscapeHTML method is to enable/disable the HTML escape on JSON marshal. +// +// Note: This option only applicable to standard JSON Marshaller. +func (c *Client) SetJSONEscapeHTML(b bool) *Client { + c.jsonEscapeHTML = b + return c +} + +// EnableTrace method enables the Resty client trace for the requests fired from +// the client using `httptrace.ClientTrace` and provides insights. +// +// client := resty.New().EnableTrace() +// +// resp, err := client.R().Get("https://httpbin.org/get") +// fmt.Println("Error:", err) +// fmt.Println("Trace Info:", resp.Request.TraceInfo()) +// +// Also `Request.EnableTrace` available too to get trace info for single request. +// +// Since v2.0.0 +func (c *Client) EnableTrace() *Client { + c.trace = true + return c +} + +// DisableTrace method disables the Resty client trace. Refer to `Client.EnableTrace`. +// +// Since v2.0.0 +func (c *Client) DisableTrace() *Client { + c.trace = false + return c +} + +// IsProxySet method returns the true is proxy is set from resty client otherwise +// false. By default proxy is set from environment, refer to `http.ProxyFromEnvironment`. +func (c *Client) IsProxySet() bool { + return c.proxyURL != nil +} + +// GetClient method returns the current `http.Client` used by the resty client. +func (c *Client) GetClient() *http.Client { + return c.httpClient +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Client Unexported methods +//_______________________________________________________________________ + +// Executes method executes the given `Request` object and returns response +// error. +func (c *Client) execute(req *Request) (*Response, error) { + defer releaseBuffer(req.bodyBuf) + // Apply Request middleware + var err error + + // user defined on before request methods + // to modify the *resty.Request object + for _, f := range c.udBeforeRequest { + if err = f(c, req); err != nil { + return nil, err + } + } + + // resty middlewares + for _, f := range c.beforeRequest { + if err = f(c, req); err != nil { + return nil, err + } + } + + if hostHeader := req.Header.Get("Host"); hostHeader != "" { + req.RawRequest.Host = hostHeader + } + + // call pre-request if defined + if c.preReqHook != nil { + if err = c.preReqHook(c, req.RawRequest); err != nil { + return nil, err + } + } + + if err = requestLogger(c, req); err != nil { + return nil, err + } + + req.Time = time.Now() + resp, err := c.httpClient.Do(req.RawRequest) + endTime := time.Now() + + if c.trace || req.trace { + req.clientTrace.endTime = endTime + } + + response := &Response{ + Request: req, + RawResponse: resp, + receivedAt: endTime, + } + + if err != nil || req.notParseResponse || c.notParseResponse { + return response, err + } + + if !req.isSaveResponse { + defer closeq(resp.Body) + body := resp.Body + + // GitHub #142 & #187 + if strings.EqualFold(resp.Header.Get(hdrContentEncodingKey), "gzip") && resp.ContentLength != 0 { + if _, ok := body.(*gzip.Reader); !ok { + body, err = gzip.NewReader(body) + if err != nil { + return response, err + } + defer closeq(body) + } + } + + if response.body, err = ioutil.ReadAll(body); err != nil { + return response, err + } + + response.size = int64(len(response.body)) + } + + // Apply Response middleware + for _, f := range c.afterResponse { + if err = f(c, response); err != nil { + break + } + } + + return response, err +} + +// getting TLS client config if not exists then create one +func (c *Client) tlsConfig() (*tls.Config, error) { + transport, err := c.transport() + if err != nil { + return nil, err + } + if transport.TLSClientConfig == nil { + transport.TLSClientConfig = &tls.Config{} + } + return transport.TLSClientConfig, nil +} + +// Transport method returns `*http.Transport` currently in use or error +// in case currently used `transport` is not a `*http.Transport`. +func (c *Client) transport() (*http.Transport, error) { + if transport, ok := c.httpClient.Transport.(*http.Transport); ok { + return transport, nil + } + return nil, errors.New("current transport is not an *http.Transport instance") +} + +// just an internal helper method +func (c *Client) outputLogTo(w io.Writer) *Client { + c.log.(*logger).l.SetOutput(w) + return c +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// File struct and its methods +//_______________________________________________________________________ + +// File struct represent file information for multipart request +type File struct { + Name string + ParamName string + io.Reader +} + +// String returns string value of current file details +func (f *File) String() string { + return fmt.Sprintf("ParamName: %v; FileName: %v", f.ParamName, f.Name) +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// MultipartField struct +//_______________________________________________________________________ + +// MultipartField struct represent custom data part for multipart request +type MultipartField struct { + Param string + FileName string + ContentType string + io.Reader +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Unexported package methods +//_______________________________________________________________________ + +func createClient(hc *http.Client) *Client { + if hc.Transport == nil { + hc.Transport = createTransport(nil) + } + + c := &Client{ // not setting lang default values + QueryParam: url.Values{}, + FormData: url.Values{}, + Header: http.Header{}, + Cookies: make([]*http.Cookie, 0), + RetryWaitTime: defaultWaitTime, + RetryMaxWaitTime: defaultMaxWaitTime, + JSONMarshal: json.Marshal, + JSONUnmarshal: json.Unmarshal, + jsonEscapeHTML: true, + httpClient: hc, + debugBodySizeLimit: math.MaxInt32, + pathParams: make(map[string]string), + } + + // Logger + c.SetLogger(createLogger()) + + // default before request middlewares + c.beforeRequest = []func(*Client, *Request) error{ + parseRequestURL, + parseRequestHeader, + parseRequestBody, + createHTTPRequest, + addCredentials, + } + + // user defined request middlewares + c.udBeforeRequest = []func(*Client, *Request) error{} + + // default after response middlewares + c.afterResponse = []func(*Client, *Response) error{ + responseLogger, + parseResponseBody, + saveResponseIntoFile, + } + + return c +} + +func createTransport(localAddr net.Addr) *http.Transport { + dialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + } + if localAddr != nil { + dialer.LocalAddr = localAddr + } + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: dialer.DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + } +} diff --git a/vendor/github.com/go-resty/resty/v2/go.mod b/vendor/github.com/go-resty/resty/v2/go.mod new file mode 100644 index 000000000..b2b881ac4 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/go.mod @@ -0,0 +1,3 @@ +module github.com/go-resty/resty/v2 + +require golang.org/x/net v0.0.0-20190628185345-da137c7871d7 diff --git a/vendor/github.com/go-resty/resty/v2/middleware.go b/vendor/github.com/go-resty/resty/v2/middleware.go new file mode 100644 index 000000000..a662db853 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/middleware.go @@ -0,0 +1,514 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "bytes" + "encoding/xml" + "errors" + "fmt" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "net/url" + "os" + "path/filepath" + "reflect" + "strings" + "time" +) + +const debugRequestLogKey = "__restyDebugRequestLog" + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Request Middleware(s) +//_______________________________________________________________________ + +func parseRequestURL(c *Client, r *Request) error { + // GitHub #103 Path Params + if len(r.pathParams) > 0 { + for p, v := range r.pathParams { + r.URL = strings.Replace(r.URL, "{"+p+"}", url.PathEscape(v), -1) + } + } + if len(c.pathParams) > 0 { + for p, v := range c.pathParams { + r.URL = strings.Replace(r.URL, "{"+p+"}", url.PathEscape(v), -1) + } + } + + // Parsing request URL + reqURL, err := url.Parse(r.URL) + if err != nil { + return err + } + + // If Request.URL is relative path then added c.HostURL into + // the request URL otherwise Request.URL will be used as-is + if !reqURL.IsAbs() { + r.URL = reqURL.String() + if len(r.URL) > 0 && r.URL[0] != '/' { + r.URL = "/" + r.URL + } + + reqURL, err = url.Parse(c.HostURL + r.URL) + if err != nil { + return err + } + } + + // Adding Query Param + query := make(url.Values) + for k, v := range c.QueryParam { + for _, iv := range v { + query.Add(k, iv) + } + } + + for k, v := range r.QueryParam { + // remove query param from client level by key + // since overrides happens for that key in the request + query.Del(k) + + for _, iv := range v { + query.Add(k, iv) + } + } + + // GitHub #123 Preserve query string order partially. + // Since not feasible in `SetQuery*` resty methods, because + // standard package `url.Encode(...)` sorts the query params + // alphabetically + if len(query) > 0 { + if IsStringEmpty(reqURL.RawQuery) { + reqURL.RawQuery = query.Encode() + } else { + reqURL.RawQuery = reqURL.RawQuery + "&" + query.Encode() + } + } + + r.URL = reqURL.String() + + return nil +} + +func parseRequestHeader(c *Client, r *Request) error { + hdr := make(http.Header) + for k := range c.Header { + hdr[k] = append(hdr[k], c.Header[k]...) + } + + for k := range r.Header { + hdr.Del(k) + hdr[k] = append(hdr[k], r.Header[k]...) + } + + if IsStringEmpty(hdr.Get(hdrUserAgentKey)) { + hdr.Set(hdrUserAgentKey, hdrUserAgentValue) + } + + ct := hdr.Get(hdrContentTypeKey) + if IsStringEmpty(hdr.Get(hdrAcceptKey)) && !IsStringEmpty(ct) && + (IsJSONType(ct) || IsXMLType(ct)) { + hdr.Set(hdrAcceptKey, hdr.Get(hdrContentTypeKey)) + } + + r.Header = hdr + + return nil +} + +func parseRequestBody(c *Client, r *Request) (err error) { + if isPayloadSupported(r.Method, c.AllowGetMethodPayload) { + // Handling Multipart + if r.isMultiPart && !(r.Method == MethodPatch) { + if err = handleMultipart(c, r); err != nil { + return + } + + goto CL + } + + // Handling Form Data + if len(c.FormData) > 0 || len(r.FormData) > 0 { + handleFormData(c, r) + + goto CL + } + + // Handling Request body + if r.Body != nil { + handleContentType(c, r) + + if err = handleRequestBody(c, r); err != nil { + return + } + } + } + +CL: + // by default resty won't set content length, you can if you want to :) + if (c.setContentLength || r.setContentLength) && r.bodyBuf != nil { + r.Header.Set(hdrContentLengthKey, fmt.Sprintf("%d", r.bodyBuf.Len())) + } + + return +} + +func createHTTPRequest(c *Client, r *Request) (err error) { + if r.bodyBuf == nil { + if reader, ok := r.Body.(io.Reader); ok { + r.RawRequest, err = http.NewRequest(r.Method, r.URL, reader) + } else { + r.RawRequest, err = http.NewRequest(r.Method, r.URL, nil) + } + } else { + r.RawRequest, err = http.NewRequest(r.Method, r.URL, r.bodyBuf) + } + + if err != nil { + return + } + + // Assign close connection option + r.RawRequest.Close = c.closeConnection + + // Add headers into http request + r.RawRequest.Header = r.Header + + // Add cookies from client instance into http request + for _, cookie := range c.Cookies { + r.RawRequest.AddCookie(cookie) + } + + // Add cookies from request instance into http request + for _, cookie := range r.Cookies { + r.RawRequest.AddCookie(cookie) + } + + // it's for non-http scheme option + if r.RawRequest.URL != nil && r.RawRequest.URL.Scheme == "" { + r.RawRequest.URL.Scheme = c.scheme + r.RawRequest.URL.Host = r.URL + } + + // Use context if it was specified + if r.ctx != nil { + r.RawRequest = r.RawRequest.WithContext(r.ctx) + } + + // Enable trace + if c.trace || r.trace { + r.clientTrace = &clientTrace{} + r.RawRequest = r.RawRequest.WithContext(r.clientTrace.createContext()) + } + + // assign get body func for the underlying raw request instance + r.RawRequest.GetBody = func() (io.ReadCloser, error) { + // If r.bodyBuf present, return the copy + if r.bodyBuf != nil { + return ioutil.NopCloser(bytes.NewReader(r.bodyBuf.Bytes())), nil + } + + // Maybe body is `io.Reader`. + // Note: Resty user have to watchout for large body size of `io.Reader` + if r.RawRequest.Body != nil { + b, err := ioutil.ReadAll(r.RawRequest.Body) + if err != nil { + return nil, err + } + + // Restore the Body + closeq(r.RawRequest.Body) + r.RawRequest.Body = ioutil.NopCloser(bytes.NewBuffer(b)) + + // Return the Body bytes + return ioutil.NopCloser(bytes.NewBuffer(b)), nil + } + + return nil, nil + } + + return +} + +func addCredentials(c *Client, r *Request) error { + var isBasicAuth bool + // Basic Auth + if r.UserInfo != nil { // takes precedence + r.RawRequest.SetBasicAuth(r.UserInfo.Username, r.UserInfo.Password) + isBasicAuth = true + } else if c.UserInfo != nil { + r.RawRequest.SetBasicAuth(c.UserInfo.Username, c.UserInfo.Password) + isBasicAuth = true + } + + if !c.DisableWarn { + if isBasicAuth && !strings.HasPrefix(r.URL, "https") { + c.log.Warnf("Using Basic Auth in HTTP mode is not secure, use HTTPS") + } + } + + // Token Auth + if !IsStringEmpty(r.Token) { // takes precedence + r.RawRequest.Header.Set(hdrAuthorizationKey, "Bearer "+r.Token) + } else if !IsStringEmpty(c.Token) { + r.RawRequest.Header.Set(hdrAuthorizationKey, "Bearer "+c.Token) + } + + return nil +} + +func requestLogger(c *Client, r *Request) error { + if c.Debug { + rr := r.RawRequest + rl := &RequestLog{Header: copyHeaders(rr.Header), Body: r.fmtBodyString()} + if c.requestLog != nil { + if err := c.requestLog(rl); err != nil { + return err + } + } + // fmt.Sprintf("COOKIES:\n%s\n", composeCookies(c.GetClient().Jar, *rr.URL)) + + + reqLog := "\n==============================================================================\n" + + "~~~ REQUEST ~~~\n" + + fmt.Sprintf("%s %s %s\n", r.Method, rr.URL.RequestURI(), rr.Proto) + + fmt.Sprintf("HOST : %s\n", rr.URL.Host) + + fmt.Sprintf("HEADERS:\n%s\n", composeHeaders(c, r, rl.Header)) + + fmt.Sprintf("BODY :\n%v\n", rl.Body) + + "------------------------------------------------------------------------------\n" + + r.initValuesMap() + r.values[debugRequestLogKey] = reqLog + } + + return nil +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Response Middleware(s) +//_______________________________________________________________________ + +func responseLogger(c *Client, res *Response) error { + if c.Debug { + rl := &ResponseLog{Header: copyHeaders(res.Header()), Body: res.fmtBodyString(c.debugBodySizeLimit)} + if c.responseLog != nil { + if err := c.responseLog(rl); err != nil { + return err + } + } + + debugLog := res.Request.values[debugRequestLogKey].(string) + debugLog += "~~~ RESPONSE ~~~\n" + + fmt.Sprintf("STATUS : %s\n", res.Status()) + + fmt.Sprintf("RECEIVED AT : %v\n", res.ReceivedAt().Format(time.RFC3339Nano)) + + fmt.Sprintf("TIME DURATION: %v\n", res.Time()) + + "HEADERS :\n" + + composeHeaders(c, res.Request, rl.Header) + "\n" + if res.Request.isSaveResponse { + debugLog += fmt.Sprintf("BODY :\n***** RESPONSE WRITTEN INTO FILE *****\n") + } else { + debugLog += fmt.Sprintf("BODY :\n%v\n", rl.Body) + } + debugLog += "==============================================================================\n" + + c.log.Debugf(debugLog) + } + + return nil +} + +func parseResponseBody(c *Client, res *Response) (err error) { + if res.StatusCode() == http.StatusNoContent { + return + } + // Handles only JSON or XML content type + ct := firstNonEmpty(res.Header().Get(hdrContentTypeKey), res.Request.fallbackContentType) + if IsJSONType(ct) || IsXMLType(ct) { + // HTTP status code > 199 and < 300, considered as Result + if res.IsSuccess() { + if res.Request.Result != nil { + err = Unmarshalc(c, ct, res.body, res.Request.Result) + return + } + } + + // HTTP status code > 399, considered as Error + if res.IsError() { + // global error interface + if res.Request.Error == nil && c.Error != nil { + res.Request.Error = reflect.New(c.Error).Interface() + } + + if res.Request.Error != nil { + err = Unmarshalc(c, ct, res.body, res.Request.Error) + } + } + } + + return +} + +func handleMultipart(c *Client, r *Request) (err error) { + r.bodyBuf = acquireBuffer() + w := multipart.NewWriter(r.bodyBuf) + + for k, v := range c.FormData { + for _, iv := range v { + if err = w.WriteField(k, iv); err != nil { + return err + } + } + } + + for k, v := range r.FormData { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return + } + } else { // form value + if err = w.WriteField(k, iv); err != nil { + return err + } + } + } + } + + // #21 - adding io.Reader support + if len(r.multipartFiles) > 0 { + for _, f := range r.multipartFiles { + err = addFileReader(w, f) + if err != nil { + return + } + } + } + + // GitHub #130 adding multipart field support with content type + if len(r.multipartFields) > 0 { + for _, mf := range r.multipartFields { + if err = addMultipartFormField(w, mf); err != nil { + return + } + } + } + + r.Header.Set(hdrContentTypeKey, w.FormDataContentType()) + err = w.Close() + + return +} + +func handleFormData(c *Client, r *Request) { + formData := url.Values{} + + for k, v := range c.FormData { + for _, iv := range v { + formData.Add(k, iv) + } + } + + for k, v := range r.FormData { + // remove form data field from client level by key + // since overrides happens for that key in the request + formData.Del(k) + + for _, iv := range v { + formData.Add(k, iv) + } + } + + r.bodyBuf = bytes.NewBuffer([]byte(formData.Encode())) + r.Header.Set(hdrContentTypeKey, formContentType) + r.isFormData = true +} + +func handleContentType(c *Client, r *Request) { + contentType := r.Header.Get(hdrContentTypeKey) + if IsStringEmpty(contentType) { + contentType = DetectContentType(r.Body) + r.Header.Set(hdrContentTypeKey, contentType) + } +} + +func handleRequestBody(c *Client, r *Request) (err error) { + var bodyBytes []byte + contentType := r.Header.Get(hdrContentTypeKey) + kind := kindOf(r.Body) + r.bodyBuf = nil + + if reader, ok := r.Body.(io.Reader); ok { + if c.setContentLength || r.setContentLength { // keep backward compability + r.bodyBuf = acquireBuffer() + _, err = r.bodyBuf.ReadFrom(reader) + r.Body = nil + } else { + // Otherwise buffer less processing for `io.Reader`, sounds good. + return + } + } else if b, ok := r.Body.([]byte); ok { + bodyBytes = b + } else if s, ok := r.Body.(string); ok { + bodyBytes = []byte(s) + } else if IsJSONType(contentType) && + (kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice) { + bodyBytes, err = jsonMarshal(c, r, r.Body) + } else if IsXMLType(contentType) && (kind == reflect.Struct) { + bodyBytes, err = xml.Marshal(r.Body) + } + + if bodyBytes == nil && r.bodyBuf == nil { + err = errors.New("unsupported 'Body' type/value") + } + + // if any errors during body bytes handling, return it + if err != nil { + return + } + + // []byte into Buffer + if bodyBytes != nil && r.bodyBuf == nil { + r.bodyBuf = acquireBuffer() + _, _ = r.bodyBuf.Write(bodyBytes) + } + + return +} + +func saveResponseIntoFile(c *Client, res *Response) error { + if res.Request.isSaveResponse { + file := "" + + if len(c.outputDirectory) > 0 && !filepath.IsAbs(res.Request.outputFile) { + file += c.outputDirectory + string(filepath.Separator) + } + + file = filepath.Clean(file + res.Request.outputFile) + if err := createDirectory(filepath.Dir(file)); err != nil { + return err + } + + outFile, err := os.Create(file) + if err != nil { + return err + } + defer closeq(outFile) + + // io.Copy reads maximum 32kb size, it is perfect for large file download too + defer closeq(res.RawResponse.Body) + + written, err := io.Copy(outFile, res.RawResponse.Body) + if err != nil { + return err + } + + res.size = written + } + + return nil +} diff --git a/vendor/github.com/go-resty/resty/v2/redirect.go b/vendor/github.com/go-resty/resty/v2/redirect.go new file mode 100644 index 000000000..afbe13e80 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/redirect.go @@ -0,0 +1,101 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "errors" + "fmt" + "net" + "net/http" + "strings" +) + +type ( + // RedirectPolicy to regulate the redirects in the resty client. + // Objects implementing the RedirectPolicy interface can be registered as + // + // Apply function should return nil to continue the redirect jounery, otherwise + // return error to stop the redirect. + RedirectPolicy interface { + Apply(req *http.Request, via []*http.Request) error + } + + // The RedirectPolicyFunc type is an adapter to allow the use of ordinary functions as RedirectPolicy. + // If f is a function with the appropriate signature, RedirectPolicyFunc(f) is a RedirectPolicy object that calls f. + RedirectPolicyFunc func(*http.Request, []*http.Request) error +) + +// Apply calls f(req, via). +func (f RedirectPolicyFunc) Apply(req *http.Request, via []*http.Request) error { + return f(req, via) +} + +// NoRedirectPolicy is used to disable redirects in the HTTP client +// resty.SetRedirectPolicy(NoRedirectPolicy()) +func NoRedirectPolicy() RedirectPolicy { + return RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error { + return errors.New("auto redirect is disabled") + }) +} + +// FlexibleRedirectPolicy is convenient method to create No of redirect policy for HTTP client. +// resty.SetRedirectPolicy(FlexibleRedirectPolicy(20)) +func FlexibleRedirectPolicy(noOfRedirect int) RedirectPolicy { + return RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error { + if len(via) >= noOfRedirect { + return fmt.Errorf("stopped after %d redirects", noOfRedirect) + } + checkHostAndAddHeaders(req, via[0]) + return nil + }) +} + +// DomainCheckRedirectPolicy is convenient method to define domain name redirect rule in resty client. +// Redirect is allowed for only mentioned host in the policy. +// resty.SetRedirectPolicy(DomainCheckRedirectPolicy("host1.com", "host2.org", "host3.net")) +func DomainCheckRedirectPolicy(hostnames ...string) RedirectPolicy { + hosts := make(map[string]bool) + for _, h := range hostnames { + hosts[strings.ToLower(h)] = true + } + + fn := RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error { + if ok := hosts[getHostname(req.URL.Host)]; !ok { + return errors.New("redirect is not allowed as per DomainCheckRedirectPolicy") + } + + return nil + }) + + return fn +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Package Unexported methods +//_______________________________________________________________________ + +func getHostname(host string) (hostname string) { + if strings.Index(host, ":") > 0 { + host, _, _ = net.SplitHostPort(host) + } + hostname = strings.ToLower(host) + return +} + +// By default Golang will not redirect request headers +// after go throughing various discussion comments from thread +// https://github.com/golang/go/issues/4800 +// Resty will add all the headers during a redirect for the same host +func checkHostAndAddHeaders(cur *http.Request, pre *http.Request) { + curHostname := getHostname(cur.URL.Host) + preHostname := getHostname(pre.URL.Host) + if strings.EqualFold(curHostname, preHostname) { + for key, val := range pre.Header { + cur.Header[key] = val + } + } else { // only library User-Agent header is added + cur.Header.Set(hdrUserAgentKey, hdrUserAgentValue) + } +} diff --git a/vendor/github.com/go-resty/resty/v2/request.go b/vendor/github.com/go-resty/resty/v2/request.go new file mode 100644 index 000000000..c5fb7d358 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/request.go @@ -0,0 +1,724 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "net" + "net/http" + "net/url" + "reflect" + "strings" + "time" +) + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Request struct and methods +//_______________________________________________________________________ + +// Request struct is used to compose and fire individual request from +// resty client. Request provides an options to override client level +// settings and also an options for the request composition. +type Request struct { + URL string + Method string + Token string + QueryParam url.Values + FormData url.Values + Header http.Header + Time time.Time + Body interface{} + Result interface{} + Error interface{} + RawRequest *http.Request + SRV *SRVRecord + UserInfo *User + Cookies []*http.Cookie + + isMultiPart bool + isFormData bool + setContentLength bool + isSaveResponse bool + notParseResponse bool + jsonEscapeHTML bool + trace bool + outputFile string + fallbackContentType string + ctx context.Context + pathParams map[string]string + values map[string]interface{} + client *Client + bodyBuf *bytes.Buffer + clientTrace *clientTrace + multipartFiles []*File + multipartFields []*MultipartField +} + +// Context method returns the Context if its already set in request +// otherwise it creates new one using `context.Background()`. +func (r *Request) Context() context.Context { + if r.ctx == nil { + return context.Background() + } + return r.ctx +} + +// SetContext method sets the context.Context for current Request. It allows +// to interrupt the request execution if ctx.Done() channel is closed. +// See https://blog.golang.org/context article and the "context" package +// documentation. +func (r *Request) SetContext(ctx context.Context) *Request { + r.ctx = ctx + return r +} + +// SetHeader method is to set a single header field and its value in the current request. +// +// For Example: To set `Content-Type` and `Accept` as `application/json`. +// client.R(). +// SetHeader("Content-Type", "application/json"). +// SetHeader("Accept", "application/json") +// +// Also you can override header value, which was set at client instance level. +func (r *Request) SetHeader(header, value string) *Request { + r.Header.Set(header, value) + return r +} + +// SetHeaders method sets multiple headers field and its values at one go in the current request. +// +// For Example: To set `Content-Type` and `Accept` as `application/json` +// +// client.R(). +// SetHeaders(map[string]string{ +// "Content-Type": "application/json", +// "Accept": "application/json", +// }) +// Also you can override header value, which was set at client instance level. +func (r *Request) SetHeaders(headers map[string]string) *Request { + for h, v := range headers { + r.SetHeader(h, v) + } + return r +} + +// SetQueryParam method sets single parameter and its value in the current request. +// It will be formed as query string for the request. +// +// For Example: `search=kitchen%20papers&size=large` in the URL after `?` mark. +// client.R(). +// SetQueryParam("search", "kitchen papers"). +// SetQueryParam("size", "large") +// Also you can override query params value, which was set at client instance level. +func (r *Request) SetQueryParam(param, value string) *Request { + r.QueryParam.Set(param, value) + return r +} + +// SetQueryParams method sets multiple parameters and its values at one go in the current request. +// It will be formed as query string for the request. +// +// For Example: `search=kitchen%20papers&size=large` in the URL after `?` mark. +// client.R(). +// SetQueryParams(map[string]string{ +// "search": "kitchen papers", +// "size": "large", +// }) +// Also you can override query params value, which was set at client instance level. +func (r *Request) SetQueryParams(params map[string]string) *Request { + for p, v := range params { + r.SetQueryParam(p, v) + } + return r +} + +// SetQueryParamsFromValues method appends multiple parameters with multi-value +// (`url.Values`) at one go in the current request. It will be formed as +// query string for the request. +// +// For Example: `status=pending&status=approved&status=open` in the URL after `?` mark. +// client.R(). +// SetQueryParamsFromValues(url.Values{ +// "status": []string{"pending", "approved", "open"}, +// }) +// Also you can override query params value, which was set at client instance level. +func (r *Request) SetQueryParamsFromValues(params url.Values) *Request { + for p, v := range params { + for _, pv := range v { + r.QueryParam.Add(p, pv) + } + } + return r +} + +// SetQueryString method provides ability to use string as an input to set URL query string for the request. +// +// Using String as an input +// client.R(). +// SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more") +func (r *Request) SetQueryString(query string) *Request { + params, err := url.ParseQuery(strings.TrimSpace(query)) + if err == nil { + for p, v := range params { + for _, pv := range v { + r.QueryParam.Add(p, pv) + } + } + } else { + r.client.log.Errorf("%v", err) + } + return r +} + +// SetFormData method sets Form parameters and their values in the current request. +// It's applicable only HTTP method `POST` and `PUT` and requests content type would be set as +// `application/x-www-form-urlencoded`. +// client.R(). +// SetFormData(map[string]string{ +// "access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F", +// "user_id": "3455454545", +// }) +// Also you can override form data value, which was set at client instance level. +func (r *Request) SetFormData(data map[string]string) *Request { + for k, v := range data { + r.FormData.Set(k, v) + } + return r +} + +// SetFormDataFromValues method appends multiple form parameters with multi-value +// (`url.Values`) at one go in the current request. +// client.R(). +// SetFormDataFromValues(url.Values{ +// "search_criteria": []string{"book", "glass", "pencil"}, +// }) +// Also you can override form data value, which was set at client instance level. +func (r *Request) SetFormDataFromValues(data url.Values) *Request { + for k, v := range data { + for _, kv := range v { + r.FormData.Add(k, kv) + } + } + return r +} + +// SetBody method sets the request body for the request. It supports various realtime needs as easy. +// We can say its quite handy or powerful. Supported request body data types is `string`, +// `[]byte`, `struct`, `map`, `slice` and `io.Reader`. Body value can be pointer or non-pointer. +// Automatic marshalling for JSON and XML content type, if it is `struct`, `map`, or `slice`. +// +// Note: `io.Reader` is processed as bufferless mode while sending request. +// +// For Example: Struct as a body input, based on content type, it will be marshalled. +// client.R(). +// SetBody(User{ +// Username: "jeeva@myjeeva.com", +// Password: "welcome2resty", +// }) +// +// Map as a body input, based on content type, it will be marshalled. +// client.R(). +// SetBody(map[string]interface{}{ +// "username": "jeeva@myjeeva.com", +// "password": "welcome2resty", +// "address": &Address{ +// Address1: "1111 This is my street", +// Address2: "Apt 201", +// City: "My City", +// State: "My State", +// ZipCode: 00000, +// }, +// }) +// +// String as a body input. Suitable for any need as a string input. +// client.R(). +// SetBody(`{ +// "username": "jeeva@getrightcare.com", +// "password": "admin" +// }`) +// +// []byte as a body input. Suitable for raw request such as file upload, serialize & deserialize, etc. +// client.R(). +// SetBody([]byte("This is my raw request, sent as-is")) +func (r *Request) SetBody(body interface{}) *Request { + r.Body = body + return r +} + +// SetResult method is to register the response `Result` object for automatic unmarshalling for the request, +// if response status code is between 200 and 299 and content type either JSON or XML. +// +// Note: Result object can be pointer or non-pointer. +// client.R().SetResult(&AuthToken{}) +// // OR +// client.R().SetResult(AuthToken{}) +// +// Accessing a result value from response instance. +// response.Result().(*AuthToken) +func (r *Request) SetResult(res interface{}) *Request { + r.Result = getPointer(res) + return r +} + +// SetError method is to register the request `Error` object for automatic unmarshalling for the request, +// if response status code is greater than 399 and content type either JSON or XML. +// +// Note: Error object can be pointer or non-pointer. +// client.R().SetError(&AuthError{}) +// // OR +// client.R().SetError(AuthError{}) +// +// Accessing a error value from response instance. +// response.Error().(*AuthError) +func (r *Request) SetError(err interface{}) *Request { + r.Error = getPointer(err) + return r +} + +// SetFile method is to set single file field name and its path for multipart upload. +// client.R(). +// SetFile("my_file", "/Users/jeeva/Gas Bill - Sep.pdf") +func (r *Request) SetFile(param, filePath string) *Request { + r.isMultiPart = true + r.FormData.Set("@"+param, filePath) + return r +} + +// SetFiles method is to set multiple file field name and its path for multipart upload. +// client.R(). +// SetFiles(map[string]string{ +// "my_file1": "/Users/jeeva/Gas Bill - Sep.pdf", +// "my_file2": "/Users/jeeva/Electricity Bill - Sep.pdf", +// "my_file3": "/Users/jeeva/Water Bill - Sep.pdf", +// }) +func (r *Request) SetFiles(files map[string]string) *Request { + r.isMultiPart = true + for f, fp := range files { + r.FormData.Set("@"+f, fp) + } + return r +} + +// SetFileReader method is to set single file using io.Reader for multipart upload. +// client.R(). +// SetFileReader("profile_img", "my-profile-img.png", bytes.NewReader(profileImgBytes)). +// SetFileReader("notes", "user-notes.txt", bytes.NewReader(notesBytes)) +func (r *Request) SetFileReader(param, fileName string, reader io.Reader) *Request { + r.isMultiPart = true + r.multipartFiles = append(r.multipartFiles, &File{ + Name: fileName, + ParamName: param, + Reader: reader, + }) + return r +} + +// SetMultipartField method is to set custom data using io.Reader for multipart upload. +func (r *Request) SetMultipartField(param, fileName, contentType string, reader io.Reader) *Request { + r.isMultiPart = true + r.multipartFields = append(r.multipartFields, &MultipartField{ + Param: param, + FileName: fileName, + ContentType: contentType, + Reader: reader, + }) + return r +} + +// SetMultipartFields method is to set multiple data fields using io.Reader for multipart upload. +// +// For Example: +// client.R().SetMultipartFields( +// &resty.MultipartField{ +// Param: "uploadManifest1", +// FileName: "upload-file-1.json", +// ContentType: "application/json", +// Reader: strings.NewReader(`{"input": {"name": "Uploaded document 1", "_filename" : ["file1.txt"]}}`), +// }, +// &resty.MultipartField{ +// Param: "uploadManifest2", +// FileName: "upload-file-2.json", +// ContentType: "application/json", +// Reader: strings.NewReader(`{"input": {"name": "Uploaded document 2", "_filename" : ["file2.txt"]}}`), +// }) +// +// If you have slice already, then simply call- +// client.R().SetMultipartFields(fields...) +func (r *Request) SetMultipartFields(fields ...*MultipartField) *Request { + r.isMultiPart = true + r.multipartFields = append(r.multipartFields, fields...) + return r +} + +// SetContentLength method sets the HTTP header `Content-Length` value for current request. +// By default Resty won't set `Content-Length`. Also you have an option to enable for every +// request. +// +// See `Client.SetContentLength` +// client.R().SetContentLength(true) +func (r *Request) SetContentLength(l bool) *Request { + r.setContentLength = true + return r +} + +// SetBasicAuth method sets the basic authentication header in the current HTTP request. +// +// For Example: +// Authorization: Basic <base64-encoded-value> +// +// To set the header for username "go-resty" and password "welcome" +// client.R().SetBasicAuth("go-resty", "welcome") +// +// This method overrides the credentials set by method `Client.SetBasicAuth`. +func (r *Request) SetBasicAuth(username, password string) *Request { + r.UserInfo = &User{Username: username, Password: password} + return r +} + +// SetAuthToken method sets bearer auth token header in the current HTTP request. Header example: +// Authorization: Bearer <auth-token-value-comes-here> +// +// For Example: To set auth token BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F +// +// client.R().SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F") +// +// This method overrides the Auth token set by method `Client.SetAuthToken`. +func (r *Request) SetAuthToken(token string) *Request { + r.Token = token + return r +} + +// SetOutput method sets the output file for current HTTP request. Current HTTP response will be +// saved into given file. It is similar to `curl -o` flag. Absolute path or relative path can be used. +// If is it relative path then output file goes under the output directory, as mentioned +// in the `Client.SetOutputDirectory`. +// client.R(). +// SetOutput("/Users/jeeva/Downloads/ReplyWithHeader-v5.1-beta.zip"). +// Get("http://bit.ly/1LouEKr") +// +// Note: In this scenario `Response.Body` might be nil. +func (r *Request) SetOutput(file string) *Request { + r.outputFile = file + r.isSaveResponse = true + return r +} + +// SetSRV method sets the details to query the service SRV record and execute the +// request. +// client.R(). +// SetSRV(SRVRecord{"web", "testservice.com"}). +// Get("/get") +func (r *Request) SetSRV(srv *SRVRecord) *Request { + r.SRV = srv + return r +} + +// SetDoNotParseResponse method instructs `Resty` not to parse the response body automatically. +// Resty exposes the raw response body as `io.ReadCloser`. Also do not forget to close the body, +// otherwise you might get into connection leaks, no connection reuse. +// +// Note: Response middlewares are not applicable, if you use this option. Basically you have +// taken over the control of response parsing from `Resty`. +func (r *Request) SetDoNotParseResponse(parse bool) *Request { + r.notParseResponse = parse + return r +} + +// SetPathParams method sets multiple URL path key-value pairs at one go in the +// Resty current request instance. +// client.R().SetPathParams(map[string]string{ +// "userId": "sample@sample.com", +// "subAccountId": "100002", +// }) +// +// Result: +// URL - /v1/users/{userId}/{subAccountId}/details +// Composed URL - /v1/users/sample@sample.com/100002/details +// It replace the value of the key while composing request URL. Also you can +// override Path Params value, which was set at client instance level. +func (r *Request) SetPathParams(params map[string]string) *Request { + for p, v := range params { + r.pathParams[p] = v + } + return r +} + +// ExpectContentType method allows to provide fallback `Content-Type` for automatic unmarshalling +// when `Content-Type` response header is unavailable. +func (r *Request) ExpectContentType(contentType string) *Request { + r.fallbackContentType = contentType + return r +} + +// SetJSONEscapeHTML method is to enable/disable the HTML escape on JSON marshal. +// +// Note: This option only applicable to standard JSON Marshaller. +func (r *Request) SetJSONEscapeHTML(b bool) *Request { + r.jsonEscapeHTML = b + return r +} + +// SetCookie method appends a single cookie in the current request instance. +// client.R().SetCookie(&http.Cookie{ +// Name:"go-resty", +// Value:"This is cookie value", +// }) +// +// Note: Method appends the Cookie value into existing Cookie if already existing. +// +// Since v2.1.0 +func (r *Request) SetCookie(hc *http.Cookie) *Request { + r.Cookies = append(r.Cookies, hc) + return r +} + +// SetCookies method sets an array of cookies in the current request instance. +// cookies := []*http.Cookie{ +// &http.Cookie{ +// Name:"go-resty-1", +// Value:"This is cookie 1 value", +// }, +// &http.Cookie{ +// Name:"go-resty-2", +// Value:"This is cookie 2 value", +// }, +// } +// +// // Setting a cookies into resty's current request +// client.R().SetCookies(cookies) +// +// Note: Method appends the Cookie value into existing Cookie if already existing. +// +// Since v2.1.0 +func (r *Request) SetCookies(rs []*http.Cookie) *Request { + r.Cookies = append(r.Cookies, rs...) + return r +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// HTTP request tracing +//_______________________________________________________________________ + +// EnableTrace method enables trace for the current request +// using `httptrace.ClientTrace` and provides insights. +// +// client := resty.New() +// +// resp, err := client.R().EnableTrace().Get("https://httpbin.org/get") +// fmt.Println("Error:", err) +// fmt.Println("Trace Info:", resp.Request.TraceInfo()) +// +// See `Client.EnableTrace` available too to get trace info for all requests. +// +// Since v2.0.0 +func (r *Request) EnableTrace() *Request { + r.trace = true + return r +} + +// TraceInfo method returns the trace info for the request. +// +// Since v2.0.0 +func (r *Request) TraceInfo() TraceInfo { + ct := r.clientTrace + return TraceInfo{ + DNSLookup: ct.dnsDone.Sub(ct.dnsStart), + ConnTime: ct.gotConn.Sub(ct.getConn), + TLSHandshake: ct.tlsHandshakeDone.Sub(ct.tlsHandshakeStart), + ServerTime: ct.gotFirstResponseByte.Sub(ct.wroteRequest), + ResponseTime: ct.endTime.Sub(ct.gotFirstResponseByte), + TotalTime: ct.endTime.Sub(ct.getConn), + IsConnReused: ct.gotConnInfo.Reused, + IsConnWasIdle: ct.gotConnInfo.WasIdle, + ConnIdleTime: ct.gotConnInfo.IdleTime, + } +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// HTTP verb method starts here +//_______________________________________________________________________ + +// Get method does GET HTTP request. It's defined in section 4.3.1 of RFC7231. +func (r *Request) Get(url string) (*Response, error) { + return r.Execute(MethodGet, url) +} + +// Head method does HEAD HTTP request. It's defined in section 4.3.2 of RFC7231. +func (r *Request) Head(url string) (*Response, error) { + return r.Execute(MethodHead, url) +} + +// Post method does POST HTTP request. It's defined in section 4.3.3 of RFC7231. +func (r *Request) Post(url string) (*Response, error) { + return r.Execute(MethodPost, url) +} + +// Put method does PUT HTTP request. It's defined in section 4.3.4 of RFC7231. +func (r *Request) Put(url string) (*Response, error) { + return r.Execute(MethodPut, url) +} + +// Delete method does DELETE HTTP request. It's defined in section 4.3.5 of RFC7231. +func (r *Request) Delete(url string) (*Response, error) { + return r.Execute(MethodDelete, url) +} + +// Options method does OPTIONS HTTP request. It's defined in section 4.3.7 of RFC7231. +func (r *Request) Options(url string) (*Response, error) { + return r.Execute(MethodOptions, url) +} + +// Patch method does PATCH HTTP request. It's defined in section 2 of RFC5789. +func (r *Request) Patch(url string) (*Response, error) { + return r.Execute(MethodPatch, url) +} + +// Execute method performs the HTTP request with given HTTP method and URL +// for current `Request`. +// resp, err := client.R().Execute(resty.GET, "http://httpbin.org/get") +func (r *Request) Execute(method, url string) (*Response, error) { + var addrs []*net.SRV + var err error + + if r.isMultiPart && !(method == MethodPost || method == MethodPut || method == MethodPatch) { + return nil, fmt.Errorf("multipart content is not allowed in HTTP verb [%v]", method) + } + + if r.SRV != nil { + _, addrs, err = net.LookupSRV(r.SRV.Service, "tcp", r.SRV.Domain) + if err != nil { + return nil, err + } + } + + r.Method = method + r.URL = r.selectAddr(addrs, url, 0) + + if r.client.RetryCount == 0 { + return r.client.execute(r) + } + + var resp *Response + attempt := 0 + err = Backoff( + func() (*Response, error) { + attempt++ + + r.URL = r.selectAddr(addrs, url, attempt) + + resp, err = r.client.execute(r) + if err != nil { + r.client.log.Errorf("%v, Attempt %v", err, attempt) + } + + return resp, err + }, + Retries(r.client.RetryCount), + WaitTime(r.client.RetryWaitTime), + MaxWaitTime(r.client.RetryMaxWaitTime), + RetryConditions(r.client.RetryConditions), + ) + + return resp, err +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// SRVRecord struct +//_______________________________________________________________________ + +// SRVRecord struct holds the data to query the SRV record for the +// following service. +type SRVRecord struct { + Service string + Domain string +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Request Unexported methods +//_______________________________________________________________________ + +func (r *Request) fmtBodyString() (body string) { + body = "***** NO CONTENT *****" + if isPayloadSupported(r.Method, r.client.AllowGetMethodPayload) { + if _, ok := r.Body.(io.Reader); ok { + body = "***** BODY IS io.Reader *****" + return + } + + // multipart or form-data + if r.isMultiPart || r.isFormData { + body = r.bodyBuf.String() + return + } + + // request body data + if r.Body == nil { + return + } + var prtBodyBytes []byte + var err error + + contentType := r.Header.Get(hdrContentTypeKey) + kind := kindOf(r.Body) + if canJSONMarshal(contentType, kind) { + prtBodyBytes, err = json.MarshalIndent(&r.Body, "", " ") + } else if IsXMLType(contentType) && (kind == reflect.Struct) { + prtBodyBytes, err = xml.MarshalIndent(&r.Body, "", " ") + } else if b, ok := r.Body.(string); ok { + if IsJSONType(contentType) { + bodyBytes := []byte(b) + out := acquireBuffer() + defer releaseBuffer(out) + if err = json.Indent(out, bodyBytes, "", " "); err == nil { + prtBodyBytes = out.Bytes() + } + } else { + body = b + return + } + } else if b, ok := r.Body.([]byte); ok { + body = base64.StdEncoding.EncodeToString(b) + } + + if prtBodyBytes != nil && err == nil { + body = string(prtBodyBytes) + } + } + + return +} + +func (r *Request) selectAddr(addrs []*net.SRV, path string, attempt int) string { + if addrs == nil { + return path + } + + idx := attempt % len(addrs) + domain := strings.TrimRight(addrs[idx].Target, ".") + path = strings.TrimLeft(path, "/") + + return fmt.Sprintf("%s://%s:%d/%s", r.client.scheme, domain, addrs[idx].Port, path) +} + +func (r *Request) initValuesMap() { + if r.values == nil { + r.values = make(map[string]interface{}) + } +} + +var noescapeJSONMarshal = func(v interface{}) ([]byte, error) { + buf := acquireBuffer() + defer releaseBuffer(buf) + encoder := json.NewEncoder(buf) + encoder.SetEscapeHTML(false) + err := encoder.Encode(v) + return buf.Bytes(), err +} diff --git a/vendor/github.com/go-resty/resty/v2/response.go b/vendor/github.com/go-resty/resty/v2/response.go new file mode 100644 index 000000000..673aeeba7 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/response.go @@ -0,0 +1,160 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + "time" +) + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Response struct and methods +//_______________________________________________________________________ + +// Response struct holds response values of executed request. +type Response struct { + Request *Request + RawResponse *http.Response + + body []byte + size int64 + receivedAt time.Time +} + +// Body method returns HTTP response as []byte array for the executed request. +// +// Note: `Response.Body` might be nil, if `Request.SetOutput` is used. +func (r *Response) Body() []byte { + if r.RawResponse == nil { + return []byte{} + } + return r.body +} + +// Status method returns the HTTP status string for the executed request. +// Example: 200 OK +func (r *Response) Status() string { + if r.RawResponse == nil { + return "" + } + return r.RawResponse.Status +} + +// StatusCode method returns the HTTP status code for the executed request. +// Example: 200 +func (r *Response) StatusCode() int { + if r.RawResponse == nil { + return 0 + } + return r.RawResponse.StatusCode +} + +// Result method returns the response value as an object if it has one +func (r *Response) Result() interface{} { + return r.Request.Result +} + +// Error method returns the error object if it has one +func (r *Response) Error() interface{} { + return r.Request.Error +} + +// Header method returns the response headers +func (r *Response) Header() http.Header { + if r.RawResponse == nil { + return http.Header{} + } + return r.RawResponse.Header +} + +// Cookies method to access all the response cookies +func (r *Response) Cookies() []*http.Cookie { + if r.RawResponse == nil { + return make([]*http.Cookie, 0) + } + return r.RawResponse.Cookies() +} + +// String method returns the body of the server response as String. +func (r *Response) String() string { + if r.body == nil { + return "" + } + return strings.TrimSpace(string(r.body)) +} + +// Time method returns the time of HTTP response time that from request we sent and received a request. +// +// See `Response.ReceivedAt` to know when client recevied response and see `Response.Request.Time` to know +// when client sent a request. +func (r *Response) Time() time.Duration { + if r.Request.clientTrace != nil { + return r.receivedAt.Sub(r.Request.clientTrace.getConn) + } + return r.receivedAt.Sub(r.Request.Time) +} + +// ReceivedAt method returns when response got recevied from server for the request. +func (r *Response) ReceivedAt() time.Time { + return r.receivedAt +} + +// Size method returns the HTTP response size in bytes. Ya, you can relay on HTTP `Content-Length` header, +// however it won't be good for chucked transfer/compressed response. Since Resty calculates response size +// at the client end. You will get actual size of the http response. +func (r *Response) Size() int64 { + return r.size +} + +// RawBody method exposes the HTTP raw response body. Use this method in-conjunction with `SetDoNotParseResponse` +// option otherwise you get an error as `read err: http: read on closed response body`. +// +// Do not forget to close the body, otherwise you might get into connection leaks, no connection reuse. +// Basically you have taken over the control of response parsing from `Resty`. +func (r *Response) RawBody() io.ReadCloser { + if r.RawResponse == nil { + return nil + } + return r.RawResponse.Body +} + +// IsSuccess method returns true if HTTP status `code >= 200 and <= 299` otherwise false. +func (r *Response) IsSuccess() bool { + return r.StatusCode() > 199 && r.StatusCode() < 300 +} + +// IsError method returns true if HTTP status `code >= 400` otherwise false. +func (r *Response) IsError() bool { + return r.StatusCode() > 399 +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Response Unexported methods +//_______________________________________________________________________ + +func (r *Response) fmtBodyString(sl int64) string { + if r.body != nil { + if int64(len(r.body)) > sl { + return fmt.Sprintf("***** RESPONSE TOO LARGE (size - %d) *****", len(r.body)) + } + ct := r.Header().Get(hdrContentTypeKey) + if IsJSONType(ct) { + out := acquireBuffer() + defer releaseBuffer(out) + err := json.Indent(out, r.body, "", " ") + if err != nil { + return fmt.Sprintf("*** Error: Unable to format response body - \"%s\" ***\n\nLog Body as-is:\n%s", err, r.String()) + } + return out.String() + } + return r.String() + } + + return "***** NO CONTENT *****" +} diff --git a/vendor/github.com/go-resty/resty/v2/resty.go b/vendor/github.com/go-resty/resty/v2/resty.go new file mode 100644 index 000000000..df2489a53 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/resty.go @@ -0,0 +1,40 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +// Package resty provides Simple HTTP and REST client library for Go. +package resty + +import ( + "net" + "net/http" + "net/http/cookiejar" + + "golang.org/x/net/publicsuffix" +) + +// Version # of resty +const Version = "2.1.0" + +// New method creates a new Resty client. +func New() *Client { + cookieJar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) + return createClient(&http.Client{ + Jar: cookieJar, + }) +} + +// NewWithClient method creates a new Resty client with given `http.Client`. +func NewWithClient(hc *http.Client) *Client { + return createClient(hc) +} + +// NewWithLocalAddr method creates a new Resty client with given Local Address +// to dial from. +func NewWithLocalAddr(localAddr net.Addr) *Client { + cookieJar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) + return createClient(&http.Client{ + Jar: cookieJar, + Transport: createTransport(localAddr), + }) +} diff --git a/vendor/github.com/go-resty/resty/v2/retry.go b/vendor/github.com/go-resty/resty/v2/retry.go new file mode 100644 index 000000000..5f34cb6f2 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/retry.go @@ -0,0 +1,180 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "context" + "math" + "math/rand" + "time" +) + +const ( + defaultMaxRetries = 3 + defaultWaitTime = time.Duration(100) * time.Millisecond + defaultMaxWaitTime = time.Duration(2000) * time.Millisecond +) + +type ( + // Option is to create convenient retry options like wait time, max retries, etc. + Option func(*Options) + + // RetryConditionFunc type is for retry condition function + // input: non-nil Response OR request execution error + RetryConditionFunc func(*Response, error) bool + + // RetryAfterFunc returns time to wait before retry + // For example, it can parse HTTP Retry-After header + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + // Non-nil error is returned if it is found that request is not retryable + // (0, nil) is a special result means 'use default algorithm' + RetryAfterFunc func(*Client, *Response) (time.Duration, error) + + // Options struct is used to hold retry settings. + Options struct { + maxRetries int + waitTime time.Duration + maxWaitTime time.Duration + retryConditions []RetryConditionFunc + } +) + +// Retries sets the max number of retries +func Retries(value int) Option { + return func(o *Options) { + o.maxRetries = value + } +} + +// WaitTime sets the default wait time to sleep between requests +func WaitTime(value time.Duration) Option { + return func(o *Options) { + o.waitTime = value + } +} + +// MaxWaitTime sets the max wait time to sleep between requests +func MaxWaitTime(value time.Duration) Option { + return func(o *Options) { + o.maxWaitTime = value + } +} + +// RetryConditions sets the conditions that will be checked for retry. +func RetryConditions(conditions []RetryConditionFunc) Option { + return func(o *Options) { + o.retryConditions = conditions + } +} + +// Backoff retries with increasing timeout duration up until X amount of retries +// (Default is 3 attempts, Override with option Retries(n)) +func Backoff(operation func() (*Response, error), options ...Option) error { + // Defaults + opts := Options{ + maxRetries: defaultMaxRetries, + waitTime: defaultWaitTime, + maxWaitTime: defaultMaxWaitTime, + retryConditions: []RetryConditionFunc{}, + } + + for _, o := range options { + o(&opts) + } + + var ( + resp *Response + err error + ) + + for attempt := 0; attempt < opts.maxRetries; attempt++ { + resp, err = operation() + ctx := context.Background() + if resp != nil && resp.Request.ctx != nil { + ctx = resp.Request.ctx + } + if ctx.Err() != nil { + return err + } + + needsRetry := err != nil // retry on operation errors by default + + for _, condition := range opts.retryConditions { + needsRetry = condition(resp, err) + if needsRetry { + break + } + } + + if !needsRetry { + return err + } + + waitTime, err2 := sleepDuration(resp, opts.waitTime, opts.maxWaitTime, attempt) + if err2 != nil { + if err == nil { + err = err2 + } + return err + } + + select { + case <-time.After(waitTime): + case <-ctx.Done(): + return ctx.Err() + } + } + + return err +} + +func sleepDuration(resp *Response, min, max time.Duration, attempt int) (time.Duration, error) { + const maxInt = 1<<31 - 1 // max int for arch 386 + + if max < 0 { + max = maxInt + } + + if resp == nil { + goto defaultCase + } + + // 1. Check for custom callback + if retryAfterFunc := resp.Request.client.RetryAfter; retryAfterFunc != nil { + result, err := retryAfterFunc(resp.Request.client, resp) + if err != nil { + return 0, err // i.e. 'API quota exceeded' + } + if result == 0 { + goto defaultCase + } + if result < 0 || max < result { + result = max + } + if result < min { + result = min + } + return result, nil + } + + // 2. Return capped exponential backoff with jitter + // http://www.awsarchitectureblog.com/2015/03/backoff.html +defaultCase: + base := float64(min) + capLevel := float64(max) + + temp := math.Min(capLevel, base*math.Exp2(float64(attempt))) + ri := int(temp / 2) + if ri <= 0 { + ri = maxInt // max int for arch 386 + } + result := time.Duration(math.Abs(float64(ri + rand.Intn(ri)))) + + if result < min { + result = min + } + + return result, nil +} diff --git a/vendor/github.com/go-resty/resty/v2/trace.go b/vendor/github.com/go-resty/resty/v2/trace.go new file mode 100644 index 000000000..a38823821 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/trace.go @@ -0,0 +1,111 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "context" + "crypto/tls" + "net/http/httptrace" + "time" +) + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// TraceInfo struct +//_______________________________________________________________________ + +// TraceInfo struct is used provide request trace info such as DNS lookup +// duration, Connection obtain duration, Server processing duration, etc. +// +// Since v2.0.0 +type TraceInfo struct { + // DNSLookup is a duration that transport took to perform + // DNS lookup. + DNSLookup time.Duration + + // ConnTime is a duration that took to obtain a successful connection. + ConnTime time.Duration + + // TLSHandshake is a duration that TLS handshake took place. + TLSHandshake time.Duration + + // ServerTime is a duration that server took to respond first byte. + ServerTime time.Duration + + // ResponseTime is a duration since first response byte from server to + // request completion. + ResponseTime time.Duration + + // TotalTime is a duration that total request took end-to-end. + TotalTime time.Duration + + // IsConnReused is whether this connection has been previously + // used for another HTTP request. + IsConnReused bool + + // IsConnWasIdle is whether this connection was obtained from an + // idle pool. + IsConnWasIdle bool + + // ConnIdleTime is a duration how long the connection was previously + // idle, if IsConnWasIdle is true. + ConnIdleTime time.Duration +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// CientTrace struct and its methods +//_______________________________________________________________________ + +// tracer struct maps the `httptrace.ClientTrace` hooks into Fields +// with same naming for easy understanding. Plus additional insights +// Request. +type clientTrace struct { + getConn time.Time + gotConn time.Time + gotFirstResponseByte time.Time + dnsStart time.Time + dnsDone time.Time + tlsHandshakeStart time.Time + tlsHandshakeDone time.Time + wroteRequest time.Time + endTime time.Time + gotConnInfo httptrace.GotConnInfo +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Trace unexported methods +//_______________________________________________________________________ + +func (t *clientTrace) createContext() context.Context { + return httptrace.WithClientTrace( + context.Background(), + &httptrace.ClientTrace{ + GetConn: func(_ string) { + t.getConn = time.Now() + }, + GotConn: func(ci httptrace.GotConnInfo) { + t.gotConn = time.Now() + t.gotConnInfo = ci + }, + GotFirstResponseByte: func() { + t.gotFirstResponseByte = time.Now() + }, + DNSStart: func(_ httptrace.DNSStartInfo) { + t.dnsStart = time.Now() + }, + DNSDone: func(_ httptrace.DNSDoneInfo) { + t.dnsDone = time.Now() + }, + TLSHandshakeStart: func() { + t.tlsHandshakeStart = time.Now() + }, + TLSHandshakeDone: func(_ tls.ConnectionState, _ error) { + t.tlsHandshakeDone = time.Now() + }, + WroteRequest: func(_ httptrace.WroteRequestInfo) { + t.wroteRequest = time.Now() + }, + }, + ) +} diff --git a/vendor/github.com/go-resty/resty/v2/util.go b/vendor/github.com/go-resty/resty/v2/util.go new file mode 100644 index 000000000..814314115 --- /dev/null +++ b/vendor/github.com/go-resty/resty/v2/util.go @@ -0,0 +1,333 @@ +// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. +// resty source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package resty + +import ( + "bytes" + "encoding/xml" + "fmt" + "io" + "log" + "mime/multipart" + "net/http" + "net/textproto" + "os" + "path/filepath" + "reflect" + "runtime" + "sort" + "strings" +) + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Logger interface +//_______________________________________________________________________ + +// Logger interface is to abstract the logging from Resty. Gives control to +// the Resty users, choice of the logger. +type Logger interface { + Errorf(format string, v ...interface{}) + Warnf(format string, v ...interface{}) + Debugf(format string, v ...interface{}) +} + +func createLogger() *logger { + l := &logger{l: log.New(os.Stderr, "", log.Ldate|log.Lmicroseconds)} + return l +} + +var _ Logger = (*logger)(nil) + +type logger struct { + l *log.Logger +} + +func (l *logger) Errorf(format string, v ...interface{}) { + l.output("ERROR RESTY "+format, v...) +} + +func (l *logger) Warnf(format string, v ...interface{}) { + l.output("WARN RESTY "+format, v...) +} + +func (l *logger) Debugf(format string, v ...interface{}) { + l.output("DEBUG RESTY "+format, v...) +} + +func (l *logger) output(format string, v ...interface{}) { + if len(v) == 0 { + l.l.Print(format) + return + } + l.l.Printf(format, v...) +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Package Helper methods +//_______________________________________________________________________ + +// IsStringEmpty method tells whether given string is empty or not +func IsStringEmpty(str string) bool { + return len(strings.TrimSpace(str)) == 0 +} + +// DetectContentType method is used to figure out `Request.Body` content type for request header +func DetectContentType(body interface{}) string { + contentType := plainTextType + kind := kindOf(body) + switch kind { + case reflect.Struct, reflect.Map: + contentType = jsonContentType + case reflect.String: + contentType = plainTextType + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = jsonContentType + } + } + + return contentType +} + +// IsJSONType method is to check JSON content type or not +func IsJSONType(ct string) bool { + return jsonCheck.MatchString(ct) +} + +// IsXMLType method is to check XML content type or not +func IsXMLType(ct string) bool { + return xmlCheck.MatchString(ct) +} + +// Unmarshalc content into object from JSON or XML +func Unmarshalc(c *Client, ct string, b []byte, d interface{}) (err error) { + if IsJSONType(ct) { + err = c.JSONUnmarshal(b, d) + } else if IsXMLType(ct) { + err = xml.Unmarshal(b, d) + } + + return +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// RequestLog and ResponseLog type +//_______________________________________________________________________ + +// RequestLog struct is used to collected information from resty request +// instance for debug logging. It sent to request log callback before resty +// actually logs the information. +type RequestLog struct { + Header http.Header + Body string +} + +// ResponseLog struct is used to collected information from resty response +// instance for debug logging. It sent to response log callback before resty +// actually logs the information. +type ResponseLog struct { + Header http.Header + Body string +} + +//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ +// Package Unexported methods +//_______________________________________________________________________ + +// way to disable the HTML escape as opt-in +func jsonMarshal(c *Client, r *Request, d interface{}) ([]byte, error) { + if !r.jsonEscapeHTML { + return noescapeJSONMarshal(d) + } else if !c.jsonEscapeHTML { + return noescapeJSONMarshal(d) + } + return c.JSONMarshal(d) +} + +func firstNonEmpty(v ...string) string { + for _, s := range v { + if !IsStringEmpty(s) { + return s + } + } + return "" +} + +var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") + +func escapeQuotes(s string) string { + return quoteEscaper.Replace(s) +} + +func createMultipartHeader(param, fileName, contentType string) textproto.MIMEHeader { + hdr := make(textproto.MIMEHeader) + + var contentDispositionValue string + if IsStringEmpty(fileName) { + contentDispositionValue = fmt.Sprintf(`form-data; name="%s"`, param) + } else { + contentDispositionValue = fmt.Sprintf(`form-data; name="%s"; filename="%s"`, + param, escapeQuotes(fileName)) + } + hdr.Set("Content-Disposition", contentDispositionValue) + + if !IsStringEmpty(contentType) { + hdr.Set(hdrContentTypeKey, contentType) + } + return hdr +} + +func addMultipartFormField(w *multipart.Writer, mf *MultipartField) error { + partWriter, err := w.CreatePart(createMultipartHeader(mf.Param, mf.FileName, mf.ContentType)) + if err != nil { + return err + } + + _, err = io.Copy(partWriter, mf.Reader) + return err +} + +func writeMultipartFormFile(w *multipart.Writer, fieldName, fileName string, r io.Reader) error { + // Auto detect actual multipart content type + cbuf := make([]byte, 512) + size, err := r.Read(cbuf) + if err != nil { + return err + } + + partWriter, err := w.CreatePart(createMultipartHeader(fieldName, fileName, http.DetectContentType(cbuf))) + if err != nil { + return err + } + + if _, err = partWriter.Write(cbuf[:size]); err != nil { + return err + } + + _, err = io.Copy(partWriter, r) + return err +} + +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer closeq(file) + return writeMultipartFormFile(w, fieldName, filepath.Base(path), file) +} + +func addFileReader(w *multipart.Writer, f *File) error { + return writeMultipartFormFile(w, f.ParamName, f.Name, f.Reader) +} + +func getPointer(v interface{}) interface{} { + vv := valueOf(v) + if vv.Kind() == reflect.Ptr { + return v + } + return reflect.New(vv.Type()).Interface() +} + +func isPayloadSupported(m string, allowMethodGet bool) bool { + return !(m == MethodHead || m == MethodOptions || (m == MethodGet && !allowMethodGet)) +} + +func typeOf(i interface{}) reflect.Type { + return indirect(valueOf(i)).Type() +} + +func valueOf(i interface{}) reflect.Value { + return reflect.ValueOf(i) +} + +func indirect(v reflect.Value) reflect.Value { + return reflect.Indirect(v) +} + +func kindOf(v interface{}) reflect.Kind { + return typeOf(v).Kind() +} + +func createDirectory(dir string) (err error) { + if _, err = os.Stat(dir); err != nil { + if os.IsNotExist(err) { + if err = os.MkdirAll(dir, 0755); err != nil { + return + } + } + } + return +} + +func canJSONMarshal(contentType string, kind reflect.Kind) bool { + return IsJSONType(contentType) && (kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice) +} + +func functionName(i interface{}) string { + return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() +} + +func acquireBuffer() *bytes.Buffer { + return bufPool.Get().(*bytes.Buffer) +} + +func releaseBuffer(buf *bytes.Buffer) { + if buf != nil { + buf.Reset() + bufPool.Put(buf) + } +} + +func closeq(v interface{}) { + if c, ok := v.(io.Closer); ok { + sliently(c.Close()) + } +} + +func sliently(_ ...interface{}) {} + +func composeHeaders(c *Client, r *Request, hdrs http.Header) string { + str := make([]string, 0, len(hdrs)) + for _, k := range sortHeaderKeys(hdrs) { + var v string + if k == "Cookie" { + cv := strings.TrimSpace(strings.Join(hdrs[k], ", ")) + for _, c := range c.GetClient().Jar.Cookies(r.RawRequest.URL) { + if cv != "" { + cv = cv + "; " + c.String() + } else { + cv = c.String() + } + } + v = strings.TrimSpace(fmt.Sprintf("%25s: %s", k, cv)) + } else { + v = strings.TrimSpace(fmt.Sprintf("%25s: %s", k, strings.Join(hdrs[k], ", "))) + } + if v != "" { + str = append(str, "\t"+v) + } + } + return strings.Join(str, "\n") +} + +func sortHeaderKeys(hdrs http.Header) []string { + keys := make([]string, 0, len(hdrs)) + for key := range hdrs { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func copyHeaders(hdrs http.Header) http.Header { + nh := http.Header{} + for k, v := range hdrs { + nh[k] = v + } + return nh +} diff --git a/vendor/github.com/mitchellh/mapstructure/.travis.yml b/vendor/github.com/mitchellh/mapstructure/.travis.yml new file mode 100644 index 000000000..1689c7d73 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - "1.11.x" + - tip + +script: + - go test diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md new file mode 100644 index 000000000..3b3cb723f --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -0,0 +1,21 @@ +## 1.1.2 + +* Fix error when decode hook decodes interface implementation into interface + type. [GH-140] + +## 1.1.1 + +* Fix panic that can happen in `decodePtr` + +## 1.1.0 + +* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] +* Support struct to struct decoding [GH-137] +* If source map value is nil, then destination map value is nil (instead of empty) +* If source slice value is nil, then destination slice value is nil (instead of empty) +* If source pointer is nil, then destination pointer is set to nil (instead of + allocated zero value of type) + +## 1.0.0 + +* Initial tagged stable release. diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +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. diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 000000000..0018dc7d9 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure [](https://godoc.org/github.com/mitchellh/mapstructure) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 000000000..1f0abc65a --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,217 @@ +package mapstructure + +import ( + "errors" + "fmt" + "net" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Type, to reflect.Type, + data interface{}) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from, to, data) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), data) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + var err error + for _, f1 := range fs { + data, err = DecodeHookExec(f1, f, t, data) + if err != nil { + return nil, err + } + + // Modify the from kind to be correct with the new data + f = nil + if val := reflect.ValueOf(data); val.IsValid() { + f = val.Type() + } + } + + return data, nil + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 000000000..47a99e5af --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,50 @@ +package mapstructure + +import ( + "errors" + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +// WrappedErrors implements the errwrap.Wrapper interface to make this +// return value more useful with the errwrap and go-multierror libraries. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + + result := make([]error, len(e.Errors)) + for i, e := range e.Errors { + result[i] = errors.New(e) + } + + return result +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/go.mod b/vendor/github.com/mitchellh/mapstructure/go.mod new file mode 100644 index 000000000..d2a712562 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/mapstructure diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 000000000..256ee63fb --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,1149 @@ +// Package mapstructure exposes functionality to convert an arbitrary +// map[string]interface{} into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +package mapstructure + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type should be DecodeHookFuncType or DecodeHookFuncKind. +// Either is accepted. Types are a superset of Kinds (Types can return +// Kinds) and are generally a richer thing to use, but Kinds are simpler +// if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +// DecodeHookFuncType is a DecodeHookFunc which has complete information about +// the source and target types. +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) + +// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the +// source and target types. +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. + // + // If an error is returned, the entire decode will fail with that + // error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // - slice of maps to a merged map + // - single values are converted to slices if required. Each + // element is weakly decoded. For example: "4" can become []int{4} + // if the target type is an int slice. + // + WeaklyTypedInput bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string +} + +// Decode takes an input structure and uses reflection to translate it to +// the output structure. output must be a pointer to a map or struct. +func Decode(input interface{}, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// DecodeMetadata is the same as Decode, but is shorthand to +// enable metadata collection. See DecoderConfig for more info. +func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecodeMetadata is the same as Decode, but is shorthand to +// enable both WeaklyTypedInput and metadata collection. See +// DecoderConfig for more info. +func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(input interface{}) error { + return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { + var inputVal reflect.Value + if input != nil { + inputVal = reflect.ValueOf(input) + + // We need to check here if input is a typed nil. Typed nils won't + // match the "input == nil" below so we check that here. + if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { + input = nil + } + } + + if input == nil { + // If the data is nil, then we don't set anything, unless ZeroFields is set + // to true. + if d.config.ZeroFields { + outVal.Set(reflect.Zero(outVal.Type())) + + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + } + return nil + } + + if !inputVal.IsValid() { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the input. + var err error + input, err = DecodeHookExec( + d.config.DecodeHook, + inputVal.Type(), outVal.Type(), input) + if err != nil { + return fmt.Errorf("error decoding '%s': %s", name, err) + } + } + + var err error + outputKind := getKind(outVal) + switch outputKind { + case reflect.Bool: + err = d.decodeBool(name, input, outVal) + case reflect.Interface: + err = d.decodeBasic(name, input, outVal) + case reflect.String: + err = d.decodeString(name, input, outVal) + case reflect.Int: + err = d.decodeInt(name, input, outVal) + case reflect.Uint: + err = d.decodeUint(name, input, outVal) + case reflect.Float32: + err = d.decodeFloat(name, input, outVal) + case reflect.Struct: + err = d.decodeStruct(name, input, outVal) + case reflect.Map: + err = d.decodeMap(name, input, outVal) + case reflect.Ptr: + err = d.decodePtr(name, input, outVal) + case reflect.Slice: + err = d.decodeSlice(name, input, outVal) + case reflect.Array: + err = d.decodeArray(name, input, outVal) + case reflect.Func: + err = d.decodeFunc(name, input, outVal) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metainput. + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + if val.IsValid() && val.Elem().IsValid() { + return d.decode(name, data, val.Elem()) + } + + dataVal := reflect.ValueOf(data) + + // If the input data is a pointer, and the assigned type is the dereference + // of that exact pointer, then indirect it so that we can assign it. + // Example: *string to string + if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { + dataVal = reflect.Indirect(dataVal) + } + + if !dataVal.IsValid() { + dataVal = reflect.Zero(val.Type()) + } + + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch elemKind { + case reflect.Uint8: + var uints []uint8 + if dataKind == reflect.Array { + uints = make([]uint8, dataVal.Len(), dataVal.Len()) + for i := range uints { + uints[i] = dataVal.Index(i).Interface().(uint8) + } + } else { + uints = dataVal.Interface().([]uint8) + } + val.SetString(string(uints)) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Int64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetInt(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(dataVal.Float()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Float64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetFloat(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + // Check input type and based on the input type jump to the proper func + dataVal := reflect.Indirect(reflect.ValueOf(data)) + switch dataVal.Kind() { + case reflect.Map: + return d.decodeMapFromMap(name, dataVal, val, valMap) + + case reflect.Struct: + return d.decodeMapFromStruct(name, dataVal, val, valMap) + + case reflect.Array, reflect.Slice: + if d.config.WeaklyTypedInput { + return d.decodeMapFromSlice(name, dataVal, val, valMap) + } + + fallthrough + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + // Special case for BC reasons (covered by tests) + if dataVal.Len() == 0 { + val.Set(valMap) + return nil + } + + for i := 0; i < dataVal.Len(); i++ { + err := d.decode( + fmt.Sprintf("%s[%d]", name, i), + dataVal.Index(i).Interface(), val) + if err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Accumulate errors + errors := make([]string, 0) + + // If the input data is empty, then we just match what the input data is. + if dataVal.Len() == 0 { + if dataVal.IsNil() { + if !val.IsNil() { + val.Set(dataVal) + } + } else { + // Set to empty allocated value + val.Set(valMap) + } + + return nil + } + + for _, k := range dataVal.MapKeys() { + fieldName := fmt.Sprintf("%s[%s]", name, k) + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + typ := dataVal.Type() + for i := 0; i < typ.NumField(); i++ { + // Get the StructField first since this is a cheap operation. If the + // field is unexported, then ignore it. + f := typ.Field(i) + if f.PkgPath != "" { + continue + } + + // Next get the actual value of this field and verify it is assignable + // to the map value. + v := dataVal.Field(i) + if !v.Type().AssignableTo(valMap.Type().Elem()) { + return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + } + + tagValue := f.Tag.Get(d.config.TagName) + tagParts := strings.Split(tagValue, ",") + + // Determine the name of the key in the map + keyName := f.Name + if tagParts[0] != "" { + if tagParts[0] == "-" { + continue + } + keyName = tagParts[0] + } + + // If "squash" is specified in the tag, we squash the field down. + squash := false + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + if squash && v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } + + switch v.Kind() { + // this is an embedded struct, so handle it differently + case reflect.Struct: + x := reflect.New(v.Type()) + x.Elem().Set(v) + + vType := valMap.Type() + vKeyType := vType.Key() + vElemType := vType.Elem() + mType := reflect.MapOf(vKeyType, vElemType) + vMap := reflect.MakeMap(mType) + + err := d.decode(keyName, x.Interface(), vMap) + if err != nil { + return err + } + + if squash { + for _, k := range vMap.MapKeys() { + valMap.SetMapIndex(k, vMap.MapIndex(k)) + } + } else { + valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) + } + + default: + valMap.SetMapIndex(reflect.ValueOf(keyName), v) + } + } + + if val.CanAddr() { + val.Set(valMap) + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { + // If the input data is nil, then we want to just set the output + // pointer to be nil as well. + isNil := data == nil + if !isNil { + switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { + case reflect.Chan, + reflect.Func, + reflect.Interface, + reflect.Map, + reflect.Ptr, + reflect.Slice: + isNil = v.IsNil() + } + } + if isNil { + if !val.IsNil() && val.CanSet() { + nilValue := reflect.New(val.Type()).Elem() + val.Set(nilValue) + } + + return nil + } + + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + if val.CanSet() { + realVal := val + if realVal.IsNil() || d.config.ZeroFields { + realVal = reflect.New(valElemType) + } + + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return err + } + + val.Set(realVal) + } else { + if err := d.decode(name, data, reflect.Indirect(val)); err != nil { + return err + } + } + return nil +} + +func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if val.Type() != dataVal.Type() { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + valSlice := val + if valSlice.IsNil() || d.config.ZeroFields { + if d.config.WeaklyTypedInput { + switch { + // Slice and array we use the normal logic + case dataValKind == reflect.Slice, dataValKind == reflect.Array: + break + + // Empty maps turn into empty slices + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } + // Create slice of maps of other sizes + return d.decodeSlice(name, []interface{}{data}, val) + + case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: + return d.decodeSlice(name, []byte(dataVal.String()), val) + + // All other types we try to convert to the slice type + // and "lift" it into it. i.e. a string becomes a string slice. + default: + // Just re-try this function with data as a slice. + return d.decodeSlice(name, []interface{}{data}, val) + } + } + + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + + // If the input value is empty, then don't allocate since non-nil != nil + if dataVal.Len() == 0 { + return nil + } + + // Make a new slice to hold our result, same size as the original data. + valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } + currentField := valSlice.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + arrayType := reflect.ArrayOf(valType.Len(), valElemType) + + valArray := val + + if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Empty maps turn into empty arrays + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.Zero(arrayType)) + return nil + } + + // All other types we try to convert to the array type + // and "lift" it into it. i.e. a string becomes a string array. + default: + // Just re-try this function with data as a slice. + return d.decodeArray(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + if dataVal.Len() > arrayType.Len() { + return fmt.Errorf( + "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + + } + + // Make a new array to hold our result, same size as the original data. + valArray = reflect.New(arrayType).Elem() + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valArray.Index(i) + + fieldName := fmt.Sprintf("%s[%d]", name, i) + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the array we built up + val.Set(valArray) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + switch dataValKind { + case reflect.Map: + return d.decodeStructFromMap(name, dataVal, val) + + case reflect.Struct: + // Not the most efficient way to do this but we can optimize later if + // we want to. To convert from struct to struct we go to map first + // as an intermediary. + m := make(map[string]interface{}) + mval := reflect.Indirect(reflect.ValueOf(&m)) + if err := d.decodeMapFromStruct(name, dataVal, mval, mval); err != nil { + return err + } + + result := d.decodeStructFromMap(name, mval, val) + return result + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + fieldKind := fieldType.Type.Kind() + + // If "squash" is specified in the tag, we squash the field down. + squash := false + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + } + + if squash { + if fieldKind != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) + } else { + structs = append(structs, structVal.FieldByName(fieldType.Name)) + } + continue + } + + // Normal struct field, store it away + fields = append(fields, field{fieldType, structVal.Field(i)}) + } + } + + // for fieldType, field := range fields { + for _, f := range fields { + field, fieldValue := f.field, f.val + fieldName := field.Name + + tagValue := field.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if strings.EqualFold(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Just ignore. + continue + } + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = fmt.Sprintf("%s.%s", name, fieldName) + } + + if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { + errors = appendErrors(errors, err) + } + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = fmt.Sprintf("%s.%s", name, key) + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + } + + return nil +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go new file mode 100644 index 000000000..200617ea8 --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/list.go @@ -0,0 +1,181 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// Package publicsuffix provides a public suffix list based on data from +// https://publicsuffix.org/ +// +// A public suffix is one under which Internet users can directly register +// names. It is related to, but different from, a TLD (top level domain). +// +// "com" is a TLD (top level domain). Top level means it has no dots. +// +// "com" is also a public suffix. Amazon and Google have registered different +// siblings under that domain: "amazon.com" and "google.com". +// +// "au" is another TLD, again because it has no dots. But it's not "amazon.au". +// Instead, it's "amazon.com.au". +// +// "com.au" isn't an actual TLD, because it's not at the top level (it has +// dots). But it is an eTLD (effective TLD), because that's the branching point +// for domain name registrars. +// +// Another name for "an eTLD" is "a public suffix". Often, what's more of +// interest is the eTLD+1, or one more label than the public suffix. For +// example, browsers partition read/write access to HTTP cookies according to +// the eTLD+1. Web pages served from "amazon.com.au" can't read cookies from +// "google.com.au", but web pages served from "maps.google.com" can share +// cookies from "www.google.com", so you don't have to sign into Google Maps +// separately from signing into Google Web Search. Note that all four of those +// domains have 3 labels and 2 dots. The first two domains are each an eTLD+1, +// the last two are not (but share the same eTLD+1: "google.com"). +// +// All of these domains have the same eTLD+1: +// - "www.books.amazon.co.uk" +// - "books.amazon.co.uk" +// - "amazon.co.uk" +// Specifically, the eTLD+1 is "amazon.co.uk", because the eTLD is "co.uk". +// +// There is no closed form algorithm to calculate the eTLD of a domain. +// Instead, the calculation is data driven. This package provides a +// pre-compiled snapshot of Mozilla's PSL (Public Suffix List) data at +// https://publicsuffix.org/ +package publicsuffix // import "golang.org/x/net/publicsuffix" + +// TODO: specify case sensitivity and leading/trailing dot behavior for +// func PublicSuffix and func EffectiveTLDPlusOne. + +import ( + "fmt" + "net/http/cookiejar" + "strings" +) + +// List implements the cookiejar.PublicSuffixList interface by calling the +// PublicSuffix function. +var List cookiejar.PublicSuffixList = list{} + +type list struct{} + +func (list) PublicSuffix(domain string) string { + ps, _ := PublicSuffix(domain) + return ps +} + +func (list) String() string { + return version +} + +// PublicSuffix returns the public suffix of the domain using a copy of the +// publicsuffix.org database compiled into the library. +// +// icann is whether the public suffix is managed by the Internet Corporation +// for Assigned Names and Numbers. If not, the public suffix is either a +// privately managed domain (and in practice, not a top level domain) or an +// unmanaged top level domain (and not explicitly mentioned in the +// publicsuffix.org list). For example, "foo.org" and "foo.co.uk" are ICANN +// domains, "foo.dyndns.org" and "foo.blogspot.co.uk" are private domains and +// "cromulent" is an unmanaged top level domain. +// +// Use cases for distinguishing ICANN domains like "foo.com" from private +// domains like "foo.appspot.com" can be found at +// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases +func PublicSuffix(domain string) (publicSuffix string, icann bool) { + lo, hi := uint32(0), uint32(numTLD) + s, suffix, icannNode, wildcard := domain, len(domain), false, false +loop: + for { + dot := strings.LastIndex(s, ".") + if wildcard { + icann = icannNode + suffix = 1 + dot + } + if lo == hi { + break + } + f := find(s[1+dot:], lo, hi) + if f == notFound { + break + } + + u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) + icannNode = u&(1<<nodesBitsICANN-1) != 0 + u >>= nodesBitsICANN + u = children[u&(1<<nodesBitsChildren-1)] + lo = u & (1<<childrenBitsLo - 1) + u >>= childrenBitsLo + hi = u & (1<<childrenBitsHi - 1) + u >>= childrenBitsHi + switch u & (1<<childrenBitsNodeType - 1) { + case nodeTypeNormal: + suffix = 1 + dot + case nodeTypeException: + suffix = 1 + len(s) + break loop + } + u >>= childrenBitsNodeType + wildcard = u&(1<<childrenBitsWildcard-1) != 0 + if !wildcard { + icann = icannNode + } + + if dot == -1 { + break + } + s = s[:dot] + } + if suffix == len(domain) { + // If no rules match, the prevailing rule is "*". + return domain[1+strings.LastIndex(domain, "."):], icann + } + return domain[suffix:], icann +} + +const notFound uint32 = 1<<32 - 1 + +// find returns the index of the node in the range [lo, hi) whose label equals +// label, or notFound if there is no such node. The range is assumed to be in +// strictly increasing node label order. +func find(label string, lo, hi uint32) uint32 { + for lo < hi { + mid := lo + (hi-lo)/2 + s := nodeLabel(mid) + if s < label { + lo = mid + 1 + } else if s == label { + return mid + } else { + hi = mid + } + } + return notFound +} + +// nodeLabel returns the label for the i'th node. +func nodeLabel(i uint32) string { + x := nodes[i] + length := x & (1<<nodesBitsTextLength - 1) + x >>= nodesBitsTextLength + offset := x & (1<<nodesBitsTextOffset - 1) + return text[offset : offset+length] +} + +// EffectiveTLDPlusOne returns the effective top level domain plus one more +// label. For example, the eTLD+1 for "foo.bar.golang.org" is "golang.org". +func EffectiveTLDPlusOne(domain string) (string, error) { + if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") || strings.Contains(domain, "..") { + return "", fmt.Errorf("publicsuffix: empty label in domain %q", domain) + } + + suffix, _ := PublicSuffix(domain) + if len(domain) <= len(suffix) { + return "", fmt.Errorf("publicsuffix: cannot derive eTLD+1 for domain %q", domain) + } + i := len(domain) - len(suffix) - 1 + if domain[i] != '.' { + return "", fmt.Errorf("publicsuffix: invalid public suffix %q for domain %q", suffix, domain) + } + return domain[1+strings.LastIndex(domain[:i], "."):], nil +} diff --git a/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/golang.org/x/net/publicsuffix/table.go new file mode 100644 index 000000000..8e1c9d3dd --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/table.go @@ -0,0 +1,10150 @@ +// generated by go run gen.go; DO NOT EDIT + +package publicsuffix + +const version = "publicsuffix.org's public_suffix_list.dat, git revision dbe9da0a8abeab1b6257c57668d1ecb584189951 (2020-05-27T00:50:31Z)" + +const ( + nodesBitsChildren = 10 + nodesBitsICANN = 1 + nodesBitsTextOffset = 15 + nodesBitsTextLength = 6 + + childrenBitsWildcard = 1 + childrenBitsNodeType = 2 + childrenBitsHi = 14 + childrenBitsLo = 14 +) + +const ( + nodeTypeNormal = 0 + nodeTypeException = 1 + nodeTypeParentOnly = 2 +) + +// numTLD is the number of top level domains. +const numTLD = 1525 + +// Text is the combined text of all labels. +const text = "9guacuiababia-goracleaningroks-theatree12hpalermomahachijoinvill" + + "eksvikaracoldwarszawabogadobeaemcloud66bjarkoyusuharabjerkreimdb" + + "altimore-og-romsdalipayokozebizenakanotoddenavuotnarashinobninsk" + + "aragandaustevoll-o-g-i-naval-d-aosta-valleyboltateshinanomachimk" + + "entateyamagrocerybnikeisenbahn4tatarantours3-ap-northeast-2ix443" + + "2-balsan-suedtirolkuszczytnoipirangamvik12bjugnieznord-frontierb" + + "lackfridayusuisservehumourbloombergbauernishiazaindielddanuorrin" + + "digenamsosnowiechernihivgubs3-website-sa-east-1bloxcms3-website-" + + "us-east-1bluedaemoneyuu2-localhostoregontrailroadrayddnsfreebox-" + + "osascoli-picenordre-landraydns3-website-us-west-1bmoattachments3" + + "-website-us-west-2bms5yuzawabmwedeploybnrwegroweibolognagasakind" + + "eroybomloabathsbchernivtsiciliabondrivefsnillfjordrobaknoluoktac" + + "hikawakuyabukievennodesadoes-itvedestrandrudupontariobranconakan" + + "iikawatanagurabonnishigoddabookinghostfoldnavyboomlair-traffic-c" + + "ontrolleyboschaefflerdalivornohtawaramotoineppueblockbustermezja" + + "mpagefrontapparachutinglobalashovhachinohedmarkarpaczeladzlglobo" + + "avistanbulsan-sudtirolombardynaliaskimitsubatamibugattiffanycher" + + "novtsymantechnologybostikaruizawabostonakijinsekikogentappsselfi" + + "paraglidinglogoweirbotanicalgardenishiharabotanicgardenishiizuna" + + "zukindustriabotanynysagaeroclubmedecincinnationwidealerbouncemer" + + "ckmsdnipropetrovskjervoyageometre-experts-comptablesakyotanabell" + + "unord-aurdalpha-myqnapcloudaccesscambridgeiseiyoichippubetsubets" + + "ugarugbydgoszczecinemagentositecnologiabounty-fullensakerryprope" + + "rtiesalangenishikatakinoueboutiquebechirurgiens-dentistes-en-fra" + + "ncebozen-sudtirolomzaporizhzhegurindustriesteamfamberkeleybozen-" + + "suedtirolondrinapleskarumaifarmsteadurbanamexhibitionishikatsura" + + "git-reposalondonetskasaokamiminersaltdalorenskogloppenzaolbia-te" + + "mpio-olbiatempioolbialystokkepnogatagajobojinfinitintelligencebp" + + "lacedogawarabikomaezakirunorddalotenkawabrandywinevalleybrasilia" + + "brindisibenikindlebtimnetzparisor-fronishikawazukamisunagawabris" + + "toloseyouriparliamentjomeloyalistoragebritishcolumbialowiezagani" + + "shimerabroadcastleclerchiryukyuragifuchungbukharavennagatorodoyb" + + "roadwaybroke-itjxfinitybrokerbronnoysundurhamburglugmbhartipscbg" + + "minakamichiharabrothermesaverdealstahaugesunderseaportsinfolldal" + + "ottebrowsersafetymarketsaludweberbrumunddalottokonamegatakazakin" + + "ternationalfirearmsalvadordalibabalena-devicesalzburgmodellingmx" + + "javald-aostarnbergretakanabeautysvardoesntexisteingeekashibataka" + + "tsukiyosatokamachintaifun-dnsdojolsterbrunelastxn--0trq7p7nnishi" + + "nomiyashironomutashinaintuitkmaxxn--11b4c3dynathomebuiltwithdark" + + "ashiharabrusselsamegawabruxellesamnangerbryansklepparmattelekomm" + + "unikationishinoomotegobrynewhollandyndns-at-homedepotenzamamidsu" + + "ndyndns-at-workisboringrimstadyndns-blogdnsampalacebuskerudinewj" + + "erseybuzentsujiiebuzzwellbeingzonebwfarsundyndns-freeboxosloftra" + + "nakanojoetsuwanouchikujogaszkolancashirecreationishinoshimatsuur" + + "abzhitomirumalatvuopmicrolightingripebzzcommunexus-2community-pr" + + "ochowicecomoarekecomparemarkerryhotelsantacruzsantafedjejuifmetl" + + "ifeinsurancecompute-1computerhistoryofscience-fictioncomsecurity" + + "tacticsantamariakecondoshichinohealth-carereformitakeharaconfere" + + "nceconstructionconsuladonnaharimalopolskanlandyndns-remotewdyndn" + + "s-serverisignconsultanthropologyconsultingrpartycontactozsdeltaj" + + "irittogliattis-a-caterercontagematsubaracontemporaryarteducation" + + "alchikugodontexistmein-iservebeercontractorskenconventureshinode" + + "arthruherecipescaravantaacookingchannelsdvrdnsfor-better-thanawa" + + "tchandclockasukabedzin-berlindasdaburcooluroycooperativano-frank" + + "ivskolefrakkestadyndns-webhopencraftrani-andria-barletta-trani-a" + + "ndriacopenhagencyclopedichofunatoriginstitutemasekashiwaracoprod" + + "uctionsantoandreamhostersanukis-a-celticsfancorsicagliaricoharuo" + + "vatraniandriabarlettatraniandriacorvettemp-dnsaobernardocosenzak" + + "opanecosidnshome-webserverdalutskasumigaurawa-mazowszexnetnedalu" + + "xurycostumedicinakaiwamizawatchesaogoncartoonartdecologiacouchpo" + + "tatofriesaotomeldaluzerncouklugsmilegallocus-3councilvivanovolda" + + "couponsapporocq-acranbrookuwanalyticsardegnarusawacrdyndns-wikir" + + "kenesardiniacreditcardyndns-workshopitsitexaskoyabearalvahkikuch" + + "ikuseikarugalsacecreditunioncremonashgabadaddjaguarqcxn--12cfi8i" + + "xb8lcrewildlifedorainfracloudfrontdoorcricketrzyncrimeast-kazakh" + + "stanangercrotonecrownipasadenaritakurashikis-a-chefashioncrsvpas" + + "sagensarlcruisesarpsborgruecryptonomichigangwoncuisinellajollame" + + "ricanexpressexyculturalcentertainmentranoycuneocupcakecuritiback" + + "yardsarufutsunomiyawakasaikaitakofuefukihaboromskoguidegreecurva" + + "lled-aostaverncymrussiacyonabaruminamidaitomanchestercyouthachio" + + "jiyahooguyfetsundynnsasayamafgujohanamakinoharafhvalerfidoomdnst" + + "racefieldynservebbsasebofagemologicallyngenfigueresinstagingulen" + + "filateliafilegear-audnedalnfilegear-deatnulvikatowicefilegear-gb" + + "izfilegear-iefilegear-jpmorganfilegear-sgunmanxn--1ck2e1bananare" + + "publicasertairaumalborkarasjohkamikoaniikappuboliviajessheimemor" + + "ialaziobserverevistaples3-external-1filminamifuranofinalfinancef" + + "ineartsavonarutomobellevuelosangelesjabbottransurlfinlandynufcfa" + + "nfinnoyfirebaseappatriafirenzefirestonefirmdalegoldpoint2thisami" + + "tsukefishingolffansaxofitjarvodkafjordynv6fitnessettlementrapani" + + "izafjalerflesberguovdageaidnunusualpersonflickragerogerschoenbru" + + "nnflightschokokekschokoladenflirfloginlinefloraflorencefloridats" + + "unanjoburgushikamifuranorth-kazakhstanfloripaderbornfloristanoha" + + "takaharunzenflorokunohealthcareerscholarshipschoolschulezajskats" + + "ushikabeeldengeluidynvpnplus-4flowerschulserverfltravelchannelfl" + + "ynnhosting-clusterfndyroyrvikinguitarsaskatchewanfor-ourfor-some" + + "dizinhistorischeschwarzgwangjuniperfor-theaterforexrothachirogat" + + "akanezawaforgotdnschweizforli-cesena-forlicesenaforlillehammerfe" + + "ste-ipaviancarrdforsaleikangerforsandasuologoipfizerfortalfortmi" + + "ssoulancasterfortworthadanorthwesternmutualfosnesciencecentersci" + + "encehistoryfotaruis-a-cubicle-slavellinodeobjectscientistordalfo" + + "xfordebianfozorafredrikstadtvscjohnsonfreeddnsgeekgalaxyfreedesk" + + "topocznore-og-uvdalfreemasonryfreesitextileirfjordfreetlscotland" + + "freiburgwiddleitungsenfreseniuscountryestateofdelawareggio-calab" + + "riafribourgxn--1ctwolominamatarnobrzegyptianfriuli-v-giuliafriul" + + "i-ve-giuliafriuli-vegiuliafriuli-venezia-giuliafriuli-veneziagiu" + + "liafriuli-vgiuliafriuliv-giuliafriulive-giuliafriulivegiuliafriu" + + "livenezia-giuliafriuliveneziagiuliafriulivgiuliafrlfroganscrappe" + + "r-sitefrognfrolandfrom-akrehamnfrom-alfrom-arfrom-azfrom-capetow" + + "nnews-stagingfrom-coffeedbackplaneapplinzis-a-democratravelersin" + + "surancefrom-ctrdfrom-dchonanbulsan-suedtirolowiczest-le-patronis" + + "hitosashimizunaminamibosogndalpusercontentoyotapartsandnessjoeni" + + "shiwakinvestmentsandoyfrom-dedyn-berlincolnfrom-flanderscrapping" + + "from-gaulardalfrom-hichisochildrensgardenfrom-iafrom-idfrom-ilfr" + + "om-in-brbanzaicloudcontrolledekagaminombresciaustraliamusementdl" + + "lpages3-ap-south-1kappchizip6116-b-dataiji234lima-cityeatselinog" + + "radult3l3p0rtatamotors3-ap-northeast-1337from-kscrysechoseiroumu" + + "enchenissandiegofrom-kyowariasahikawafrom-lanciafrom-mamurogawaf" + + "rom-mdfrom-meeresistancefrom-mifunefrom-mnfrom-modalenfrom-mserv" + + "eirchoshibuyachiyodapliernewspaperfrom-mtnfrom-nctulangevagrigen" + + "tomologyeonggiehtavuoatnagahamaroyerfrom-ndfrom-nefrom-nh-serveb" + + "logsiteleafamilycompanyanagawafflecellclaimserveminecraftrentin-" + + "sud-tirolfrom-njaworznoticiasnesoddenmarkhangelskjakdnepropetrov" + + "skiervaapsteiermarkatsuyamarugame-hostrowiechoyodobashichikashuk" + + "ujitawarafrom-nminamiiserniafrom-nvalledaostargetmyiphostrodawar" + + "afrom-nyfrom-ohkurafrom-oketogurafrom-orfrom-padovaksdalfrom-pra" + + "tohmandalfrom-ris-a-designerfrom-schmidtre-gauldalfrom-sdfrom-tn" + + "from-txn--1lqs03nfrom-utsiracusaikisarazurecontainerdpolicefrom-" + + "val-daostavalleyfrom-vtrentin-sudtirolfrom-wafrom-wielunnerfrom-" + + "wvallee-aosteroyfrom-wyfrosinonefrostalowa-wolawafroyahikobierzy" + + "cefstcgroupgfoggiafujiiderafujikawaguchikonefujiminokamoenairlin" + + "edre-eikerfujinomiyadattowebcampinashikiminohostre-totendofinter" + + "net-dnsaliasiafujiokayamangonohejis-a-doctorayfujisatoshonairpor" + + "tland-4-salernoboribetsuckservemp3fujisawafujishiroishidakabirat" + + "oridefenseljordfujitsurugashimangyshlakasamatsudovre-eikerfujixe" + + "roxn--1lqs71dfujiyoshidavvenjargap-northeast-3fukayabeatservep2p" + + "harmacienservepicservequakefukuchiyamadavvesiidappnodebalancerti" + + "ficationfukudominichristiansburgrondarfukuis-a-financialadvisor-" + + "aurdalfukumitsubishigakishiwadazaifudaigojomedio-campidano-medio" + + "campidanomediofukuokazakisofukushimaniwakuratefukuroishikarikatu" + + "rindalfukusakisosakitagawafukuyamagatakahatakaishimoichinosekiga" + + "harafunabashiriuchinadafunagatakamatsukawafunahashikamiamakusats" + + "umasendaisennangooglecodespotrentin-sued-tirolfundaciofuoiskujuk" + + "uriyamannorfolkebibleirvikaufenfuosskoczowilliamhillfurnitureggi" + + "o-emilia-romagnakatombetsumitakagiizefurubirafurudonostiaafuruka" + + "wairtelebitbridgestonekobayashikshacknetcimbarcelonagawalmartatt" + + "oolforgehimejiitatebayashijonawatempresashibetsukuiiyamanouchiku" + + "hokuryugasakitaurayasudaustrheimatunduhrennesoyokosukanumazuryok" + + "oteastcoastaldefenceatonsbergjerdrumemergencyachts3-ca-central-1" + + "fusodegaurafussaintlouis-a-anarchistoireggiocalabriafutabayamagu" + + "chinomigawafutboldlygoingnowhere-for-morenakatsugawafuttsurugimp" + + "eriafuturecmservesarcasmatartanddesignfuturehostingfuturemailing" + + "fvgfylkesbiblackbaudcdn77-securebungoonord-odalfyresdalhangoutsy" + + "stemscloudhannanmokuizumodenaklodzkochikushinonsenergyhannosegaw" + + "ahanyuzenhapmircloudharstadharvestcelebrationhasamarburghasamina" + + "mi-alpsharis-a-hunterhashbanghasudahasura-appharmacysharphdfcban" + + "kazoologyhasvikazunow-dnshawaiijimaritimoduminamimakis-a-knightp" + + "ointtohobby-sitehatogayaitakaokalmykiahatoyamazakitakamiizumisan" + + "ofidelityhatsukaichikaiseiheijis-a-landscaperugiahattfjelldalhay" + + "ashimamotobungotakadagestangeorgeorgiahazuminobusells-for-usrcfa" + + "stlylbamblebesbyglandroverhalla-speziaustinnavigationavoizumizak" + + "ibigawajudaicable-modemocraciabruzzoologicalvinklein-addrammenuo" + + "rochesterimo-i-ranaamesjevuemielno-ipifonyaaarborteaches-yogasaw" + + "aracingdyniaetnabudapest-a-la-masion-riopretobamaceratabuseating" + + "-organic66helsinkitakatakarazukaluganskygearapphiladelphiaareadm" + + "yblogspotrentino-a-adigehembygdsforbundhemneshellaspeziahemsedal" + + "hepforgeherokussldheroyhgtvallee-d-aosteigenhidorahigashiagatsum" + + "agoianiahigashichichibunkyonanaoshimageandsoundandvisionthewifia" + + "tmallorcadaqueshimokawahigashihiroshimanehigashiizumozakitakyush" + + "uaiahigashikagawahigashikagurasoedahigashikawakitaaikitamihamada" + + "higashikurumeetrentino-aadigehigashimatsushimarcheapigeelvinckdd" + + "iethnologyhigashimatsuyamakitaakitadaitoigawahigashimurayamamoto" + + "rcycleshimokitayamahigashinarusells-itrentino-alto-adigehigashin" + + "ehigashiomihachimanagementrentino-altoadigehigashiosakasayamanak" + + "akogawahigashishirakawamatakasagoppdalhigashisumiyoshikawaminami" + + "aikitamotosumy-gatewayhigashitsunoshiroomurahigashiurausukitanak" + + "agusukumodernhigashiyamatokoriyamanashiibahccavuotnagareyamainte" + + "nancehigashiyodogawahigashiyoshinogaris-a-lawyerhiraizumisatohno" + + "shoooshikamaishimofusartshimonitayanagithubusercontentrentino-s-" + + "tirolhirakatashinagawahiranairtrafficplexus-1hirarahiratsukagawa" + + "hirayaizuwakamatsubushikusakadogawahistorichouseshimonosekikawah" + + "itachiomiyagildeskaliszhitachiotagotembaixadahitraeumtgeradelmen" + + "horstalbanshimosuwalkis-a-liberalhjartdalhjelmelandholeckodairah" + + "olidayhomeiphilatelyhomelinkitoolsztynsettlershimotsukehomelinux" + + "n--1qqw23ahomeofficehomesecuritymacaparecidahomesecuritypchristm" + + "aseratiresandvikcoromantovalle-d-aostatic-accessanfranciscofreak" + + "unemurorangehirnrtoyotomiyazakinzais-a-candidatehomesenseeringho" + + "meunixn--2m4a15ehondahongotpantheonsitehonjyoitakasakitashiobara" + + "hornindalhorsellsyourhomegoodshimotsumahorteneis-a-libertarianho" + + "spitalhoteleshinichinanhotmailhoyangerhoylandetroitskypehumaniti" + + "eshinjournalismailillesandefjordhurdalhurumajis-a-linux-useranis" + + "hiaritabashikaoirminamiminowahyllestadhyogoris-a-llamarriottrent" + + "ino-stirolhyugawarahyundaiwafuneis-very-badajozis-very-evillagei" + + "s-very-goodyearis-very-niceis-very-sweetpepperis-with-thebandois" + + "leofmanaustdaljevnakershuscultureggioemiliaromagnamsskoganeis-a-" + + "nascarfanjewelryjewishartgalleryjfkharkivalleedaostejgorajlljls-" + + "sto1jmphotographysiojnjcphonefosshintomikasaharajoyentrentino-su" + + "edtiroljoyokaichibajddarchitecturealtorlandjpnjprshiojirishirifu" + + "jiedajurkosherbrookegawakoshimizumakizunokunimimatakayamarylandk" + + "oshunantankhersonkosugekotohiradomainsurehabmerkotourakouhokutam" + + "akis-a-patsfankounosupplieshirakokaminokawanishiaizubangekouyama" + + "shikekouzushimashikis-a-personaltrainerkozagawakozakis-a-photogr" + + "apherokuapphilipsyno-dshinjukumanowtvalleeaosteinkjerusalembroid" + + "erykozowindmillkpnkppspdnshiranukamitsuekrasnikahokutokashikis-a" + + "-playershifteditchyouriphoenixn--2scrj9chromedicaltanissettaishi" + + "nomakinkobeardubaiduckdnsangokrasnodarkredstonekristiansandcatsh" + + "iraois-a-republicancerresearchaeologicaliforniakristiansundkrods" + + "heradkrokstadelvaldaostarostwodzislawindowskrakowinnershiraokamo" + + "gawakryminamioguni5kumatorinokumejimasoykumenantokigawakunisakis" + + "-a-rockstarachowicekunitachiarailwaykunitomigusukumamotoyamashik" + + "okuchuokunneppubtlshiratakahagitlaborkunstsammlungkunstunddesign" + + "kuokgroupilotshishikuis-a-socialistdlibestadkureisenkurgankurobe" + + "laudibleasingleshisognekurogiminamiashigarakuroisoftwarezzokurom" + + "atsunais-a-soxfankurotakikawasakis-a-studentalkushirogawakustana" + + "is-a-teacherkassyncloudkusupplykutchanelkutnokuzumakis-a-techiet" + + "is-a-musiciankvafjordkvalsundkvamlidlugolekadenagaivuotnagaokaky" + + "otambabyenebakkeshibechambagriculturennebudejjuedischesapeakebay" + + "ernukvanangenkvinesdalkvinnheradkviteseidatingkvitsoykwpspectrum" + + "inamisanrikubetsurfastvps-serveronakasatsunairguardiannakadomari" + + "nebraskauniversitychyattorneyagawakembuchikumagayagawakkanaibets" + + "ubamericanfamilydsclouderackmazerbaijan-mayen-rootaribeiraogashi" + + "madachicagoboatsassaris-a-conservativegarsheis-a-cpadualstackher" + + "o-networkinggroupassenger-associationkzmissileluxembourgmisugito" + + "kuyamatsumotofukemitourismolanxesshitaramamitoyoakemiuramiyazure" + + "websiteshikagamiishibukawamiyotamanomjondalenmlbfanmontrealestat" + + "efarmequipmentrentinoa-adigemonza-brianzapposhizukuishimogosenmo" + + "nza-e-della-brianzaptokyotangotsukitahatakamoriokakegawamonzabri" + + "anzaramonzaebrianzamonzaedellabrianzamoonscaleforcemordoviamoriy" + + "amatsunomoriyoshiminamiawajikis-an-actormormonstermoroyamatsusak" + + "ahoginankokubunjis-an-actresshinshinotsurgerymortgagemoscowioshi" + + "zuokanagawamoseushistorymosjoenmoskeneshoppingmosshopwarendalenu" + + "gmosvikhmelnytskyivaomoteginowaniihamatamakawajimansionshoujis-a" + + "n-anarchistoricalsocietymoviemovimientolgamozilla-iotrentinoaadi" + + "gemtranbymuenstermuginozawaonsenmuikamisatokaizukamikitayamatsur" + + "is-an-artistgorymukoebenhavnmulhouseoullensvanguardmunakatanemun" + + "cienciamuosattemupimientakkoelnmurmanskhplaystation-cloudmurotor" + + "craftrentinoalto-adigemusashimurayamatsushigemusashinoharamuseet" + + "rentinoaltoadigemuseumverenigingmusicargodaddyn-vpndnshowamutsuz" + + "awamy-vigorgemy-wanggouvichungnamdalseidfjordyndns-mailubindalub" + + "lindesnesanjotoyotsukaidomyactivedirectorymyasustor-elvdalmycdn7" + + "7-sslattuminamitanemydattolocalhistorymyddnskingmydissentrentino" + + "s-tirolmydobisshikis-an-engineeringmydroboehringerikemydshowtime" + + "lhusdecorativeartshriramsterdamnserverbaniamyeffectrentinostirol" + + "myfastly-terrariuminamiuonumasudamyfirewallonieruchomoscienceand" + + "industrynmyforuminamiyamashirokawanabelembetsukubankhmelnitskiya" + + "marumorimachidamyfritzmyftpaccesshwitdklabudhabikinokawabarthads" + + "electrentin-suedtirolmyhome-servermyjinomykolaivaporcloudmymaile" + + "rmymediapchurcharternidyndns-office-on-the-webhareidsbergentingr" + + "ongausdalucaniamyokohamamatsudamypepinkmpspbarclays3-sa-east-1my" + + "petsienarviikamishihoronobeauxartsandcraftsigdalmyphotoshibalati" + + "nogiftsilknx-serversailleshioyandexcloudmypictetrentinosud-tirol" + + "mypsxn--32vp30haebaruericssongdalenviknakayamaoris-a-geekautokei" + + "notteroymysecuritycamerakermyshopblocksimple-urlmytis-a-bookkeep" + + "erspectakasugais-an-entertainermytuleaprendemasakikonaikawachina" + + "ganoharamcoachampionshiphoptobishimadridvagsoygardendoftheintern" + + "etlifyis-bytomaritimekeepingmyvncircustomer-ociprianiigataitogit" + + "suldaluccarbonia-iglesias-carboniaiglesiascarboniamywirepbodynam" + + "ic-dnsirdalplatformshangrilapyplatter-appioneerplatterpippugliap" + + "lazaplcube-serversicherungplumbingoplurinacionalpodhalevangerpod" + + "lasiellaktyubinskiptveterinaireadthedocscappgafannefrankfurtrent" + + "inosudtirolpodzonepohlpoivronpokerpokrovskomakiyosunndalpolitica" + + "rrierpolitiendapolkowicepoltavalle-aostathellewismillerpomorzesz" + + "owithgoogleapiszponpesaro-urbino-pesarourbinopesaromasvuotnaroyp" + + "onypordenonepornporsangerporsangugeporsgrunnanyokoshibahikariwan" + + "umatamayufuelveruminanopoznanpraxis-a-bruinsfanprdpreservationpr" + + "esidioprgmrprimelbourneprincipeprivatizehealthinsuranceprofesion" + + "alprogressivenneslaskerrylogisticslupskomatsushimarylhurstjordal" + + "shalsenpromombetsurgeonshalloffameiwamassa-carrara-massacarraram" + + "assabusinessebyklecznagasukepropertyprotectionprotonetrentinosue" + + "d-tirolprudentialpruszkowithyoutuberspacekitagatargivestbytemark" + + "omforbarefootballooningjerstadotsuruokakamigaharauthordalandds3-" + + "eu-central-1prvcyberlevagangaviikanonjis-certifieducatorahimeshi" + + "mamateramobaraprzeworskogptplusgardenpulawypupittsburghofficialp" + + "vhagakhanamigawapvtrentinosuedtirolpwcistrondheimmobilienissayok" + + "kaichiropractichitachinakagawassamukawatarightathomeftparocherni" + + "governmentksatxn--12c1fe0bradescorporationrenderpzqhagebostadqld" + + "qponiatowadaqslingqualifioappiwatequickconnectrentinsud-tirolqui" + + "cksytestingquipelementslzqvcitadeliveryggeesusonosuzakanazawasuz" + + "ukaneyamazoesuzukis-into-animegurownprovidersvalbardunloppacific" + + "ivilaviationissedalucernesveiosvelvikomorotsukaminoyamaxunjargas" + + "vizzerasvn-reposologneswidnicasacamdvrcampinagrandebuilderschles" + + "ischesolundbeckommunalforbundswidnikkokonoeswiebodzin-butterswif" + + "tcoverswinoujscienceandhistoryswissmarterthanyousynology-disksta" + + "tionsynology-dsolutionsnoasakakinokiaturystykanmakiwientuscanytu" + + "shuissier-justicetuvalle-daostaticsootuxfamilytwmailvestnesopotr" + + "entinsudtirolvestre-slidreviewsaitoshimayfirstockholmestrandvest" + + "re-totennishiawakuravestvagoyvevelstadvibo-valentiavibovalentiav" + + "ideovillasor-odalvinnicasadelamonedancevinnytsiavipsinaappixolin" + + "ovirginiavirtual-userveftpizzavirtualservervirtualuservegame-ser" + + "vervirtueeldomein-vigorlicevirtuelvisakegawaviterboknowsitallviv" + + "olkenkundenvixn--3bst00miniservervlaanderenvladikavkazimierz-dol" + + "nyvladimirvlogintoyonezawavminnesotaketaketomisatokorozawavologd" + + "anskongsbergvolvolkswagentsor-varangervolyngdalvoorloperaunitero" + + "is-into-carshinshirovossevangenvotevotingvotoyonowmflabsorfoldwn" + + "extdirectroandinosaureplantationworldworse-thandawowiwatsukiyono" + + "tairestaurantritonwpdevcloudwritesthisblogsytewroclawloclawekong" + + "svingerwtcminterepaircraftingvollombardiamondshisuifuettertdasne" + + "tzwtfauskedsmokorsetagayaseralingenoamishirasatogokasells-for-le" + + "ssaudawuozuwzmiuwajimaxn--42c2d9axn--45br5cylxn--45brj9civilizat" + + "ionxn--45q11civilwarmiastagets-itoyouraxn--4gbriminingxn--4it168" + + "dxn--4it797konskowolayangroupictureshirahamatonbetsurnadalxn--4p" + + "vxs4allxn--54b7fta0cclanbibaidarmeniaxn--55qw42gxn--55qx5dxn--5j" + + "s045dxn--5rtp49cldmailovecollegefantasyleaguernseyxn--5rtq34kons" + + "ulatrobeepilepsykkylvenetodayxn--5su34j936bgsgxn--5tzm5gxn--6btw" + + "5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264clic20001wwwhosw" + + "hokksundyndns-picsannohelplfinancialukowiiheyakagexn--80adxhksor" + + "ocabalestrandabergamo-siemensncfdxn--80ao21axn--80aqecdr1axn--80" + + "asehdbarreauction-webhostingjesdalillyolasitemrxn--80aswgxn--80a" + + "ugustowmcloudxn--8ltr62konyvelolipopiemontexn--8pvr4uxn--8y0a063" + + "axn--90a3academiamicaarpkomaganexn--90aeroportalabamagasakishima" + + "baraogakibichuoxn--90aishobarakawagoexn--90azhytomyravendbarrel-" + + "of-knowledgeapplicationcloudappspotagerxn--9dbhblg6digitalxn--9d" + + "bq2axn--9et52uxn--9krt00axn--andy-iraxn--aroport-byaotsurreyxn--" + + "asky-iraxn--aurskog-hland-jnbarrell-of-knowledgestackarasjokaras" + + "uyamarshallstatebankarateu-1xn--avery-yuasakuhokkaidownloadxn--b" + + "-5gaxn--b4w605ferdxn--balsan-sdtirol-nsbsorreisahayakawakamiichi" + + "kawamisatottoris-foundationxn--bck1b9a5dre4clickashiwazakiyosemi" + + "texn--bdddj-mrabdxn--bearalvhki-y4axn--berlevg-jxaxn--bhcavuotna" + + "-s4axn--bhccavuotna-k7axn--bidr-5nachikatsuuraxn--bievt-0qa2xn--" + + "bjarky-fyasakaiminatoyookaniepcexn--bjddar-ptarumizusawaxn--blt-" + + "elabourxn--bmlo-graingerxn--bod-2nativeamericanantiquesortlandxn" + + "--bozen-sdtirol-2obanazawaxn--brnny-wuacademy-firewall-gatewayxn" + + "--brnnysund-m8accident-investigation-aptibleadpagest-mon-blogueu" + + "rovision-k3sorumincomcastresindevicenzaporizhzhiaxn--brum-voagat" + + "rogstadxn--btsfjord-9zaxn--bulsan-sdtirol-nsbarsycenterprisesaki" + + "kugawaltervistaikimobetsuitainaioirasebastopologyeongnamegawakay" + + "amagazineat-urlimanowarudautomotiveconomiasakuchinotsuchiurakawa" + + "lesundeportevadsobetsumidatlanticaseihicampobassociatest-iservec" + + "ounterstrikebinagisoccertmgrazimutheworkpccwebredirectmembers3-e" + + "u-west-1xn--c1avgxn--c2br7gxn--c3s14misakis-a-therapistoiaxn--cc" + + "k2b3barsyonlinewhampshirealtysnes3-us-gov-west-1xn--cckwcxetdxn-" + + "-cesena-forl-mcbremangerxn--cesenaforl-i8axn--cg4bkis-into-carto" + + "onshintokushimaxn--ciqpnxn--clchc0ea0b2g2a9gcdxn--comunicaes-v6a" + + "2oxn--correios-e-telecomunicaes-ghc29axn--czr694bashkiriautoscan" + + "adaeguambulanceobihirosakikamijimatsuzakibmdevelopmentatsunobira" + + "ukraanghkeymachineustargardd-dnsiskinkyotobetsulikes-piedmontice" + + "llodingenatuurwetenschappenaumburggfarmerseine164-balsfjorddnsli" + + "velanddnss3-ap-southeast-1xn--czrs0tromsakataobaomoriguchiharahk" + + "keravjuegoshikijobservableusercontentrentinsuedtirolxn--czru2dxn" + + "--czrw28basicservercelliguriaveroykenglandgcahcesuoloans3-eu-wes" + + "t-2xn--d1acj3basilicataniavocatanzarowebspacebinordreisa-hockeyn" + + "utazuerichardlikescandyn53utilitiesquare7xn--d1alfaromeoxn--d1at" + + "romsojamisonxn--d5qv7z876clinichocolatelevisionishiokoppegardynd" + + "ns-ipartinuyamashinatsukigatakashimarnardalouvreitoyosatoyokawax" + + "n--davvenjrga-y4axn--djrs72d6uyxn--djty4kooris-a-nursembokukitch" + + "enxn--dnna-grajewolterskluwerxn--drbak-wuaxn--dyry-iraxn--e1a4cl" + + "iniquenoharaxn--eckvdtc9dxn--efvn9soundcastronomy-routerxn--efvy" + + "88haibarakitahiroshimapartmentservicesevastopolexn--ehqz56nxn--e" + + "lqq16hair-surveillancexn--eveni-0qa01gaxn--f6qx53axn--fct429kope" + + "rvikharkovanylvenicexn--fhbeiarnxn--finny-yuaxn--fiq228c5hsouthc" + + "arolinatalxn--fiq64basketballfinanzgoravoues3-eu-west-3xn--fiqs8" + + "southwestfalenxn--fiqz9sowaxn--fjord-lraxn--fjq720axn--fl-ziaxn-" + + "-flor-jraxn--flw351exn--forl-cesena-fcbsspeedpartnersokananiimih" + + "oboleslawiecitichitosetogakushimotoganewportlligatmparsamsclubar" + + "towhalingriwataraidyndns-homednsamsungroks-thisayamanobeokakudam" + + "atsuexn--forlcesena-c8axn--fpcrj9c3dxn--frde-grandrapidspjelkavi" + + "komonowruzhgorodeoxn--frna-woaraisaijosoyrorospreadbettingxn--fr" + + "ya-hraxn--fzc2c9e2clintonoshoesanokasserverrankoshigayameinforum" + + "zxn--fzys8d69uvgmailxn--g2xx48clothingdustdataiwanairforcebetsui" + + "kidsmynasushiobaragusabaejrietisalatinabenonicbcn-north-1xn--gck" + + "r3f0fbsbxn--12co0c3b4evalleaostavangerxn--gecrj9cn-northwest-1xn" + + "--ggaviika-8ya47hakatanortonxn--gildeskl-g0axn--givuotna-8yasugi" + + "vingxn--gjvik-wuaxn--gk3at1exn--gls-elacaixaxn--gmq050is-into-ga" + + "messinazawaxn--gmqw5axn--h-2failxn--h1aeghakodatexn--h2breg3even" + + "espydebergxn--h2brj9c8cngrossetouchihayaakasakawaharaxn--h3cuzk1" + + "discountyxn--hbmer-xqaxn--hcesuolo-7ya35batochiokinoshimakeupowi" + + "at-band-campaniaxaurskog-holandingjemnes3-ap-southeast-2xn--hery" + + "-iraxn--hgebostad-g3axn--hkkinen-5waxn--hmmrfeasta-s4accident-pr" + + "evention-rancherkasydneyxn--hnefoss-q1axn--hobl-iraxn--holtlen-h" + + "xaxn--hpmir-xqaxn--hxt814exn--hyanger-q1axn--hylandet-54axn--i1b" + + "6b1a6a2exn--imr513nxn--indery-fyasuokanoyakumoldeloittenrikuzent" + + "akatajimidorissagamiharaxn--io0a7is-leetrentino-sud-tirolxn--j1a" + + "efbx-osauheradyndns1xn--j1amhakonexn--j6w193gxn--jlq480n2rgxn--j" + + "lq61u9w7batsfjordiscoveryombolzano-altoadigeologyomitanoceanogra" + + "phics3-us-west-1xn--jlster-byatomitamamuraxn--jrpeland-54axn--jv" + + "r189misasaguris-an-accountantshinkamigotoyohashimototalxn--k7yn9" + + "5exn--karmy-yuaxn--kbrq7oxn--kcrx77d1x4axn--kfjord-iuaxn--klbu-w" + + "oaxn--klt787dxn--kltp7dxn--kltx9axn--klty5xn--3ds443gxn--koluokt" + + "a-7ya57hakubahcavuotnagaraholtaleniwaizumiotsukumiyamazonawsmppl" + + "anetariuminamiizukamiokameokameyamatotakadaxn--kprw13dxn--kpry57" + + "dxn--kpu716fbxosavannahgaxn--kput3is-lostrolekamakurazakiwakunig" + + "amiharustkannamilanotogawaxn--krager-gyatsukanraxn--kranghke-b0a" + + "xn--krdsherad-m8axn--krehamn-dxaxn--krjohka-hwab49jdfastpanelbla" + + "grarchaeologyeongbuk0emmafann-arboretumbriamallamaceiobbcg12038x" + + "n--ksnes-uuaxn--kvfjord-nxaxn--kvitsy-fyatsushiroxn--kvnangen-k0" + + "axn--l-1fairwindsrlxn--l1accentureklamborghinikolaeventsrvareser" + + "vehalflifestylexn--laheadju-7yawaraxn--langevg-jxaxn--lcvr32dxn-" + + "-ldingen-q1axn--leagaviika-52bauhausposts-and-telecommunications" + + "3-us-west-2xn--lesund-huaxn--lgbbat1ad8jelasticbeanstalkhakassia" + + "xn--lgrd-poacctrusteexn--lhppi-xqaxn--linds-pramericanartrvargga" + + "trentoyonakagyokutoyakolobrzegersundxn--lns-qlaquilanstorfjordxn" + + "--loabt-0qaxn--lrdal-sraxn--lrenskog-54axn--lt-liacnpyatigorskod" + + "jeffersonxn--lten-granexn--lury-iraxn--m3ch0j3axn--mely-iraxn--m" + + "erker-kuaxn--mgb2ddestorjdevcloudnshinyoshitomiokamitondabayashi" + + "ogamagoriziaxn--mgb9awbfedorapeoplegnicapebretonamicrosoftbankas" + + "uyanaizulminamiechizenxn--mgba3a3ejtrycloudflareportrevisohughes" + + "omaxn--mgba3a4f16axn--mgba3a4franamizuholdingstpetersburgxn--mgb" + + "a7c0bbn0axn--mgbaakc7dvfedoraprojectransportexn--mgbaam7a8hakuis" + + "-a-greenxn--mgbab2bdxn--mgbah1a3hjkrdxn--mgbai9a5eva00beneventoe" + + "idskoguchikuzenayorovigovtaxihuanflfanfshostrowwlkpmgjovikaratsu" + + "ginamikatagamilitaryonagoyaxn--mgbai9azgqp6jelenia-goraxn--mgbay" + + "h7gpaleoxn--mgbbh1a71exn--mgbc0a9azcgxn--mgbca7dzdoxn--mgberp4a5" + + "d4a87gxn--mgberp4a5d4arxn--mgbgu82axn--mgbi4ecexposedxn--mgbpl2f" + + "hskydivingxn--mgbqly7c0a67fbcnsantabarbaraxn--mgbqly7cvafranzisk" + + "anerimaringatlantakahashimamakiryuohdattorelayxn--mgbt3dhdxn--mg" + + "btf8flatangerxn--mgbtx2bentleyonagunicommbankarelianceu-2xn--mgb" + + "x4cd0abbvieeexn--mix082feiraquarelleaseeklogesaves-the-whalessan" + + "dria-trani-barletta-andriatranibarlettaandriaxn--mix891fermochiz" + + "ukirovogradoyxn--mjndalen-64axn--mk0axin-dslgbtrysiljanxn--mk1bu" + + "44cntoystre-slidrettozawaxn--mkru45is-not-certifiedugit-pagespee" + + "dmobilizeroticanonoichinomiyakexn--mlatvuopmi-s4axn--mli-tlarvik" + + "oryokamikawanehonbetsurutaharaxn--mlselv-iuaxn--moreke-juaxn--mo" + + "ri-qsakuragawaxn--mosjen-eyawatahamaxn--mot-tlavagiskexn--mre-og" + + "-romsdal-qqbuserveexchangexn--msy-ula0hakusanagochijiwadell-ogli" + + "astraderxn--mtta-vrjjat-k7aflakstadaokagakicks-assnasaarlandxn--" + + "muost-0qaxn--mxtq1misawaxn--ngbc5azdxn--ngbe9e0axn--ngbrxn--3e0b" + + "707exn--nit225kosaigawaxn--nmesjevuemie-tcbalsan-sudtirollagdene" + + "snaaseinet-freakstreamswatch-and-clockerxn--nnx388axn--nodessaku" + + "rais-savedunetflixilxn--nqv7fs00emaxn--nry-yla5gxn--ntso0iqx3axn" + + "--ntsq17gxn--nttery-byaeservehttplantsjcbnpparibaselburgxn--nvuo" + + "tna-hwaxn--nyqy26axn--o1acheltenham-radio-openairbusantiquest-a-" + + "la-maisondre-landroidxn--o3cw4haldenxn--o3cyx2axn--od0algxn--od0" + + "aq3beppublishproxyzgorzeleccogladefinimakanegasakiraxn--ogbpf8fl" + + "ekkefjordxn--oppegrd-ixaxn--ostery-fyaxn--osyro-wuaxn--otu796dxn" + + "--p1acferraraxn--p1ais-slickfhappoutwentexn--pbt977collectionxn-" + + "-pgbs0dhlxn--porsgu-sta26ferrarivnexn--pssu33lxn--pssy2uxn--q9jy" + + "b4colognewyorkshirecifedexeterxn--qcka1pmckinseyxn--qqqt11miscon" + + "fusedxn--qxa6axn--qxamuneuestudioxn--rady-iraxn--rdal-poaxn--rde" + + "-ulavangenxn--rdy-0nabaris-uberleetrentino-sudtirolxn--rennesy-v" + + "1axn--rhkkervju-01aferrerotikagoshimalvikaszubyxn--rholt-mragowo" + + "odsidemonmouthalsaitamatsukuris-a-guruslivinghistoryxn--rhqv96gx" + + "n--rht27zxn--rht3dxn--rht61exn--risa-5naturalhistorymuseumcenter" + + "xn--risr-iraxn--rland-uuaxn--rlingen-mxaxn--rmskog-byaxn--rny31h" + + "ammarfeastafricapitalonewmexicodyn-o-saurlandesevenassisicilyxn-" + + "-rovu88beskidyn-ip24xn--rros-granvindafjordxn--rskog-uuaxn--rst-" + + "0naturalsciencesnaturellestudynamisches-dnsokndalxn--rsta-franca" + + "iseharaxn--rvc1e0am3exn--ryken-vuaxn--ryrvik-byaxn--s-1faithamur" + + "akamigoris-a-hard-workersewinbarclaycards3-fips-us-gov-west-1xn-" + + "-s9brj9colonialwilliamsburgroundhandlingroznyxn--sandnessjen-ogb" + + "estbuyshouses3-website-ap-northeast-1xn--sandy-yuaxn--sdtirol-n2" + + "axn--seral-lraxn--ses554gxn--sgne-graphoxn--3hcrj9civilisationis" + + "shinguccircleverappsannaniyodogawaxn--skierv-utazastuff-4-salexn" + + "--skjervy-v1axn--skjk-soaxn--sknit-yqaxn--sknland-fxaxn--slat-5n" + + "aturbruksgymnxn--slt-elabcieszynxn--smla-hraxn--smna-gratangentl" + + "entapisa-geekosakaerodromegallupinbargainstantcloudfunctionswede" + + "nvironmentalconservationfabricafederationionjukudoyamaizuruhrhcl" + + "oudiscourses3-us-east-2xn--snase-nraxn--sndre-land-0cbetainaboxf" + + "usejnymemsettsupportcp4xn--snes-poaxn--snsa-roaxn--sr-aurdal-l8a" + + "xn--sr-fron-q1axn--sr-odal-q1axn--sr-varanger-ggbhzcasinordkappa" + + "lmasfjordenhktjeldsundishakotanhlfanhs3-website-ap-southeast-1xn" + + "--srfold-byaxn--srreisa-q1axn--srum-gratis-a-bulls-fanxn--stfold" + + "-9xaxn--stjrdal-s1axn--stjrdalshalsen-sqbieidsvollimitediskussio" + + "nsbereichaseljeepsondriodejaneirockartuzyoriikariyaltakatorin-th" + + "e-bandain-vpncateringebuildinglassassinationalheritageu-3xn--str" + + "e-toten-zcbielawashingtondclkarlsoyoshiokanzakiyokawaraxn--t60b5" + + "6axn--tckweatherchannelxn--tiq49xqyjeonnamerikawauexn--tjme-hrax" + + "n--tn0agrinetbankoseis-a-painteractivegaskvollxn--tnsberg-q1axn-" + + "-tor131oxn--trany-yuaxn--trentin-sd-tirol-rzbiellaakesvuemielecc" + + "eu-4xn--trentin-sdtirol-7vbrplsbxn--3oq18vl8pn36axn--trentino-sd" + + "-tirol-c3bieszczadygeyachimataipeigersundisrechtrainingleezevje-" + + "og-hornnes3-website-ap-southeast-2xn--trentino-sdtirol-szbievath" + + "letajimabaridagawalbrzycharitydalcesurancechirealmpmnikonanporov" + + "noceanographiquextraspace-to-rentalstomakomaibaraxn--trentinosd-" + + "tirol-rzbifukagawashtenawdev-myqnapcloudeitysfjordivtasvuodnakam" + + "agayahabaghdadivttasvuotnakamuratakahamalselvendrellimoliseminex" + + "n--trentinosdtirol-7vbigv-infoodnetworkangerxn--trentinsd-tirol-" + + "6vbihorologyukincheoninohekinannestadiyukuhashimojindianapolis-a" + + "-bloggerxn--trentinsdtirol-nsbikedaejeonbukcoalvdalaheadjudygarl" + + "andnpalmspringsakerxn--trgstad-r1axn--trna-woaxn--troms-zuaxn--t" + + "ysvr-vraxn--uc0atvaroyxn--uc0ay4axn--uist22handsonyoursidellogli" + + "astradingxn--uisz3gxn--unjrga-rtashkentunesomnarvikommunexn--unu" + + "p4yxn--uuwu58axn--vads-jraxn--valle-aoste-ebbtunkomvuxn--30rr7yx" + + "n--valle-d-aoste-ehbodollstufftoread-booksnesolarssonxn--valleao" + + "ste-e7axn--valledaoste-ebbvacationstuttgartrentinsued-tirolxn--v" + + "ard-jraxn--vegrshei-c0axn--vermgensberater-ctbilbaokinawashirosa" + + "tochigiessensiositelemarkarmoyurihonjournalistjohninomiyakonojor" + + "pelandrangedalinkyard-cloudyclusterxn--vermgensberatung-pwbillus" + + "trationredumbrellahppiacenzachpomorskienirasakindianmarketinglit" + + "chattanooganordlandray-dnsupdaternopilawaweddingliwicexn--vestvg" + + "y-ixa6oxn--vg-yiabkhaziaxn--vgan-qoaxn--vgsy-qoa0jetztrentino-su" + + "ed-tirolxn--vgu402coloradoplateaudioxn--vhquvestfoldxn--vler-qoa" + + "xn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla5gxn--vuq861biocpanama" + + "tta-varjjatjmaxxxboxenapponazure-mobilexn--w4r85el8fhu5dnraxn--w" + + "4rs40lxn--wcvs22dxn--wgbh1columbusheyxn--wgbl6axn--xhq521birdart" + + "centerprisecloudcontrolappleborkdalwaysdatabaseballangenkainanae" + + "robatickets3-website-eu-west-1xn--xkc2al3hye2axn--xkc2dl3a5ee0ha" + + "ngglidingxn--y9a3aquariumishimatsumaebashimodatexn--yer-znaturhi" + + "storischesusakis-gonexn--yfro4i67oxn--ygarden-p1axn--ygbi2ammxn-" + + "-3pxu8koninjambylxn--ystre-slidre-ujbirkenesoddtangenovaranzanqu" + + "anpachigasakihokumakogengerdalaskanittedallasalleangaviikaascoli" + + "picenodumetacentrumeteorappanasonicatholicaxiashorokanaiexn--zbx" + + "025dxn--zf0ao64axn--zf0avxlxn--zfr164birthplacexnbayxz" + +// nodes is the list of nodes. Each node is represented as a uint32, which +// encodes the node's children, wildcard bit and node type (as an index into +// the children array), ICANN bit and text. +// +// If the table was generated with the -comments flag, there is a //-comment +// after each node's data. In it is the nodes-array indexes of the children, +// formatted as (n0x1234-n0x1256), with * denoting the wildcard bit. The +// nodeType is printed as + for normal, ! for exception, and o for parent-only +// nodes that have children but don't match a domain label in their own right. +// An I denotes an ICANN domain. +// +// The layout within the uint32, from MSB to LSB, is: +// [ 0 bits] unused +// [10 bits] children index +// [ 1 bits] ICANN bit +// [15 bits] text index +// [ 6 bits] text length +var nodes = [...]uint32{ + 0x297a83, + 0x32a504, + 0x2eadc6, + 0x24c943, + 0x24c946, + 0x38b146, + 0x3b05c3, + 0x214bc4, + 0x201507, + 0x2eaa08, + 0x1a000c2, + 0x1f36987, + 0x376649, + 0x36c4ca, + 0x36c4cb, + 0x201203, + 0x233985, + 0x2201602, + 0x2d2044, + 0x2eaf43, + 0x269045, + 0x2601742, + 0x343083, + 0x2a135c4, + 0x2982c5, + 0x2e0de42, + 0x26e24e, + 0x250b83, + 0x3a6286, + 0x3203082, + 0x306087, + 0x2372c6, + 0x3606bc2, + 0x27f943, + 0x27f944, + 0x399b86, + 0x35bc88, + 0x286046, + 0x26fc84, + 0x3a00ac2, + 0x34abc9, + 0x2236c7, + 0x202446, + 0x353689, + 0x32f208, + 0x2478c4, + 0x23f2c6, + 0x3c3846, + 0x3e041c2, + 0x36fcc6, + 0x242f4f, + 0x2d108e, + 0x219a44, + 0x218b45, + 0x32a405, + 0x2e7589, + 0x23d709, + 0x39a387, + 0x3ddf06, + 0x267243, + 0x42037c2, + 0x21adc3, + 0x35054a, + 0x460f283, + 0x3d95c5, + 0x29d282, + 0x38b6c9, + 0x4e01182, + 0x201c84, + 0x2f3146, + 0x28a745, + 0x36d1c4, + 0x560fbc4, + 0x220dc3, + 0x232d04, + 0x5a02d02, + 0x235784, + 0x5e79284, + 0x33cb4a, + 0x6200882, + 0x3c1f47, + 0x2d0548, + 0x76031c2, + 0x328287, + 0x2c9044, + 0x2c9047, + 0x3d57c5, + 0x378847, + 0x303c06, + 0x2f0e44, + 0x342e05, + 0x257187, + 0x8e01482, + 0x36fe43, + 0x9226782, + 0x3633c3, + 0x9606b42, + 0x274985, + 0x9a00202, + 0x2cd104, + 0x2c23c5, + 0x219987, + 0x249e0e, + 0x2b6e44, + 0x290f44, + 0x210603, + 0x286ac9, + 0x3aa74b, + 0x2edac8, + 0x303148, + 0x3b1888, + 0x3d9ac8, + 0x3534ca, + 0x378747, + 0x2cdf46, + 0x9e47402, + 0x374d83, + 0x3ccac3, + 0x3ce604, + 0x374dc3, + 0x35cb83, + 0x1732182, + 0xa2016c2, + 0x27cd05, + 0x224686, + 0x233744, + 0x38a5c7, + 0x2355c6, + 0x2c8984, + 0x3abfc7, + 0x215dc3, + 0xa6d5bc2, + 0xaa20f82, + 0xae20d42, + 0x220d46, + 0xb200282, + 0x284405, + 0x3336c3, + 0x3c8744, + 0x2f7784, + 0x2f7785, + 0x3d6d83, + 0xb602703, + 0xba019c2, + 0x205fc5, + 0x205fcb, + 0x20ec0b, + 0x229904, + 0x206689, + 0x208244, + 0xbe09c42, + 0x20a483, + 0x20a703, + 0xc202e82, + 0x398a0a, + 0xc601542, + 0x2d22c5, + 0x2e6a0a, + 0x247584, + 0x20b103, + 0x20b7c4, + 0x20d6c3, + 0x20d6c4, + 0x20d6c7, + 0x20e245, + 0x2114c6, + 0x211846, + 0x2124c3, + 0x217688, + 0x208f03, + 0xca0cd42, + 0x308648, + 0x2862cb, + 0x21ffc8, + 0x2205c6, + 0x2213c7, + 0x227208, + 0xda07682, + 0xde1d482, + 0x298408, + 0x210c07, + 0x30dcc5, + 0x30dcc8, + 0xe301108, + 0x26c243, + 0x22a444, + 0x38b1c2, + 0xe62a882, + 0xea16182, + 0xf22c042, + 0x22c043, + 0xf6086c2, + 0x296303, + 0x3b2744, + 0x2086c3, + 0x247884, + 0x296a4b, + 0x215843, + 0x2f1486, + 0x278704, + 0x2c340e, + 0x38f345, + 0x261e48, + 0x3a6387, + 0x3a638a, + 0x22f983, + 0x2343c7, + 0x3aa905, + 0x22f984, + 0x2526c6, + 0x2526c7, + 0x31a204, + 0xfb0d704, + 0x24a144, + 0x33c806, + 0x22b844, + 0x3b5cc6, + 0x232443, + 0x3ba348, + 0x3df888, + 0x290f03, + 0x3989c3, + 0x340384, + 0x355943, + 0x10215702, + 0x1068d502, + 0x218043, + 0x2435c6, + 0x343343, + 0x30c504, + 0x10a3fec2, + 0x24cf43, + 0x327783, + 0x212c02, + 0x10e00d42, + 0x2cb886, + 0x234807, + 0x3c25c7, + 0x3b91c5, + 0x3d3004, + 0x29fbc5, + 0x2253c7, + 0x2ade49, + 0x2c19c6, + 0x2ec246, + 0x1120b682, + 0x2f4b48, + 0x3ae1c6, + 0x2aed85, + 0x30a6c7, + 0x3562c4, + 0x3562c5, + 0x11668c84, + 0x268c88, + 0x11a06082, + 0x11e00482, + 0x26e986, + 0x200488, + 0x331ac5, + 0x34b646, + 0x34ef88, + 0x35b788, + 0x12201805, + 0x126136c4, + 0x2136c7, + 0x12a07cc2, + 0x12e167c2, + 0x14201242, + 0x2f3245, + 0x14a83545, + 0x262486, + 0x323647, + 0x39f087, + 0x14e14a83, + 0x338487, + 0x38a948, + 0x2022cd09, + 0x26e407, + 0x22d447, + 0x22e548, + 0x22ed46, + 0x22f486, + 0x2300cc, + 0x23180a, + 0x231c07, + 0x23384b, + 0x234647, + 0x23464e, + 0x20635944, + 0x235b44, + 0x238b07, + 0x25c7c7, + 0x23d006, + 0x23d007, + 0x3b3147, + 0x2d2c43, + 0x20a2ba02, + 0x23e306, + 0x23e30a, + 0x23f44b, + 0x240987, + 0x241405, + 0x241e43, + 0x242246, + 0x242247, + 0x2f8983, + 0x20e00102, + 0x242bca, + 0x21377dc2, + 0x2173da82, + 0x21a3fd02, + 0x21e373c2, + 0x245385, + 0x245d44, + 0x22a05582, + 0x235805, + 0x23fa43, + 0x314885, + 0x2688c4, + 0x2afb04, + 0x2cea06, + 0x250f06, + 0x2061c3, + 0x3bb644, + 0x303ec3, + 0x23a02a42, + 0x213c44, + 0x213c46, + 0x221745, + 0x244d46, + 0x30a7c8, + 0x223dc4, + 0x367bc8, + 0x231e85, + 0x262b88, + 0x2caa06, + 0x217c07, + 0x273504, + 0x24e73506, + 0x252239c3, + 0x39e183, + 0x31d988, + 0x29ffc4, + 0x2572ccc7, + 0x25ee4846, + 0x2e4849, + 0x362008, + 0x36a408, + 0x3b6544, + 0x3c7903, + 0x22dd42, + 0x2624e782, + 0x2660fa82, + 0x3c9083, + 0x26a01642, + 0x2f8904, + 0x279986, + 0x21c103, + 0x2bc7c7, + 0x303743, + 0x32fcc8, + 0x20b885, + 0x25a683, + 0x2c2345, + 0x2c2484, + 0x30bcc6, + 0x20cac6, + 0x2198c6, + 0x2f39c4, + 0x234a03, + 0x26e0fe02, + 0x27233fc5, + 0x200843, + 0x27a07382, + 0x22d1c3, + 0x2676c5, + 0x27e32dc3, + 0x28632dc9, + 0x28a00942, + 0x29208902, + 0x28ce05, + 0x213f06, + 0x28ec06, + 0x2e6608, + 0x2e660b, + 0x339c8b, + 0x3b93c5, + 0x2d6149, + 0x1600b42, + 0x2f0548, + 0x206984, + 0x29a03c42, + 0x34a843, + 0x2a25c986, + 0x3c2888, + 0x2a6142c2, + 0x35c708, + 0x2aaaac82, + 0x337f8a, + 0x2aedb383, + 0x2b776c86, + 0x392488, + 0x214886, + 0x387b87, + 0x243147, + 0x3c33ca, + 0x247604, + 0x360704, + 0x376209, + 0x2bba9dc5, + 0x26e286, + 0x210e03, + 0x24e3c4, + 0x2be196c4, + 0x3458c7, + 0x2c241c87, + 0x294f84, + 0x39f545, + 0x262548, + 0x39e647, + 0x3a24c7, + 0x2c60dec2, + 0x29cf44, + 0x293048, + 0x246d84, + 0x24b904, + 0x24bcc5, + 0x24be07, + 0x2ca7ebc9, + 0x2232c4, + 0x24d789, + 0x24d9c8, + 0x24e144, + 0x24e147, + 0x2ce4e583, + 0x24ea87, + 0x2d20bb42, + 0x16b8842, + 0x24fa46, + 0x250087, + 0x250704, + 0x251d07, + 0x253787, + 0x253f83, + 0x22dec2, + 0x20d982, + 0x303243, + 0x3c6704, + 0x3c670b, + 0x2d703248, + 0x25a044, + 0x255b85, + 0x257407, + 0x2e92c5, + 0x33144a, + 0x259f83, + 0x2da05dc2, + 0x208e04, + 0x25c589, + 0x260c03, + 0x260cc7, + 0x240749, + 0x205dc8, + 0x22af03, + 0x27b3c7, + 0x27be89, + 0x225583, + 0x283b84, + 0x284d09, + 0x28b2c6, + 0x2f4103, + 0x2015c2, + 0x23c903, + 0x2b8647, + 0x23c905, + 0x3b1686, + 0x270744, + 0x35ff85, + 0x27c7c3, + 0x212706, + 0x292503, + 0x206882, + 0x248f84, + 0x2de299c2, + 0x2e2299c3, + 0x2e607082, + 0x248343, + 0x211cc4, + 0x2ece07, + 0x2946c6, + 0x262302, + 0x2ea5cd82, + 0x30a9c4, + 0x2f20d842, + 0x2f616902, + 0x2ef084, + 0x2ef085, + 0x302c85, + 0x35ef86, + 0x2fa0f582, + 0x39b745, + 0x3ba745, + 0x283483, + 0x20f586, + 0x20fec5, + 0x220cc2, + 0x35b3c5, + 0x220cc4, + 0x223d03, + 0x223f43, + 0x2fe05b42, + 0x2e29c7, + 0x24dbc4, + 0x24dbc9, + 0x24e2c4, + 0x2833c3, + 0x2b61c8, + 0x302833c4, + 0x2833c6, + 0x2a37c3, + 0x256303, + 0x308003, + 0x306f7642, + 0x309442, + 0x30a00642, + 0x335408, + 0x36af48, + 0x3b7906, + 0x3830c5, + 0x22c805, + 0x204287, + 0x30e77185, + 0x23c782, + 0x3129b602, + 0x31600042, + 0x2cfb88, + 0x3ae105, + 0x2fc7c4, + 0x244c85, + 0x2547c7, + 0x3a3884, + 0x242ac2, + 0x31a11442, + 0x351144, + 0x220a87, + 0x28ddc7, + 0x378804, + 0x3cd483, + 0x290e44, + 0x290e48, + 0x22f7c6, + 0x25254a, + 0x326584, + 0x299288, + 0x234184, + 0x2214c6, + 0x29b5c4, + 0x2f3546, + 0x24de89, + 0x2a9fc7, + 0x207543, + 0x31e3ee42, + 0x3b62c3, + 0x209e42, + 0x32204702, + 0x349e46, + 0x381988, + 0x2abfc7, + 0x228b09, + 0x2b1549, + 0x2ad505, + 0x2afc09, + 0x2b0405, + 0x2b1245, + 0x2b1f88, + 0x32608784, + 0x32a540c7, + 0x22d803, + 0x2b2187, + 0x22d806, + 0x2b25c7, + 0x2a9ac5, + 0x22d083, + 0x32e315c2, + 0x20b344, + 0x3320e782, + 0x33606502, + 0x380e86, + 0x2d04c5, + 0x2b54c7, + 0x343a03, + 0x35cb04, + 0x209283, + 0x2cd743, + 0x33a06182, + 0x34205bc2, + 0x38b244, + 0x22de83, + 0x3047c5, + 0x34600f42, + 0x34e01f02, + 0x304fc6, + 0x201f04, + 0x306bc4, + 0x306bca, + 0x356005c2, + 0x213903, + 0x21884a, + 0x21bac8, + 0x35a21dc4, + 0x2005c3, + 0x35e96b43, + 0x237909, + 0x22e0c9, + 0x2bc8c6, + 0x3621bc83, + 0x21bc85, + 0x222f8d, + 0x226586, + 0x26518b, + 0x3660ccc2, + 0x205708, + 0x3a217782, + 0x3a605382, + 0x2bad85, + 0x3aa04582, + 0x2b3307, + 0x210083, + 0x210088, + 0x3ae07882, + 0x288304, + 0x20c743, + 0x33b805, + 0x23fb46, + 0x224004, + 0x398983, + 0x2b9583, + 0x3b201d82, + 0x3b9344, + 0x3d4c45, + 0x2b8247, + 0x279403, + 0x2b8e43, + 0x16b9102, + 0x2b9103, + 0x2b9503, + 0x3b600e02, + 0x3473c4, + 0x251106, + 0x2e42c3, + 0x2b9c03, + 0x3ba49582, + 0x249588, + 0x2bab84, + 0x347146, + 0x255707, + 0x284646, + 0x29ff44, + 0x49e03fc2, + 0x22d6cb, + 0x2ff50e, + 0x216d8f, + 0x39d6c3, + 0x4a65ac42, + 0x161fb02, + 0x4aa0af02, + 0x2928c3, + 0x2108c3, + 0x20af06, + 0x21d306, + 0x34dec7, + 0x310c44, + 0x4ae14042, + 0x4b20bd82, + 0x2e0685, + 0x2ff987, + 0x2bb206, + 0x4b662702, + 0x384c44, + 0x2c03c3, + 0x4ba01e42, + 0x4bf73103, + 0x2c2984, + 0x2c8009, + 0x4c2ced42, + 0x4c614d42, + 0x344945, + 0x4cad3942, + 0x4ce06002, + 0x35f947, + 0x3768cb, + 0x242f05, + 0x258109, + 0x26aa86, + 0x4d209504, + 0x295449, + 0x2d46c7, + 0x3dea87, + 0x22c343, + 0x2eef06, + 0x324047, + 0x25cc03, + 0x2a6a86, + 0x4da1ae42, + 0x4de33042, + 0x3b6403, + 0x38b885, + 0x21f407, + 0x236146, + 0x23c885, + 0x24db44, + 0x2a8985, + 0x38dac4, + 0x4e202482, + 0x2cc844, + 0x22dfc4, + 0x22dfcd, + 0x377189, + 0x22c648, + 0x344bc4, + 0x328845, + 0x3b8c47, + 0x3c5cc4, + 0x265907, + 0x2e4005, + 0x4e6ac604, + 0x2bf345, + 0x25f8c4, + 0x3a39c6, + 0x3973c5, + 0x4ea05442, + 0x26e903, + 0x267fc3, + 0x348cc4, + 0x348cc5, + 0x396886, + 0x23c9c5, + 0x22ae84, + 0x329743, + 0x4ee1a286, + 0x221fc5, + 0x222a85, + 0x323544, + 0x2f6283, + 0x32660c, + 0x4f208b02, + 0x4f605102, + 0x4fa02042, + 0x21a8c3, + 0x21a8c4, + 0x4fe08282, + 0x30e1c8, + 0x3b1745, + 0x2d3b84, + 0x23af86, + 0x50223502, + 0x5061b542, + 0x50a00c42, + 0x290c05, + 0x2f3886, + 0x219604, + 0x39a0c6, + 0x362dc6, + 0x211183, + 0x50ea240a, + 0x2795c5, + 0x350503, + 0x222446, + 0x3d2d09, + 0x222447, + 0x2b4d08, + 0x32f0c9, + 0x2adfc8, + 0x227d46, + 0x2105c3, + 0x512017c2, + 0x39fa08, + 0x51601f42, + 0x51a09e82, + 0x2137c3, + 0x2ec0c5, + 0x29f2c4, + 0x2fe389, + 0x2898c4, + 0x24aec8, + 0x52209e83, + 0x52696ec4, + 0x213f48, + 0x22df07, + 0x52b3d642, + 0x238442, + 0x32a385, + 0x37fc49, + 0x23c803, + 0x27e384, + 0x31d284, + 0x210943, + 0x27f28a, + 0x52e03f82, + 0x5320b182, + 0x2d5b43, + 0x390883, + 0x1627f82, + 0x374583, + 0x5361d542, + 0x53a00bc2, + 0x53f06c44, + 0x3d7846, + 0x26bbc4, + 0x277d83, + 0x281c83, + 0x54200bc3, + 0x23f7c6, + 0x208405, + 0x2d9ac7, + 0x2d9a06, + 0x2dab48, + 0x2dad46, + 0x20e944, + 0x2a0f0b, + 0x2dd603, + 0x2dd605, + 0x20f002, + 0x35fc42, + 0x54645402, + 0x54a02382, + 0x202383, + 0x54e6c9c2, + 0x26c9c3, + 0x2de083, + 0x55622902, + 0x55ae2406, + 0x258946, + 0x55e05902, + 0x5620a742, + 0x56623f82, + 0x56a15402, + 0x56e18482, + 0x57202802, + 0x214e83, + 0x385546, + 0x57619a04, + 0x213a4a, + 0x3a4986, + 0x20da84, + 0x204643, + 0x5820ce02, + 0x208482, + 0x23a0c3, + 0x5861a3c3, + 0x3bd287, + 0x3972c7, + 0x5aed3087, + 0x344407, + 0x228643, + 0x22864a, + 0x262044, + 0x31afc4, + 0x31afca, + 0x22cb45, + 0x5b21bb02, + 0x24fa03, + 0x5b600602, + 0x24e283, + 0x3b6283, + 0x5be00582, + 0x38a8c4, + 0x204484, + 0x3c2d05, + 0x3dd205, + 0x26a146, + 0x306e06, + 0x5c230a42, + 0x5c602902, + 0x310805, + 0x258652, + 0x35e586, + 0x207283, + 0x359106, + 0x2bf805, + 0x16535c2, + 0x64a0a9c2, + 0x372b43, + 0x20a9c3, + 0x292083, + 0x64e06e42, + 0x210e83, + 0x6521ad42, + 0x276e43, + 0x24b188, + 0x2624c3, + 0x2ad386, + 0x3cfc87, + 0x321486, + 0x32148b, + 0x20d9c7, + 0x31d784, + 0x65a00c02, + 0x3b15c5, + 0x65e08443, + 0x26d243, + 0x3b29c5, + 0x33f243, + 0x6673f246, + 0x3cac0a, + 0x2a7083, + 0x2366c4, + 0x2003c6, + 0x2af186, + 0x66a42543, + 0x299047, + 0x237807, + 0x2a2c85, + 0x2e4406, + 0x222003, + 0x6960f7c3, + 0x69a00a82, + 0x69e0f044, + 0x3df689, + 0x21d685, + 0x356cc4, + 0x355b48, + 0x264bc5, + 0x6a231ac5, + 0x241f49, + 0x202503, + 0x33da04, + 0x6a614282, + 0x214283, + 0x6aa57b82, + 0x257b86, + 0x1677282, + 0x6ae15302, + 0x290b08, + 0x290e03, + 0x2bf287, + 0x2b9605, + 0x2b9185, + 0x2b918b, + 0x2eec86, + 0x2b9386, + 0x27d384, + 0x2efa86, + 0x6b321708, + 0x27fd03, + 0x265f03, + 0x265f04, + 0x2ed8c4, + 0x2f6a07, + 0x315645, + 0x6b72a5c2, + 0x6ba0a882, + 0x6c21bfc5, + 0x2c1044, + 0x2e0a0b, + 0x2f7688, + 0x253604, + 0x6c62c4c2, + 0x6ca1b742, + 0x3ba2c3, + 0x2f9484, + 0x2f9745, + 0x2fa147, + 0x6cefc304, + 0x378904, + 0x6d2141c2, + 0x37ab09, + 0x2fd745, + 0x2431c5, + 0x2fe2c5, + 0x6d6141c3, + 0x237f04, + 0x237f0b, + 0x2fedc4, + 0x2ff08b, + 0x3001c5, + 0x216eca, + 0x301708, + 0x30190a, + 0x3021c3, + 0x3021ca, + 0x6de11e42, + 0x6e214b42, + 0x6e615d43, + 0x6eadbd02, + 0x3068c3, + 0x6eef6702, + 0x6f333e42, + 0x309004, + 0x2177c6, + 0x399e05, + 0x30a643, + 0x298046, + 0x399905, + 0x3573c4, + 0x6f600902, + 0x299ec4, + 0x2d5dca, + 0x2ba807, + 0x33f5c6, + 0x234207, + 0x23e343, + 0x2c29c8, + 0x3d21cb, + 0x2bc9c5, + 0x2c8b85, + 0x2c8b86, + 0x34cb84, + 0x38ab88, + 0x21aa43, + 0x26ee44, + 0x3c3747, + 0x31d3c6, + 0x380b86, + 0x2c324a, + 0x24d804, + 0x31c0ca, + 0x6fb12606, + 0x312607, + 0x255c07, + 0x2a9a04, + 0x34a189, + 0x238dc5, + 0x307a4b, + 0x2f6603, + 0x20cc83, + 0x6fe1e243, + 0x22fb84, + 0x70200682, + 0x307e06, + 0x706c60c5, + 0x359345, + 0x24fc86, + 0x2a4944, + 0x70a013c2, + 0x241e84, + 0x70e0ca42, + 0x2160c5, + 0x3b2e44, + 0x71a1c5c3, + 0x71e0aa02, + 0x20aa03, + 0x21f646, + 0x72205142, + 0x393d08, + 0x2222c4, + 0x2222c6, + 0x391106, + 0x726574c4, + 0x21a205, + 0x356d88, + 0x3577c7, + 0x2ae247, + 0x2ae24f, + 0x292f46, + 0x23d183, + 0x242144, + 0x209043, + 0x221604, + 0x24e484, + 0x72a0b382, + 0x28d203, + 0x330983, + 0x72e090c2, + 0x215803, + 0x220f03, + 0x20e2ca, + 0x273847, + 0x25284c, + 0x73252b06, + 0x252c86, + 0x255407, + 0x7362e987, + 0x25a749, + 0x308784, + 0x73a5be04, + 0x73e023c2, + 0x742045c2, + 0x2c3606, + 0x298e44, + 0x28d686, + 0x22ee08, + 0x38b944, + 0x2eafc6, + 0x28ebc5, + 0x74750788, + 0x242343, + 0x3a6b85, + 0x3aa603, + 0x2432c3, + 0x2432c4, + 0x208dc3, + 0x74a499c2, + 0x74e02d42, + 0x2f64c9, + 0x290d05, + 0x291604, + 0x29ab05, + 0x206a84, + 0x286707, + 0x35a685, + 0x7523e804, + 0x2db988, + 0x2dcdc6, + 0x2e2d44, + 0x2e6e08, + 0x2e7447, + 0x75607842, + 0x2ef184, + 0x314cc4, + 0x2c9247, + 0x75a07844, + 0x24a682, + 0x75e02f82, + 0x210883, + 0x2e5ac4, + 0x299943, + 0x2b2cc5, + 0x7622ae42, + 0x309345, + 0x23c7c2, + 0x30f885, + 0x23c7c5, + 0x76607242, + 0x327704, + 0x76a071c2, + 0x33d486, + 0x2c8686, + 0x37fd88, + 0x2c9c08, + 0x380e04, + 0x3cdb05, + 0x310389, + 0x2f0684, + 0x3cabc4, + 0x288b03, + 0x26c703, + 0x76f02905, + 0x3829c5, + 0x283644, + 0x359b4d, + 0x294ec2, + 0x376403, + 0x77206382, + 0x77603242, + 0x3937c5, + 0x24b447, + 0x224244, + 0x32f2c9, + 0x2d5f09, + 0x2770c3, + 0x2770c8, + 0x312b09, + 0x21e7c7, + 0x77a08805, + 0x396406, + 0x3a06c6, + 0x3a8645, + 0x377285, + 0x77e01bc2, + 0x27a585, + 0x2bd4c8, + 0x2cb646, + 0x783b4347, + 0x2cf3c4, + 0x2da987, + 0x30b306, + 0x78601082, + 0x396586, + 0x30ef0a, + 0x30f785, + 0x78af00c2, + 0x78e11102, + 0x365486, + 0x211108, + 0x7928df87, + 0x79601402, + 0x214b83, + 0x3c0706, + 0x2caac4, + 0x346ac6, + 0x271ac6, + 0x26930a, + 0x2047c5, + 0x286f06, + 0x384643, + 0x384644, + 0x79a35002, + 0x2869c3, + 0x79e1a902, + 0x2ea903, + 0x7a218ac4, + 0x211244, + 0x7a61124a, + 0x21bd03, + 0x237ac7, + 0x313146, + 0x33c284, + 0x20d942, + 0x2aad42, + 0x7aa007c2, + 0x226e83, + 0x2559c7, + 0x2007c7, + 0x285d84, + 0x3da107, + 0x2fa246, + 0x210d47, + 0x220e44, + 0x2ae145, + 0x205345, + 0x7ae1e502, + 0x3d7286, + 0x220383, + 0x2266c2, + 0x2266c6, + 0x7b21f3c2, + 0x7b633442, + 0x29d005, + 0x7ba02c02, + 0x7be02982, + 0x324605, + 0x2d7505, + 0x2ac745, + 0x7c65b003, + 0x279a45, + 0x2eed47, + 0x36cc85, + 0x204985, + 0x261f44, + 0x264a46, + 0x38e104, + 0x7ca008c2, + 0x7d793085, + 0x3cb087, + 0x3c0bc8, + 0x253c46, + 0x253c4d, + 0x262d49, + 0x262d52, + 0x37a385, + 0x37ae03, + 0x7da09d42, + 0x3027c4, + 0x226603, + 0x3cb985, + 0x310f85, + 0x7de0c782, + 0x25a6c3, + 0x7e226dc2, + 0x7ea1d602, + 0x7ee00082, + 0x2e9bc5, + 0x207643, + 0x7f205b02, + 0x7f60c2c2, + 0x38a886, + 0x2d020a, + 0x215003, + 0x2579c3, + 0x2ff8c3, + 0x80e01b82, + 0x8f20c1c2, + 0x8fa0a5c2, + 0x203642, + 0x3ce689, + 0x2ce144, + 0x2dfac8, + 0x8ff04382, + 0x90606482, + 0x3bd905, + 0x233c88, + 0x231148, + 0x2f738c, + 0x2398c3, + 0x90a075c2, + 0x90e00f02, + 0x24ac46, + 0x313fc5, + 0x295b43, + 0x254686, + 0x314106, + 0x296b03, + 0x314c03, + 0x315046, + 0x316884, + 0x29cc86, + 0x23cd44, + 0x316f44, + 0x31784a, + 0x912b7402, + 0x24e705, + 0x3193ca, + 0x319305, + 0x31a7c4, + 0x31a8c6, + 0x31aa44, + 0x214546, + 0x91602b42, + 0x24c5c6, + 0x33bf85, + 0x286d87, + 0x33a106, + 0x255604, + 0x2e3407, + 0x234f85, + 0x23b687, + 0x3bc247, + 0x3bc24e, + 0x278646, + 0x222705, + 0x207787, + 0x20a783, + 0x3d3a47, + 0x20ab85, + 0x2123c4, + 0x22a8c2, + 0x325ec7, + 0x310cc4, + 0x23dec4, + 0x284a4b, + 0x21cb83, + 0x2c4907, + 0x21cb84, + 0x2c4c07, + 0x3a6603, + 0x34e40d, + 0x3a2f88, + 0x91a292c4, + 0x23e705, + 0x31b805, + 0x31bc43, + 0x91e221c2, + 0x31d1c3, + 0x31e083, + 0x3d7404, + 0x27bf85, + 0x220407, + 0x3846c6, + 0x38d943, + 0x22680b, + 0x249b8b, + 0x2acfcb, + 0x2c174b, + 0x3ccd4a, + 0x31734b, + 0x36ea8b, + 0x394e0c, + 0x3ada0b, + 0x3bf811, + 0x3dcf4a, + 0x31f58b, + 0x31f84c, + 0x31fb4b, + 0x3200ca, + 0x3209ca, + 0x3221ce, + 0x32294b, + 0x322c0a, + 0x324751, + 0x324b8a, + 0x32508b, + 0x3255ce, + 0x326c8c, + 0x32784b, + 0x327b0e, + 0x327e8c, + 0x328bca, + 0x329d4c, + 0x9232a04a, + 0x32a808, + 0x32b3c9, + 0x32ce8a, + 0x32d10a, + 0x32d38b, + 0x33010e, + 0x3316d1, + 0x33e209, + 0x33e44a, + 0x33ee8b, + 0x33fc0d, + 0x340a8a, + 0x341616, + 0x34298b, + 0x34668a, + 0x347d0a, + 0x3490cb, + 0x34aa49, + 0x34ed89, + 0x34f30d, + 0x34fe0b, + 0x351c8b, + 0x352509, + 0x352b4e, + 0x35328a, + 0x353dca, + 0x35438a, + 0x354a0b, + 0x35524b, + 0x3585cd, + 0x35a18d, + 0x35b050, + 0x35b50b, + 0x35ce4c, + 0x35d98b, + 0x35f44b, + 0x360c4e, + 0x36128b, + 0x36128d, + 0x3663cb, + 0x366e4f, + 0x36720b, + 0x36860a, + 0x368e49, + 0x369509, + 0x9276988b, + 0x369b4e, + 0x369ece, + 0x36be8b, + 0x36d64f, + 0x370acb, + 0x370d8b, + 0x37104b, + 0x37164a, + 0x3764c9, + 0x37964f, + 0x37e24c, + 0x37f30c, + 0x38058e, + 0x3810cf, + 0x38148e, + 0x381e50, + 0x38224f, + 0x382b4e, + 0x38320c, + 0x383511, + 0x383952, + 0x3856d1, + 0x385dce, + 0x38620b, + 0x38620e, + 0x38658f, + 0x38694e, + 0x386cd3, + 0x387191, + 0x3875cc, + 0x3878ce, + 0x387d4c, + 0x388293, + 0x388a90, + 0x389b8c, + 0x389e8c, + 0x38a34b, + 0x38ae4e, + 0x38b34b, + 0x38cb4b, + 0x38ddcc, + 0x39424a, + 0x39460c, + 0x39490c, + 0x394c09, + 0x396a0b, + 0x396cc8, + 0x397509, + 0x39750f, + 0x3991cb, + 0x92b9a54a, + 0x39bd0c, + 0x39cccb, + 0x39cf89, + 0x39d348, + 0x39da4b, + 0x39df4b, + 0x39eb8a, + 0x39ee0b, + 0x39f78c, + 0x3a0149, + 0x3a0388, + 0x3a3d0b, + 0x3a6f4b, + 0x3a91ce, + 0x3aaf4b, + 0x3ad38b, + 0x3bbdcb, + 0x3bc089, + 0x3bc5cd, + 0x3cbe4a, + 0x3cf5d7, + 0x3d18d8, + 0x3d5909, + 0x3d6b0b, + 0x3d79d4, + 0x3d7ecb, + 0x3d844a, + 0x3d894a, + 0x3d8bcb, + 0x3da790, + 0x3dab91, + 0x3db24a, + 0x3dc54d, + 0x3dcc4d, + 0x3e06cb, + 0x3d7383, + 0x92f9b403, + 0x289b06, + 0x246085, + 0x30ccc7, + 0x2ef746, + 0x165c942, + 0x270b89, + 0x297e44, + 0x2ed408, + 0x21e183, + 0x302707, + 0x205602, + 0x2b5503, + 0x93201442, + 0x2d69c6, + 0x2d8084, + 0x38f1c4, + 0x268643, + 0x93ad3982, + 0x93e2a784, + 0x34a0c7, + 0x9422a502, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x105dc8, + 0x203dc3, + 0x2000c2, + 0x9a048, + 0x201242, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x20e2c3, + 0x337396, + 0x364d53, + 0x3d9f89, + 0x2135c8, + 0x3b1449, + 0x319546, + 0x351190, + 0x20dcd3, + 0x31d488, + 0x277e87, + 0x279e87, + 0x2a86ca, + 0x343189, + 0x267d49, + 0x2d368b, + 0x303c06, + 0x30334a, + 0x2205c6, + 0x32a4c3, + 0x2e2905, + 0x3ba348, + 0x27decd, + 0x2f330c, + 0x2ec347, + 0x30bfcd, + 0x2136c4, + 0x22fe4a, + 0x23134a, + 0x23180a, + 0x20dfc7, + 0x23cb87, + 0x240104, + 0x273506, + 0x348a44, + 0x304c08, + 0x289909, + 0x2e6606, + 0x2e6608, + 0x24360d, + 0x2d6149, + 0x392488, + 0x243147, + 0x3b27ca, + 0x250086, + 0x2fd244, + 0x212107, + 0x30800a, + 0x3ab68e, + 0x277185, + 0x3daf8b, + 0x226bc9, + 0x22e0c9, + 0x2b3147, + 0x3d090a, + 0x2c9187, + 0x2ff649, + 0x33b048, + 0x2a5e8b, + 0x2ec0c5, + 0x22c50a, + 0x223d49, + 0x295aca, + 0x20f30b, + 0x21200b, + 0x2d3415, + 0x2c8205, + 0x2431c5, + 0x237f0a, + 0x22b98a, + 0x2f5d87, + 0x233dc3, + 0x2c3588, + 0x2e0eca, + 0x2222c6, + 0x259c09, + 0x350788, + 0x2e2d44, + 0x388049, + 0x2c9c08, + 0x2ca947, + 0x393086, + 0x3cb087, + 0x2be807, + 0x23f5c5, + 0x2d314c, + 0x23e705, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x201242, + 0x214a83, + 0x21a3c3, + 0x203dc3, + 0x242543, + 0x214a83, + 0x21a3c3, + 0x3dc3, + 0x2624c3, + 0x242543, + 0x1cc203, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x9a048, + 0x201242, + 0x214a83, + 0x22ca07, + 0x86504, + 0x21a3c3, + 0x97a04, + 0x242543, + 0x201242, + 0x2052c2, + 0x3192c2, + 0x207882, + 0x201582, + 0x2eda82, + 0x908c6, + 0x50849, + 0xf3fc7, + 0x481c5c3, + 0x86107, + 0x148406, + 0x7783, + 0x11af85, + 0xc1, + 0x5214a83, + 0x232dc3, + 0x228503, + 0x308003, + 0x21bc83, + 0x23c803, + 0x2e2806, + 0x21a3c3, + 0x242543, + 0x233d43, + 0x9a048, + 0x345b44, + 0x296c87, + 0x268683, + 0x2bad84, + 0x2187c3, + 0x284d43, + 0x308003, + 0x17e707, + 0x9c4, + 0x4e83, + 0x68b05, + 0x66000c2, + 0x2703, + 0x6a01242, + 0x6c8c109, + 0x8c98d, + 0x8cccd, + 0x3192c2, + 0x21dc4, + 0x68b49, + 0x2003c2, + 0x7221cc8, + 0xfe7c4, + 0x31c843, + 0x9a048, + 0x1414882, + 0x14005c2, + 0x1414882, + 0x1517146, + 0x22f043, + 0x26f6c3, + 0x7a14a83, + 0x22fe44, + 0x7e32dc3, + 0x8b08003, + 0x206182, + 0x221dc4, + 0x21a3c3, + 0x3b1e83, + 0x204042, + 0x242543, + 0x202642, + 0x308f43, + 0x205142, + 0x2263c3, + 0x223a43, + 0x201342, + 0x9a048, + 0x22f043, + 0x3df888, + 0x83b1e83, + 0x204042, + 0x308f43, + 0x205142, + 0x86263c3, + 0x223a43, + 0x201342, + 0x252b07, + 0x232dc9, + 0x308f43, + 0x205142, + 0x2263c3, + 0x223a43, + 0x201342, + 0x214a83, + 0x16c2, + 0x32443, + 0x3c42, + 0xaac82, + 0x5cd82, + 0x17c2, + 0x1b82, + 0x43342, + 0x202703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x20eb02, + 0x2141c3, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x202703, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x208805, + 0x20c782, + 0x2000c2, + 0x9a048, + 0x144ca88, + 0x12848a, + 0x308003, + 0x225cc1, + 0x2009c1, + 0x200a01, + 0x204ac1, + 0x204781, + 0x20a541, + 0x201941, + 0x225dc1, + 0x23ff81, + 0x200001, + 0x2000c1, + 0x200201, + 0x139b05, + 0x9a048, + 0x200101, + 0x201301, + 0x200501, + 0x205dc1, + 0x200041, + 0x200801, + 0x200181, + 0x200e01, + 0x200701, + 0x2004c1, + 0x200bc1, + 0x200581, + 0x2003c1, + 0x200a81, + 0x215481, + 0x200401, + 0x200741, + 0x2007c1, + 0x200081, + 0x200f01, + 0x201341, + 0x204f01, + 0x201b41, + 0x201441, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x201242, + 0x214a83, + 0x232dc3, + 0x2003c2, + 0x242543, + 0x1bf83, + 0x17e707, + 0xd1407, + 0x28886, + 0x34b8a, + 0x8b848, + 0x54e08, + 0x558c7, + 0x174586, + 0xea585, + 0x97805, + 0x125483, + 0x11ec6, + 0x365c6, + 0x2d3684, + 0x328147, + 0x9a048, + 0x2e3504, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x1242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x32a248, + 0x204244, + 0x232d04, + 0x229904, + 0x24ab47, + 0x2e0007, + 0x214a83, + 0x235b4b, + 0x29650a, + 0x33c147, + 0x23bc48, + 0x33b888, + 0x232dc3, + 0x287847, + 0x228503, + 0x206f88, + 0x2130c9, + 0x221dc4, + 0x21bc83, + 0x23b248, + 0x23c803, + 0x2dd74a, + 0x2e2806, + 0x3a4987, + 0x21a3c3, + 0x267906, + 0x26f548, + 0x242543, + 0x24d446, + 0x2f78cd, + 0x2f9e08, + 0x2fedcb, + 0x20eb46, + 0x24b347, + 0x2225c5, + 0x21674a, + 0x308245, + 0x3828ca, + 0x20c782, + 0x207783, + 0x23dec4, + 0x200006, + 0x3b05c3, + 0x299f43, + 0x27ee03, + 0x204243, + 0x296183, + 0x2041c2, + 0x355dc5, + 0x2ad8c9, + 0x23fc43, + 0x220dc3, + 0x21fdc3, + 0x200201, + 0x2f0447, + 0x2e9905, + 0x3b5c03, + 0x3d6d83, + 0x229904, + 0x343a43, + 0x20ff88, + 0x35d143, + 0x30d98d, + 0x278708, + 0x3dfa46, + 0x286a03, + 0x361583, + 0x38e083, + 0xce14a83, + 0x232608, + 0x235b44, + 0x240983, + 0x200106, + 0x243d88, + 0x27b0c3, + 0x216783, + 0x22d1c3, + 0x232dc3, + 0x21afc3, + 0x2532c3, + 0x283603, + 0x286983, + 0x2cbf83, + 0x2196c3, + 0x38b5c5, + 0x250804, + 0x251987, + 0x22dec2, + 0x254483, + 0x257d06, + 0x2592c3, + 0x25a283, + 0x277083, + 0x374e43, + 0x345843, + 0x29c047, + 0xd308003, + 0x2425c3, + 0x286a43, + 0x206c03, + 0x21bac3, + 0x24c903, + 0x20ef85, + 0x373c83, + 0x200e09, + 0x20bb83, + 0x311283, + 0xd63c883, + 0x2d3b03, + 0x219208, + 0x2ad806, + 0x374c06, + 0x2b7106, + 0x389147, + 0x227d43, + 0x2137c3, + 0x23c803, + 0x28b946, + 0x20f002, + 0x267d83, + 0x353145, + 0x21a3c3, + 0x319e87, + 0x1603dc3, + 0x202903, + 0x2089c3, + 0x21fec3, + 0x26d243, + 0x242543, + 0x209006, + 0x3b5f86, + 0x37a243, + 0x2f8a83, + 0x2141c3, + 0x220ec3, + 0x314c83, + 0x305fc3, + 0x309303, + 0x399905, + 0x22b983, + 0x39f446, + 0x2d1cc8, + 0x20cc83, + 0x20cc89, + 0x298948, + 0x223488, + 0x229a85, + 0x22f18a, + 0x23818a, + 0x239b4b, + 0x23b808, + 0x398943, + 0x38da83, + 0x30a583, + 0x326f48, + 0x376dc3, + 0x384644, + 0x235002, + 0x25ca83, + 0x2007c3, + 0x356c43, + 0x263343, + 0x233d43, + 0x20c782, + 0x229e43, + 0x2398c3, + 0x3172c3, + 0x318284, + 0x23dec4, + 0x20fe43, + 0x9a048, + 0x2000c2, + 0x200ac2, + 0x2041c2, + 0x204b42, + 0x200202, + 0x204342, + 0x240702, + 0x203c42, + 0x200382, + 0x200c42, + 0x33d642, + 0x202382, + 0x26c9c2, + 0x200a82, + 0x2eda82, + 0x214282, + 0x205742, + 0x2141c2, + 0x2c1902, + 0x2069c2, + 0x200682, + 0x206f02, + 0x2013c2, + 0x2090c2, + 0x2045c2, + 0x26c702, + 0x202982, + 0xc2, + 0xac2, + 0x41c2, + 0x4b42, + 0x202, + 0x4342, + 0x40702, + 0x3c42, + 0x382, + 0xc42, + 0x13d642, + 0x2382, + 0x6c9c2, + 0xa82, + 0xeda82, + 0x14282, + 0x5742, + 0x141c2, + 0xc1902, + 0x69c2, + 0x682, + 0x6f02, + 0x13c2, + 0x90c2, + 0x45c2, + 0x6c702, + 0x2982, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x7782, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x1242, + 0x201242, + 0x242543, + 0xee14a83, + 0x308003, + 0x23c803, + 0x1b4103, + 0x22aec2, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x3dc3, + 0x1b4103, + 0x242543, + 0x1442, + 0x2001c2, + 0x15c45c5, + 0x139b05, + 0x20b3c2, + 0x9a048, + 0x1242, + 0x2347c2, + 0x206782, + 0x204642, + 0x21bb02, + 0x230a42, + 0x97805, + 0x202f42, + 0x204042, + 0x206e42, + 0x205e42, + 0x214282, + 0x23fcc2, + 0x202f82, + 0x292882, + 0xfe98384, + 0x142, + 0x17e707, + 0x12380d, + 0xea609, + 0x115e0b, + 0xeec08, + 0x65dc9, + 0x111b86, + 0x308003, + 0x9a048, + 0x9c4, + 0x4e83, + 0x68b05, + 0x9a048, + 0xe5a47, + 0x56306, + 0x68b49, + 0x1d134e, + 0x14a887, + 0x2000c2, + 0x2d3684, + 0x201242, + 0x214a83, + 0x2052c2, + 0x232dc3, + 0x1bb43, + 0x200382, + 0x2e3504, + 0x21bc83, + 0x201f42, + 0x21a3c3, + 0x30a42, + 0x2003c2, + 0x242543, + 0x2431c6, + 0x32d94f, + 0x602, + 0x725e43, + 0x2f294a, + 0x9a048, + 0x201242, + 0x228503, + 0x308003, + 0x23c803, + 0x3dc3, + 0x1467206, + 0x1d1348, + 0x141650b, + 0x156518a, + 0xf1fc9, + 0x15d024a, + 0x1511707, + 0xa878b, + 0x10b7c5, + 0xebbc5, + 0x119bc9, + 0x139b05, + 0x17e707, + 0xfbfc4, + 0x201242, + 0x214a83, + 0x308003, + 0x21a3c3, + 0x2000c2, + 0x200c82, + 0x2019c2, + 0x13214a83, + 0x23d342, + 0x232dc3, + 0x20bb42, + 0x2299c2, + 0x308003, + 0x23c782, + 0x25d282, + 0x22a742, + 0x200cc2, + 0x290602, + 0x200802, + 0x200d82, + 0x23ee42, + 0x27b8c2, + 0x204702, + 0x1b19cc, + 0x2b8e42, + 0x252e82, + 0x2203c2, + 0x248642, + 0x23c803, + 0x200bc2, + 0x21a3c3, + 0x243802, + 0x249b42, + 0x242543, + 0x308c82, + 0x2090c2, + 0x2023c2, + 0x202d42, + 0x207242, + 0x2f00c2, + 0x21e502, + 0x226dc2, + 0x223fc2, + 0x322c0a, + 0x36860a, + 0x39abca, + 0x3e0d02, + 0x210702, + 0x20ef42, + 0x1376fcc9, + 0x13b5cbca, + 0x142e307, + 0x13e026c2, + 0x14fe3c3, + 0x4a82, + 0x15cbca, + 0x15dc0e, + 0x24c0c4, + 0x572c5, + 0x14614a83, + 0x3dc83, + 0x232dc3, + 0x24d9c4, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x137a89, + 0x68006, + 0x23c803, + 0xefa04, + 0x4743, + 0x21a3c3, + 0x1df105, + 0x203dc3, + 0x242543, + 0x1464b04, + 0x22b983, + 0x11b504, + 0x207783, + 0x9a048, + 0x1521403, + 0x125d86, + 0x1574504, + 0x68445, + 0x14a64a, + 0x129cc2, + 0x1500160d, + 0x1a6286, + 0x15291, + 0x1576fcc9, + 0x684c8, + 0x62888, + 0x1c12c707, + 0x1182, + 0x16fe47, + 0x2380e, + 0x139b0b, + 0x13f10b, + 0x1b3d4a, + 0x29907, + 0x9a048, + 0x11c988, + 0x7bc7, + 0x1c4169cb, + 0x1bf87, + 0xcd42, + 0x26ccd, + 0x1c2a07, + 0xaed8a, + 0x1d92cf, + 0x6738f, + 0x167c2, + 0x1242, + 0x83548, + 0x1c8f48cc, + 0xe770a, + 0xe554a, + 0x18990a, + 0x78508, + 0x8d08, + 0x5aa88, + 0xe5a08, + 0x145e88, + 0x2a42, + 0x1c464f, + 0xc134b, + 0x79108, + 0x25687, + 0x14474a, + 0x2490b, + 0x33249, + 0x46e07, + 0x8c08, + 0x3834c, + 0x15c087, + 0x1a67ca, + 0x106c8, + 0x2888e, + 0x2904e, + 0x2974b, + 0x2aa8b, + 0x15748b, + 0x14bf09, + 0xe3b0b, + 0xec58d, + 0x1261cb, + 0x30b4d, + 0x30ecd, + 0x3640a, + 0x3dd0b, + 0x3e54b, + 0x46405, + 0x1cd79a10, + 0x199e8f, + 0x9854f, + 0x63c4d, + 0x137c50, + 0xaac82, + 0x1d20c388, + 0xd1288, + 0xe8090, + 0xcf48e, + 0x1d75d105, + 0x4d1cb, + 0x136b90, + 0x8e0a, + 0x2ac49, + 0x61487, + 0x617c7, + 0x61987, + 0x61d07, + 0x631c7, + 0x63407, + 0x65587, + 0x65ac7, + 0x66007, + 0x66387, + 0x66a47, + 0x66c07, + 0x66dc7, + 0x66f87, + 0x69a47, + 0x6a407, + 0x6ac07, + 0x6afc7, + 0x6b607, + 0x6b8c7, + 0x6ba87, + 0x6bd87, + 0x6c887, + 0x6ca87, + 0x6d907, + 0x6dac7, + 0x6dc87, + 0x6f247, + 0x71247, + 0x71707, + 0x72207, + 0x724c7, + 0x72847, + 0x72a07, + 0x72e07, + 0x73247, + 0x73707, + 0x73c87, + 0x73e47, + 0x74007, + 0x74447, + 0x74ec7, + 0x75407, + 0x75987, + 0x75b47, + 0x75ec7, + 0x76407, + 0x6882, + 0x5ab8a, + 0x11cc8, + 0x1b0ecc, + 0x71b87, + 0x85805, + 0xa7951, + 0x1c0d86, + 0xfb14a, + 0x833ca, + 0x56306, + 0xb060b, + 0x642, + 0x2f7d1, + 0xbf089, + 0x9b209, + 0x9bb06, + 0x3ee42, + 0x9218a, + 0xacdc9, + 0xad50f, + 0xadb0e, + 0xaff88, + 0x6502, + 0x174a49, + 0x8a58e, + 0x1c7f0c, + 0xf1ccf, + 0x1b7a0e, + 0x3230c, + 0x41a89, + 0xd2551, + 0xd2b08, + 0x59452, + 0x62a4d, + 0x733cd, + 0x7984b, + 0x7ea95, + 0xf0c09, + 0x182f8a, + 0x1a3749, + 0x1aa210, + 0x9028b, + 0x9378f, + 0xa694b, + 0xab54c, + 0xb1b90, + 0xb4b0a, + 0xcc00d, + 0xb7ece, + 0x14db0a, + 0x1bd50c, + 0xbe4d4, + 0xbed11, + 0xc0f0b, + 0xc310f, + 0xc5f8d, + 0xc854e, + 0xca80c, + 0xcb00c, + 0xcbd0b, + 0x13ea4e, + 0x16c350, + 0xd974b, + 0xda40d, + 0xdcf0f, + 0xdf00c, + 0xe648e, + 0xf2391, + 0x10498c, + 0x1dc387, + 0x10b44d, + 0x11a00c, + 0x140cd0, + 0x15fd8d, + 0x168847, + 0x18e8d0, + 0x19d508, + 0x1a160b, + 0xb6b8f, + 0x1b1148, + 0x149d4d, + 0x10f810, + 0x17e609, + 0x1db799c8, + 0x1deb9c06, + 0xbaac3, + 0x15a889, + 0xc00c5, + 0x1e42, + 0x144bc9, + 0x14a34a, + 0x1e259906, + 0x145990d, + 0x1e7c2c04, + 0x57a46, + 0x1e08a, + 0x6474d, + 0x1e9df489, + 0x19a83, + 0x1175ca, + 0xe4651, + 0xe4a89, + 0xe54c7, + 0xe61c8, + 0xe68c7, + 0x71c48, + 0x1540b, + 0x12bc49, + 0xf1210, + 0xf16cc, + 0xf27c8, + 0xf4705, + 0x13b1c8, + 0x1961ca, + 0x184947, + 0x2902, + 0x1ef47415, + 0x13788a, + 0x1b2589, + 0x108a08, + 0x9cd89, + 0x46145, + 0x119d0a, + 0x8decf, + 0x10b84b, + 0xf04c, + 0x18ee12, + 0x77285, + 0x114e48, + 0xf678b, + 0xe0a11, + 0x4dcca, + 0x1f2fe185, + 0x19b18c, + 0x133e43, + 0x192286, + 0x3fcc2, + 0x10948b, + 0x109f4a, + 0x150a2cc, + 0xd1608, + 0x30d08, + 0x1f708a86, + 0x1b2f07, + 0xca42, + 0x5142, + 0x18bb50, + 0x69bc7, + 0x2ee0f, + 0x11ec6, + 0x11ed0e, + 0x94c0b, + 0x472c8, + 0x33609, + 0x13ce92, + 0x19234d, + 0x115488, + 0x115cc9, + 0x176f4d, + 0x198609, + 0x63cb, + 0x6bf08, + 0x7a688, + 0x7ce08, + 0x7d249, + 0x7d44a, + 0x8c30c, + 0x3e80a, + 0xf198a, + 0x114cc7, + 0x9994a, + 0x1c350d, + 0xd2e11, + 0x1fac8846, + 0x1cd64b, + 0x97c4c, + 0x39988, + 0x13d849, + 0x15b84d, + 0x61f50, + 0x1808cd, + 0xc2c2, + 0x4f70d, + 0x1b82, + 0xc1c2, + 0x114c0a, + 0x6e70a, + 0xfb04a, + 0x10260b, + 0x292cc, + 0x11c48a, + 0x11c70e, + 0x1d74cd, + 0x1fde0bc5, + 0x128948, + 0x1442, + 0x14239c3, + 0x15a6960e, + 0x16204b4e, + 0x16a6820a, + 0x1734630e, + 0x17b63a8e, + 0x18289d0c, + 0x142e307, + 0x142e309, + 0x14fe3c3, + 0x18b0400c, + 0x1933dfc9, + 0x19b48e89, + 0x1a353b89, + 0x4a82, + 0x69551, + 0x4a91, + 0x6814d, + 0x146251, + 0x1639d1, + 0x89c4f, + 0x103f4f, + 0x13df0c, + 0x148dcc, + 0x153acc, + 0x4b5cd, + 0x1aaa15, + 0xedc8c, + 0x1b32cc, + 0x13f810, + 0x16b10c, + 0x178fcc, + 0x1ac319, + 0x1b6959, + 0x1c1259, + 0x1da294, + 0x76d4, + 0x7d54, + 0x9754, + 0x9f94, + 0x1aa07989, + 0x1b008009, + 0x1bbb3389, + 0x15ed2d09, + 0x4a82, + 0x166d2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x16ed2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x176d2d09, + 0x4a82, + 0x17ed2d09, + 0x4a82, + 0x186d2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x18ed2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x196d2d09, + 0x4a82, + 0x19ed2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x1a6d2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x1aed2d09, + 0x4a82, + 0x1b6d2d09, + 0x4a82, + 0x1bed2d09, + 0x4a82, + 0x76ca, + 0x4a82, + 0x1400401, + 0x15285, + 0x1b3d44, + 0x14c86c3, + 0x15d6e03, + 0x14f8943, + 0x6960e, + 0x4b4e, + 0x7c80e, + 0x6820a, + 0x14630e, + 0x163a8e, + 0x89d0c, + 0x10400c, + 0x13dfc9, + 0x148e89, + 0x153b89, + 0x7989, + 0x8009, + 0x1b3389, + 0x13f8cd, + 0x9a09, + 0xa249, + 0x12f604, + 0x18ad44, + 0x1bad44, + 0x1bf004, + 0xa8a44, + 0x2cc04, + 0x3ca84, + 0x53684, + 0x11dc4, + 0x62b84, + 0x1588703, + 0x13dd87, + 0x147dc8c, + 0xf283, + 0xaac82, + 0xae8c6, + 0x1d74c3, + 0xf283, + 0x9fc83, + 0x8582, + 0x8588, + 0xe9247, + 0x12bcc7, + 0x2a42, + 0x2000c2, + 0x201242, + 0x2052c2, + 0x20dec2, + 0x200382, + 0x2003c2, + 0x205142, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21bac3, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x21a3c3, + 0x242543, + 0xb2c3, + 0x308003, + 0x21dc4, + 0x2000c2, + 0x202703, + 0x22214a83, + 0x38b9c7, + 0x308003, + 0x21a8c3, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x21e2ca, + 0x2431c5, + 0x2141c3, + 0x233442, + 0x9a048, + 0x226d8a4a, + 0xe01, + 0x9a048, + 0x1242, + 0x131a42, + 0x22fdf20b, + 0x23227fc4, + 0x1c2b45, + 0x1805, + 0xf48c6, + 0x23601805, + 0x53bc3, + 0x94e83, + 0x9c4, + 0x4e83, + 0x68b05, + 0x139b05, + 0x9a048, + 0x1bf87, + 0x14a83, + 0x2cd0d, + 0x23e3a147, + 0x144686, + 0x24146145, + 0x1b8dd2, + 0x3a247, + 0x1d35ca, + 0x1d3488, + 0x95c7, + 0x6574a, + 0x1a7308, + 0xe2b07, + 0x1a870f, + 0x169347, + 0x53486, + 0x136b90, + 0x11dccf, + 0x1a009, + 0x57ac4, + 0x2443a30e, + 0x35509, + 0x670c6, + 0x10ecc9, + 0x18d986, + 0x1ba1c6, + 0x78ecc, + 0x24b0a, + 0x333c7, + 0x14420a, + 0x33c9, + 0xf714c, + 0x1d40a, + 0x5c30a, + 0x68b49, + 0x57a46, + 0x3348a, + 0x11634a, + 0xa430a, + 0x14fbc9, + 0xe30c8, + 0xe3346, + 0xeb54d, + 0x5390b, + 0xc0545, + 0x24b55a0c, + 0x14a887, + 0x10d1c9, + 0xbf407, + 0x10fc14, + 0x11010b, + 0x254ca, + 0x13cd0a, + 0xaabcd, + 0x1502809, + 0x11524c, + 0x115acb, + 0x106c3, + 0x106c3, + 0x28886, + 0x106c3, + 0xf48c8, + 0x155983, + 0x44ec4, + 0x53f83, + 0x335c5, + 0x146e943, + 0x50849, + 0xf678b, + 0x14df283, + 0x148406, + 0x14ecac7, + 0x1aa487, + 0x2592c5c9, + 0x1a286, + 0x173d09, + 0x2703, + 0x9a048, + 0x1242, + 0x4d9c4, + 0x88c3, + 0x8805, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x220dc3, + 0x214a83, + 0x232dc3, + 0x228503, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x29b3c3, + 0x207783, + 0x220dc3, + 0x2d3684, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x2308c3, + 0x2752c6c5, + 0x142c943, + 0x214a83, + 0x232dc3, + 0x21bb43, + 0x228503, + 0x308003, + 0x221dc4, + 0x2059c3, + 0x2137c3, + 0x23c803, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x2141c3, + 0x2821e9c3, + 0x18ed09, + 0x1242, + 0x3c0743, + 0x28e14a83, + 0x232dc3, + 0x247103, + 0x308003, + 0x223703, + 0x2137c3, + 0x242543, + 0x2f4bc3, + 0x3b9a84, + 0x9a048, + 0x29614a83, + 0x232dc3, + 0x2b0043, + 0x308003, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x22e983, + 0x9a048, + 0x29e14a83, + 0x232dc3, + 0x228503, + 0x203dc3, + 0x242543, + 0x9a048, + 0x142e307, + 0x202703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x139b05, + 0x17e707, + 0x10fe4b, + 0xe4e84, + 0xc0545, + 0x144ca88, + 0x2a54d, + 0x2b231ac5, + 0x647c4, + 0x1242, + 0x3a83, + 0x17e505, + 0x2aec2, + 0x5e42, + 0x303dc5, + 0x9a048, + 0x106c2, + 0x1d2c3, + 0x16454f, + 0x1242, + 0x105646, + 0x2000c2, + 0x202703, + 0x214a83, + 0x308003, + 0x221dc4, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x2aec2, + 0x32a988, + 0x2d3684, + 0x349646, + 0x353986, + 0x9a048, + 0x3373c3, + 0x2cd549, + 0x217915, + 0x1791f, + 0x214a83, + 0xd1ac7, + 0x214892, + 0x169046, + 0x1712c5, + 0x8e0a, + 0x2ac49, + 0x21464f, + 0x2e3504, + 0x224445, + 0x311050, + 0x2137c7, + 0x203dc3, + 0x31bf88, + 0x1283c6, + 0x27cfca, + 0x221c84, + 0x2fdbc3, + 0x233442, + 0x2f850b, + 0x3dc3, + 0x17cc84, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x306403, + 0x201242, + 0x89ac3, + 0x1dee04, + 0x21a3c3, + 0x242543, + 0x2ed73e05, + 0x8346, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a8c3, + 0x223d43, + 0x242543, + 0x2703, + 0x201242, + 0x214a83, + 0x232dc3, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x267c2, + 0x2000c2, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x1805, + 0xf283, + 0x2d3684, + 0x214a83, + 0x232dc3, + 0x306c44, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x1b3089, + 0x29904, + 0x214a83, + 0x2a42, + 0x232dc3, + 0x228503, + 0x206c03, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x2982, + 0x214a83, + 0x232dc3, + 0x308003, + 0x343104, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x207783, + 0x16c2, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x2f3983, + 0x13903, + 0x1a8c3, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x322c0a, + 0x3413c9, + 0x35fb0b, + 0x3602ca, + 0x36860a, + 0x377c8b, + 0x38d74a, + 0x39424a, + 0x39abca, + 0x39ae4b, + 0x3bcfc9, + 0x3ca20a, + 0x3ca58b, + 0x3d818b, + 0x3e040a, + 0x15702, + 0x214a83, + 0x232dc3, + 0x228503, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x1558b, + 0xcf487, + 0x5b788, + 0x177084, + 0x8f308, + 0xe8006, + 0x15546, + 0x366c9, + 0x9a048, + 0x214a83, + 0x8e04, + 0x261484, + 0x202742, + 0x219a04, + 0x269045, + 0x220dc3, + 0x2d3684, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x24d9c4, + 0x2e3504, + 0x221dc4, + 0x2137c3, + 0x21a3c3, + 0x242543, + 0x24f8c5, + 0x2308c3, + 0x2141c3, + 0x32bf03, + 0x23e804, + 0x325d04, + 0x373fc5, + 0x9a048, + 0x203ac4, + 0x3b5cc6, + 0x268c84, + 0x201242, + 0x38f207, + 0x3a25c7, + 0x24b904, + 0x2e92c5, + 0x35ff85, + 0x22d805, + 0x221dc4, + 0x389208, + 0x22b586, + 0x3295c8, + 0x27b905, + 0x2ec0c5, + 0x262044, + 0x242543, + 0x2fe7c4, + 0x376806, + 0x2432c3, + 0x23e804, + 0x3829c5, + 0x344b44, + 0x23acc4, + 0x233442, + 0x231d86, + 0x3aeb46, + 0x313fc5, + 0x2000c2, + 0x202703, + 0x33e01242, + 0x20c504, + 0x200382, + 0x23c803, + 0x215402, + 0x21a3c3, + 0x2003c2, + 0x2fb406, + 0x20e2c3, + 0x207783, + 0x9a048, + 0x9a048, + 0x308003, + 0x1b4103, + 0x2000c2, + 0x34a01242, + 0x308003, + 0x266d43, + 0x2059c3, + 0x227fc4, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x2000c2, + 0x35201242, + 0x214a83, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x682, + 0x209d42, + 0x20c782, + 0x21a8c3, + 0x2f7103, + 0x2000c2, + 0x139b05, + 0x9a048, + 0x17e707, + 0x201242, + 0x232dc3, + 0x24d9c4, + 0x207083, + 0x308003, + 0x206c03, + 0x23c803, + 0x21a3c3, + 0x2125c3, + 0x242543, + 0x233dc3, + 0x12be53, + 0x12e714, + 0x139b05, + 0x17e707, + 0x1d35c9, + 0x10d8c6, + 0xf5ecb, + 0x28886, + 0x54c47, + 0x15aec6, + 0x649, + 0x15794a, + 0x8b70d, + 0x12350c, + 0x116cca, + 0x112988, + 0x97805, + 0x1d3608, + 0x11ec6, + 0x1c6606, + 0x365c6, + 0x602, + 0x2aac82, + 0x174ec4, + 0x9fc86, + 0x12c310, + 0x147498e, + 0x68846, + 0x6264c, + 0x36a6720b, + 0x139b05, + 0x14820b, + 0x36fc6544, + 0x1b3f07, + 0x22111, + 0x1ae28a, + 0x214a83, + 0x3727db88, + 0x656c5, + 0x19b808, + 0xca04, + 0x14a545, + 0x3755ca06, + 0xa7946, + 0xc7746, + 0x908ca, + 0x1b5c43, + 0x37a0dc84, + 0x50849, + 0x129747, + 0x1274ca, + 0x14d8949, + 0x605, + 0xec503, + 0x37e33f07, + 0x1df105, + 0x1538186, + 0x1498886, + 0xb06cc, + 0x101b88, + 0x3803fcc3, + 0xf874b, + 0x13864b, + 0x38647c0c, + 0x140a503, + 0xc2dc8, + 0xf89c5, + 0xc11c9, + 0xea803, + 0x102908, + 0x141dfc6, + 0x86107, + 0x38b5b849, + 0x19d887, + 0xebbca, + 0x39fbf648, + 0x11578d, + 0xa788, + 0xf283, + 0x1443f09, + 0x174483, + 0x28886, + 0xf48c8, + 0x11dc4, + 0x1205c5, + 0x148df83, + 0x239c7, + 0x38e239c3, + 0x393c0a06, + 0x39637f04, + 0x39b0a107, + 0xf48c4, + 0xf48c4, + 0xf48c4, + 0xf48c4, + 0x41, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x2000c2, + 0x201242, + 0x308003, + 0x206182, + 0x21a3c3, + 0x242543, + 0x20e2c3, + 0x3810cf, + 0x38148e, + 0x9a048, + 0x214a83, + 0x43bc7, + 0x232dc3, + 0x308003, + 0x21bc83, + 0x21a3c3, + 0x242543, + 0x68784, + 0x4fc4, + 0x145bc4, + 0x21c9c3, + 0x296747, + 0x203082, + 0x26ce49, + 0x200ac2, + 0x38be4b, + 0x2a1b8a, + 0x2a2889, + 0x200542, + 0x20cdc6, + 0x236a55, + 0x38bf95, + 0x2391d3, + 0x38c513, + 0x2037c2, + 0x2037c5, + 0x2037cc, + 0x27514b, + 0x276205, + 0x204b42, + 0x29d282, + 0x37bb86, + 0x201182, + 0x2c9d46, + 0x20908d, + 0x3dee8c, + 0x379a84, + 0x200882, + 0x202b02, + 0x259808, + 0x200202, + 0x205086, + 0x395a8f, + 0x205090, + 0x3a1544, + 0x236c15, + 0x239353, + 0x24d2c3, + 0x34934a, + 0x214f07, + 0x383d89, + 0x327387, + 0x220f82, + 0x200282, + 0x3beb06, + 0x205fc2, + 0x9a048, + 0x202e82, + 0x201542, + 0x20ac47, + 0x36a6c7, + 0x36a6d1, + 0x2180c5, + 0x2180ce, + 0x218e8f, + 0x20cd42, + 0x2679c7, + 0x21d008, + 0x207682, + 0x21d482, + 0x2101c6, + 0x2101cf, + 0x263710, + 0x22c042, + 0x2086c2, + 0x238c48, + 0x2086c3, + 0x25cec8, + 0x2c1bcd, + 0x215843, + 0x363208, + 0x27fc4f, + 0x28000e, + 0x33c9ca, + 0x2f5211, + 0x2f5690, + 0x300acd, + 0x300e0c, + 0x24a147, + 0x3494c7, + 0x349709, + 0x220f42, + 0x204342, + 0x25678c, + 0x256a8b, + 0x200d42, + 0x2cbec6, + 0x20b682, + 0x200482, + 0x2167c2, + 0x201242, + 0x22d204, + 0x239e07, + 0x22ba02, + 0x23f707, + 0x241247, + 0x22f142, + 0x22ec02, + 0x243a85, + 0x205582, + 0x392dce, + 0x3cae0d, + 0x232dc3, + 0x28508e, + 0x2b794d, + 0x328b03, + 0x2027c2, + 0x21fc84, + 0x24cf02, + 0x222342, + 0x38cdc5, + 0x39d187, + 0x246702, + 0x20dec2, + 0x24d5c7, + 0x250bc8, + 0x22dec2, + 0x277306, + 0x25660c, + 0x25694b, + 0x205dc2, + 0x25db0f, + 0x25ded0, + 0x25e2cf, + 0x25e695, + 0x25ebd4, + 0x25f0ce, + 0x25f44e, + 0x25f7cf, + 0x25fb8e, + 0x25ff14, + 0x260413, + 0x2608cd, + 0x2765c9, + 0x28d003, + 0x207082, + 0x31e805, + 0x3ddc86, + 0x200382, + 0x37f147, + 0x308003, + 0x200642, + 0x361608, + 0x2f5451, + 0x2f5890, + 0x201f02, + 0x28bf47, + 0x204582, + 0x271547, + 0x201e42, + 0x295749, + 0x37bb47, + 0x29ac08, + 0x35c846, + 0x24b083, + 0x24b085, + 0x233042, + 0x2004c2, + 0x3bef05, + 0x39b605, + 0x202482, + 0x21bdc3, + 0x348587, + 0x20e5c7, + 0x201842, + 0x345044, + 0x210543, + 0x31d809, + 0x210548, + 0x202042, + 0x208282, + 0x2ed207, + 0x2f5145, + 0x298bc8, + 0x2ae507, + 0x20fac3, + 0x29fb06, + 0x30094d, + 0x300ccc, + 0x305086, + 0x206782, + 0x2017c2, + 0x209e82, + 0x27facf, + 0x27fece, + 0x360007, + 0x210942, + 0x372385, + 0x372386, + 0x21d542, + 0x200bc2, + 0x28e5c6, + 0x247703, + 0x3c5d46, + 0x2d6705, + 0x2d670d, + 0x2d6f95, + 0x2d7e0c, + 0x2d818d, + 0x2d84d2, + 0x202382, + 0x26c9c2, + 0x202802, + 0x219386, + 0x3c7dc6, + 0x202902, + 0x3ddd06, + 0x206e42, + 0x296f45, + 0x201582, + 0x392f09, + 0x21ae0c, + 0x21b14b, + 0x2003c2, + 0x251d88, + 0x202942, + 0x200a82, + 0x272b46, + 0x2d2c85, + 0x200a87, + 0x227c85, + 0x257145, + 0x215542, + 0x2a3882, + 0x214282, + 0x293a87, + 0x2fb4cd, + 0x2fb84c, + 0x234307, + 0x277282, + 0x205742, + 0x3d2508, + 0x344d48, + 0x3298c8, + 0x3b1104, + 0x33ecc7, + 0x3c2c83, + 0x21b742, + 0x20cb42, + 0x2fc0c9, + 0x228c87, + 0x2141c2, + 0x272f45, + 0x214b42, + 0x20eb42, + 0x2f6e43, + 0x2f6e46, + 0x305fc2, + 0x308c02, + 0x200402, + 0x35c406, + 0x21fbc7, + 0x213fc2, + 0x200902, + 0x25cd0f, + 0x284ecd, + 0x28a98e, + 0x2b77cc, + 0x206842, + 0x206142, + 0x35c685, + 0x320b86, + 0x200b82, + 0x2069c2, + 0x200682, + 0x285244, + 0x2c1a44, + 0x384486, + 0x205142, + 0x27a207, + 0x23d903, + 0x23d908, + 0x23e108, + 0x2d23c7, + 0x24c186, + 0x207842, + 0x20b603, + 0x20b607, + 0x3a6dc6, + 0x2ee0c5, + 0x274608, + 0x2071c2, + 0x3b9447, + 0x26c702, + 0x294ec2, + 0x206382, + 0x205249, + 0x201082, + 0xcb3c8, + 0x203882, + 0x234583, + 0x204847, + 0x203282, + 0x21af8c, + 0x21b28b, + 0x305106, + 0x2ec445, + 0x202c02, + 0x202982, + 0x2c55c6, + 0x216643, + 0x342e87, + 0x291f82, + 0x2008c2, + 0x2368d5, + 0x38c155, + 0x239093, + 0x38c693, + 0x24ee47, + 0x26ee11, + 0x275590, + 0x283712, + 0x2eb111, + 0x29a208, + 0x29a210, + 0x29f38f, + 0x2a1953, + 0x2a2652, + 0x2a7d50, + 0x2b4ecf, + 0x3689d2, + 0x3a1891, + 0x3d4d53, + 0x2b9d52, + 0x2d634f, + 0x2ddd0e, + 0x2e1112, + 0x2e1fd1, + 0x2e5e0f, + 0x2e7c8e, + 0x2efbd1, + 0x2f8ed0, + 0x301d52, + 0x306491, + 0x309b50, + 0x311f8f, + 0x3cea91, + 0x347910, + 0x37b006, + 0x380cc7, + 0x218987, + 0x209f42, + 0x280f85, + 0x310dc7, + 0x20c782, + 0x2018c2, + 0x229e45, + 0x21ec03, + 0x374946, + 0x2fb68d, + 0x2fb9cc, + 0x203642, + 0x20364b, + 0x27500a, + 0x22408a, + 0x2c43c9, + 0x2fa74b, + 0x2ae64d, + 0x3114cc, + 0x35d58a, + 0x244f8c, + 0x27188b, + 0x27604c, + 0x29b68e, + 0x2bf90b, + 0x2b8a0c, + 0x2dc483, + 0x376e46, + 0x3bf642, + 0x304382, + 0x24f4c3, + 0x206482, + 0x20c3c3, + 0x324506, + 0x25e847, + 0x352386, + 0x2e78c8, + 0x348408, + 0x2cf746, + 0x200f02, + 0x31398d, + 0x313ccc, + 0x338807, + 0x316b07, + 0x234a42, + 0x2143c2, + 0x20b582, + 0x27c602, + 0x330496, + 0x335f95, + 0x3395d6, + 0x33ff53, + 0x340612, + 0x355513, + 0x358152, + 0x3acc8f, + 0x3be558, + 0x3bf117, + 0x3bfc59, + 0x3c1898, + 0x3c3c58, + 0x3c5fd7, + 0x3c6b17, + 0x3c8216, + 0x3cc693, + 0x3ccfd5, + 0x3cdd52, + 0x3ce1d3, + 0x201242, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x20e2c3, + 0x2000c2, + 0x201602, + 0x3be933c5, + 0x3c281445, + 0x3c746bc6, + 0x9a048, + 0x3caba385, + 0x201242, + 0x2052c2, + 0x3ce871c5, + 0x3d27e985, + 0x3d680387, + 0x3da806c9, + 0x3de1f844, + 0x200382, + 0x200642, + 0x3e249a05, + 0x3e69d789, + 0x3eb2fb48, + 0x3eeb4985, + 0x3f350107, + 0x3f61d988, + 0x3fb09745, + 0x3fe9e2c6, + 0x403a2709, + 0x406db0c8, + 0x40aca648, + 0x40e9ddca, + 0x412c21c4, + 0x4168e885, + 0x41ac6c08, + 0x41f44945, + 0x20fe82, + 0x42297703, + 0x426aa1c6, + 0x42aaf5c8, + 0x42ef2f86, + 0x4320ad88, + 0x43785546, + 0x43a02c44, + 0x43e08482, + 0x446f4cc7, + 0x44ab0b04, + 0x44e79487, + 0x453cfc87, + 0x2003c2, + 0x456a2c85, + 0x45a13504, + 0x45fa3407, + 0x4623d187, + 0x466830c6, + 0x46a7f445, + 0x46e9d887, + 0x472daf48, + 0x477d0007, + 0x47b41189, + 0x47ed7505, + 0x48331207, + 0x48692a06, + 0x647cb, + 0x48b3aec8, + 0x225bcd, + 0x25d2c9, + 0x27418b, + 0x27c08b, + 0x2b014b, + 0x2f010b, + 0x320d8b, + 0x32104b, + 0x321e89, + 0x322e8b, + 0x32314b, + 0x323c8b, + 0x324e0a, + 0x32534a, + 0x32594c, + 0x32934b, + 0x329aca, + 0x33e6ca, + 0x34b30e, + 0x34d44e, + 0x34d7ca, + 0x34f64a, + 0x350c0b, + 0x350ecb, + 0x3519cb, + 0x36cdcb, + 0x36d3ca, + 0x36e08b, + 0x36e34a, + 0x36e5ca, + 0x36e84a, + 0x38e64b, + 0x39510b, + 0x397c0e, + 0x397f8b, + 0x39e8cb, + 0x39fc0b, + 0x3a3fca, + 0x3a4249, + 0x3a448a, + 0x3a5d8a, + 0x3bdf4b, + 0x3ca84b, + 0x3cb24a, + 0x3cc0cb, + 0x3d520b, + 0x3dfe4b, + 0x48e81788, + 0x4928ae89, + 0x496a5789, + 0x49aed408, + 0x3597c5, + 0x2041c3, + 0x251084, + 0x3015c5, + 0x21f586, + 0x307385, + 0x28a004, + 0x37f048, + 0x31bb05, + 0x294984, + 0x3c7607, + 0x2a4b0a, + 0x38f4ca, + 0x360107, + 0x34c207, + 0x2e6307, + 0x280947, + 0x334605, + 0x3b9b46, + 0x2f2207, + 0x39bc04, + 0x2f9b46, + 0x2f9a46, + 0x3c2d85, + 0x3b6684, + 0x29ee06, + 0x2a3bc7, + 0x34bb86, + 0x3adf47, + 0x251143, + 0x384106, + 0x238e85, + 0x280487, + 0x26a5ca, + 0x356504, + 0x219d88, + 0x31a2c9, + 0x2d4847, + 0x390606, + 0x3c5808, + 0x2f36c9, + 0x383f44, + 0x31eb84, + 0x2dea45, + 0x222b48, + 0x2d4b07, + 0x36c9c9, + 0x34cdc8, + 0x318406, + 0x264a46, + 0x29f988, + 0x36b706, + 0x281445, + 0x283186, + 0x279b88, + 0x27f9c6, + 0x255d8b, + 0x39d746, + 0x2a14cd, + 0x3d0845, + 0x2b09c6, + 0x20c045, + 0x24a789, + 0x370447, + 0x385188, + 0x291386, + 0x2a0689, + 0x3b1306, + 0x26a545, + 0x2a6dc6, + 0x2e5346, + 0x2d9209, + 0x2c0b06, + 0x2a4807, + 0x360b05, + 0x201583, + 0x21b7c5, + 0x34dd07, + 0x288f46, + 0x3d0749, + 0x346bc6, + 0x279686, + 0x20f849, + 0x282b89, + 0x2a8587, + 0x343488, + 0x2a7789, + 0x280c08, + 0x394486, + 0x2e2e85, + 0x2cfd8a, + 0x279706, + 0x33a806, + 0x2dc705, + 0x2523c8, + 0x326447, + 0x22f5ca, + 0x24e1c6, + 0x2e05c5, + 0x309186, + 0x215f87, + 0x3904c7, + 0x21c2c5, + 0x26a705, + 0x263586, + 0x269d46, + 0x26c0c6, + 0x2c70c4, + 0x282109, + 0x28bd06, + 0x30618a, + 0x2211c8, + 0x330f08, + 0x38f4ca, + 0x2af785, + 0x2a3b05, + 0x3c4f48, + 0x2c4f08, + 0x237c47, + 0x3b9d86, + 0x333988, + 0x2108c7, + 0x274848, + 0x2bebc6, + 0x283ec8, + 0x29c606, + 0x27ba87, + 0x3681c6, + 0x29ee06, + 0x2643ca, + 0x305206, + 0x2e2e89, + 0x36f506, + 0x2a5c8a, + 0x202c49, + 0x241706, + 0x2c2844, + 0x31e8cd, + 0x28b107, + 0x3b2a86, + 0x2ca505, + 0x3b1385, + 0x391106, + 0x2a7349, + 0x2bd687, + 0x27ab86, + 0x31db46, + 0x28a089, + 0x281384, + 0x244744, + 0x204088, + 0x356846, + 0x2a6ec8, + 0x318a88, + 0x2883c7, + 0x3c0549, + 0x26c2c7, + 0x2ba24a, + 0x2fcb8f, + 0x2e43ca, + 0x3d9e45, + 0x279dc5, + 0x2173c5, + 0x3c2147, + 0x215b43, + 0x343688, + 0x3de2c6, + 0x3de3c9, + 0x2f2b06, + 0x2d9047, + 0x2a0449, + 0x385088, + 0x2dc7c7, + 0x31f203, + 0x359845, + 0x215ac5, + 0x2c6f0b, + 0x344a04, + 0x23ba44, + 0x277906, + 0x31f3c7, + 0x39168a, + 0x3803c7, + 0x293607, + 0x27e985, + 0x3c8785, + 0x270489, + 0x29ee06, + 0x38024d, + 0x298b05, + 0x2bc683, + 0x226283, + 0x35c505, + 0x334285, + 0x3c5808, + 0x27b4c7, + 0x2444c6, + 0x2a5406, + 0x22a145, + 0x233087, + 0x287ec7, + 0x22b447, + 0x28e90a, + 0x3841c8, + 0x2c70c4, + 0x27f747, + 0x27d6c7, + 0x35e406, + 0x29bc87, + 0x2e9688, + 0x357b08, + 0x370346, + 0x34c448, + 0x2c0b84, + 0x2f2206, + 0x37ff46, + 0x3bbc46, + 0x204506, + 0x2a3044, + 0x280a06, + 0x2c95c6, + 0x29f1c6, + 0x245806, + 0x3d0d46, + 0x2e94c6, + 0x2443c8, + 0x2bb748, + 0x2dfcc8, + 0x307588, + 0x3c4ec6, + 0x206a05, + 0x21b786, + 0x2b4a05, + 0x393907, + 0x29d485, + 0x20d743, + 0x226305, + 0x2ed004, + 0x3d0e85, + 0x202943, + 0x395407, + 0x36c188, + 0x3ae006, + 0x37e88d, + 0x279d86, + 0x29e785, + 0x205243, + 0x2c65c9, + 0x281506, + 0x299486, + 0x292104, + 0x2e4347, + 0x35bf06, + 0x244945, + 0x23a8c3, + 0x206284, + 0x27d886, + 0x35ad44, + 0x26e588, + 0x3c7989, + 0x2bdc09, + 0x2a6cca, + 0x2a914d, + 0x361a87, + 0x3ba086, + 0x2afb04, + 0x2806c9, + 0x285b48, + 0x28ad06, + 0x234e86, + 0x29bc87, + 0x2c74c6, + 0x2261c6, + 0x287346, + 0x3cfd0a, + 0x21d988, + 0x265085, + 0x295e09, + 0x2d528a, + 0x30b048, + 0x2a34c8, + 0x299408, + 0x2b0d0c, + 0x34da05, + 0x2a5688, + 0x2bba46, + 0x372046, + 0x3db607, + 0x3802c5, + 0x283305, + 0x2bdac9, + 0x20d447, + 0x3de385, + 0x2283c7, + 0x226283, + 0x2d5745, + 0x2273c8, + 0x2d6d07, + 0x2a3389, + 0x2e2d45, + 0x380fc4, + 0x2a8e08, + 0x2c1e87, + 0x2dc988, + 0x20d188, + 0x2b1a85, + 0x20c206, + 0x2a5506, + 0x2dee09, + 0x380047, + 0x2b52c6, + 0x3de007, + 0x2027c3, + 0x21f844, + 0x2da0c5, + 0x2331c4, + 0x246744, + 0x389507, + 0x2664c7, + 0x27ad44, + 0x2a31d0, + 0x296007, + 0x3c8785, + 0x30394c, + 0x20cf44, + 0x2b9a08, + 0x27b989, + 0x3bcb46, + 0x302a48, + 0x267884, + 0x277c08, + 0x22fbc6, + 0x264248, + 0x2a4186, + 0x28ba4b, + 0x32b105, + 0x2d9f48, + 0x211b44, + 0x281e8a, + 0x2a3389, + 0x3680c6, + 0x2bbc48, + 0x259345, + 0x2c5bc4, + 0x2b9906, + 0x22b308, + 0x281788, + 0x32dc86, + 0x384404, + 0x2cfd06, + 0x26c347, + 0x279387, + 0x29bc8f, + 0x339e47, + 0x2417c7, + 0x372245, + 0x372ac5, + 0x2a8249, + 0x2ead06, + 0x389745, + 0x282e87, + 0x3db888, + 0x300805, + 0x3681c6, + 0x221008, + 0x2f2f8a, + 0x22b008, + 0x28e347, + 0x2fcfc6, + 0x295dc6, + 0x2003c3, + 0x212503, + 0x2d5449, + 0x2a7609, + 0x2b9806, + 0x2e2d45, + 0x2b0b88, + 0x2bbc48, + 0x36b888, + 0x2873cb, + 0x37eac7, + 0x31bdc9, + 0x29bf08, + 0x34f104, + 0x3bb888, + 0x28fe49, + 0x2b55c5, + 0x3c2047, + 0x21f8c5, + 0x281688, + 0x29324b, + 0x29d5d0, + 0x2b0545, + 0x211a8c, + 0x244685, + 0x27ea03, + 0x2bf706, + 0x2c8b04, + 0x368486, + 0x2a3bc7, + 0x202804, + 0x242808, + 0x34354d, + 0x318845, + 0x2a2cc4, + 0x2ae044, + 0x2b3e49, + 0x2b2308, + 0x32b5c7, + 0x22fc48, + 0x2821c8, + 0x27ae85, + 0x2d0e87, + 0x27ae07, + 0x2cd307, + 0x26a709, + 0x2879c9, + 0x3dfb46, + 0x301006, + 0x282f46, + 0x322605, + 0x3b8a04, + 0x3c4206, + 0x3c7086, + 0x27aec8, + 0x215c4b, + 0x3563c7, + 0x2afb04, + 0x35be46, + 0x2e99c7, + 0x36f805, + 0x2971c5, + 0x2ae204, + 0x287946, + 0x3c4288, + 0x2806c9, + 0x24bb46, + 0x285948, + 0x244a06, + 0x360a48, + 0x321a0c, + 0x27ad46, + 0x29e44d, + 0x29e8cb, + 0x2a48c5, + 0x288007, + 0x2c0c06, + 0x390388, + 0x3dfbc9, + 0x2ee4c8, + 0x3c8785, + 0x39b947, + 0x280d08, + 0x23b4c9, + 0x35bb86, + 0x25138a, + 0x390108, + 0x2ee30b, + 0x21dc0c, + 0x277d08, + 0x27cc06, + 0x2d0888, + 0x2f2c07, + 0x33a409, + 0x35024d, + 0x29ed06, + 0x2250c8, + 0x2bb609, + 0x2c71c8, + 0x283fc8, + 0x2c9ecc, + 0x2cab87, + 0x2cb7c7, + 0x26a545, + 0x2bdf87, + 0x3db748, + 0x2b9986, + 0x24b9cc, + 0x300288, + 0x2db2c8, + 0x307846, + 0x2af0c7, + 0x3dfd44, + 0x307588, + 0x2cf84c, + 0x28538c, + 0x3d9ec5, + 0x3c2e07, + 0x384386, + 0x2af046, + 0x24a948, + 0x21d284, + 0x34bb8b, + 0x27a34b, + 0x2fcfc6, + 0x3433c7, + 0x343ec5, + 0x272605, + 0x34bcc6, + 0x259305, + 0x3449c5, + 0x2d4287, + 0x20e989, + 0x269f04, + 0x25a2c5, + 0x2f6d85, + 0x35aac8, + 0x28d785, + 0x2cf209, + 0x2badc7, + 0x2badcb, + 0x2fbbc6, + 0x244109, + 0x3b65c8, + 0x290185, + 0x2cd408, + 0x287a08, + 0x253047, + 0x2b4247, + 0x389589, + 0x264187, + 0x29d389, + 0x2da70c, + 0x341088, + 0x2c0649, + 0x2c2f87, + 0x282289, + 0x33c3c7, + 0x21dd08, + 0x33a345, + 0x2f2186, + 0x2ca548, + 0x217488, + 0x2d5149, + 0x344a07, + 0x273005, + 0x3c3909, + 0x2f42c6, + 0x292a04, + 0x37b446, + 0x2af448, + 0x320807, + 0x215e48, + 0x34c509, + 0x33be47, + 0x2a4cc6, + 0x2880c4, + 0x226389, + 0x2d0d08, + 0x307707, + 0x367a06, + 0x215b86, + 0x33a784, + 0x34c706, + 0x239f83, + 0x32ac89, + 0x32b0c6, + 0x2a3705, + 0x2a5406, + 0x2d95c5, + 0x281188, + 0x347207, + 0x2306c6, + 0x287206, + 0x330f08, + 0x2a83c7, + 0x29ed45, + 0x2a2fc8, + 0x3aa048, + 0x390108, + 0x244545, + 0x2f2206, + 0x2bd9c9, + 0x2dec84, + 0x2d944b, + 0x225ecb, + 0x264f89, + 0x226283, + 0x257845, + 0x3ae4c6, + 0x246508, + 0x306ec4, + 0x3ae006, + 0x28ea49, + 0x2c93c5, + 0x2d41c6, + 0x2c1e86, + 0x222dc4, + 0x29958a, + 0x2a3648, + 0x217486, + 0x2cd045, + 0x343d47, + 0x3344c7, + 0x20c204, + 0x226107, + 0x2ba244, + 0x34ce46, + 0x210b43, + 0x26a705, + 0x2b6e45, + 0x23ef88, + 0x27f905, + 0x27aa89, + 0x2a9fc7, + 0x3073cb, + 0x2a9fcc, + 0x2aa5ca, + 0x350107, + 0x203d03, + 0x278808, + 0x244705, + 0x300885, + 0x359904, + 0x21dc06, + 0x27b986, + 0x34c747, + 0x23a80b, + 0x2a3044, + 0x355f44, + 0x2d4444, + 0x2d8ec6, + 0x202804, + 0x222c48, + 0x359705, + 0x21c145, + 0x36b7c7, + 0x288109, + 0x334285, + 0x39110a, + 0x3db9c9, + 0x2b174a, + 0x3cfe49, + 0x3545c4, + 0x31dc05, + 0x2c75c8, + 0x3a34cb, + 0x2dea45, + 0x24c386, + 0x241304, + 0x27afc6, + 0x33bcc9, + 0x2e9ac7, + 0x346d88, + 0x2a94c6, + 0x26c2c7, + 0x281788, + 0x377746, + 0x3c72c4, + 0x3817c7, + 0x382e85, + 0x392987, + 0x267784, + 0x2c0b86, + 0x30ad48, + 0x29ea88, + 0x2ff987, + 0x202808, + 0x29c6c5, + 0x226004, + 0x38f3c8, + 0x202904, + 0x217345, + 0x30af44, + 0x2109c7, + 0x28bdc7, + 0x2823c8, + 0x2dcb06, + 0x27f885, + 0x27a888, + 0x246848, + 0x2a6c09, + 0x2261c6, + 0x22f648, + 0x281d0a, + 0x36f888, + 0x309745, + 0x21b986, + 0x2a7208, + 0x39ba0a, + 0x219507, + 0x285f85, + 0x292c08, + 0x270fc4, + 0x252446, + 0x2cbb48, + 0x3d0d46, + 0x334c08, + 0x2d7ac7, + 0x3c7506, + 0x2c2844, + 0x237687, + 0x2bc004, + 0x33bc87, + 0x367e0d, + 0x237cc5, + 0x2d6b0b, + 0x285606, + 0x251e88, + 0x2427c4, + 0x3c50c6, + 0x27d886, + 0x2d0bc7, + 0x29e10d, + 0x304807, + 0x2bc5c8, + 0x284145, + 0x270648, + 0x2d4a86, + 0x29c748, + 0x238606, + 0x3036c7, + 0x282749, + 0x35a587, + 0x28afc8, + 0x34a005, + 0x22a1c8, + 0x2aef85, + 0x228e05, + 0x362b45, + 0x24dec3, + 0x204584, + 0x292e05, + 0x3a2709, + 0x367906, + 0x2e9788, + 0x2c2105, + 0x2bde47, + 0x371bca, + 0x2d4109, + 0x2e524a, + 0x2dfd48, + 0x22820c, + 0x282f0d, + 0x311883, + 0x334b08, + 0x206245, + 0x2f2d46, + 0x384f06, + 0x31e585, + 0x3de109, + 0x33d2c5, + 0x27a888, + 0x258546, + 0x369706, + 0x2a8cc9, + 0x3a9007, + 0x293506, + 0x371b48, + 0x3bbb48, + 0x2ed607, + 0x2c974e, + 0x2d4cc5, + 0x23b3c5, + 0x3d0c48, + 0x271e87, + 0x200e42, + 0x2c9b84, + 0x36838a, + 0x3077c8, + 0x287b46, + 0x2a0588, + 0x2a5506, + 0x288b88, + 0x2b52c8, + 0x228dc4, + 0x2be205, + 0x668c84, + 0x668c84, + 0x668c84, + 0x20aec3, + 0x215a06, + 0x27ad46, + 0x2a458c, + 0x202dc3, + 0x267786, + 0x21a604, + 0x281488, + 0x28e885, + 0x368486, + 0x2c6d08, + 0x2e0e46, + 0x230646, + 0x3c5608, + 0x2da147, + 0x263f49, + 0x3ae60a, + 0x266644, + 0x29d485, + 0x2e4305, + 0x2d7746, + 0x361ac6, + 0x2a50c6, + 0x3dc246, + 0x264084, + 0x26408b, + 0x264a44, + 0x244285, + 0x2b3a45, + 0x288486, + 0x201b48, + 0x282dc7, + 0x32b044, + 0x25b603, + 0x270ac5, + 0x37b307, + 0x282ccb, + 0x23ee87, + 0x2c6c08, + 0x2be347, + 0x26b746, + 0x25d588, + 0x2c51cb, + 0x301506, + 0x212849, + 0x2c5345, + 0x31f203, + 0x2d41c6, + 0x2d79c8, + 0x20c2c3, + 0x24c343, + 0x281786, + 0x2a5506, + 0x3759ca, + 0x27cc45, + 0x27d6cb, + 0x2a534b, + 0x213c03, + 0x20ea43, + 0x2ba1c4, + 0x370587, + 0x277d04, + 0x281484, + 0x2bb8c4, + 0x36fb88, + 0x2ccf88, + 0x214d49, + 0x2d7588, + 0x3b2d07, + 0x245806, + 0x2e93cf, + 0x2d4e06, + 0x2df404, + 0x2ccdca, + 0x37b207, + 0x2bc106, + 0x292a49, + 0x214cc5, + 0x23f0c5, + 0x214e06, + 0x22a303, + 0x271009, + 0x21db06, + 0x34c2c9, + 0x391686, + 0x26a705, + 0x35c905, + 0x204583, + 0x3706c8, + 0x32b787, + 0x3de2c4, + 0x281308, + 0x371dc4, + 0x359006, + 0x2bf706, + 0x23d646, + 0x2d9e09, + 0x300805, + 0x29ee06, + 0x2713c9, + 0x2d3e06, + 0x2e94c6, + 0x3a14c6, + 0x22bd85, + 0x30af46, + 0x3036c4, + 0x33a345, + 0x217484, + 0x2bcf46, + 0x298ac4, + 0x2109c3, + 0x285c05, + 0x233d88, + 0x3572c7, + 0x306f49, + 0x285e88, + 0x29f751, + 0x2c1f0a, + 0x2fcf07, + 0x357e46, + 0x21a604, + 0x2ca648, + 0x2ea008, + 0x29f90a, + 0x2cefcd, + 0x2a6dc6, + 0x3c5706, + 0x237746, + 0x21c147, + 0x2bc685, + 0x286c47, + 0x2813c5, + 0x2baf04, + 0x3c5e46, + 0x224dc7, + 0x270d0d, + 0x2a7147, + 0x37ef48, + 0x27ab89, + 0x21b886, + 0x35bb05, + 0x23c2c4, + 0x2af546, + 0x20c106, + 0x307946, + 0x2a0e08, + 0x21ad83, + 0x2465c3, + 0x349b05, + 0x31ec06, + 0x2b5285, + 0x2a96c8, + 0x2a3d8a, + 0x347344, + 0x281488, + 0x299408, + 0x2882c7, + 0x286589, + 0x2c6908, + 0x280747, + 0x2bbb46, + 0x3d0d4a, + 0x2af5c8, + 0x30c989, + 0x2b23c8, + 0x21ef89, + 0x357d07, + 0x312785, + 0x2a5906, + 0x2b9808, + 0x252008, + 0x224508, + 0x222dc8, + 0x244285, + 0x200d04, + 0x232708, + 0x241084, + 0x3cfc44, + 0x26a705, + 0x2949c7, + 0x287ec9, + 0x2d09c7, + 0x20f8c5, + 0x277b06, + 0x36f1c6, + 0x201c44, + 0x2a9006, + 0x27db04, + 0x291746, + 0x287c86, + 0x212e86, + 0x3c8785, + 0x2a9587, + 0x203d03, + 0x211609, + 0x330d08, + 0x2805c4, + 0x2805cd, + 0x29eb88, + 0x32a608, + 0x30c906, + 0x282849, + 0x2d4109, + 0x33b9c5, + 0x2a3e8a, + 0x291aca, + 0x2b444c, + 0x2b45c6, + 0x278406, + 0x2d5686, + 0x38ce89, + 0x2f2f86, + 0x21dd86, + 0x33d386, + 0x307588, + 0x202806, + 0x2de54b, + 0x294b45, + 0x21c145, + 0x279485, + 0x203e06, + 0x226043, + 0x23d5c6, + 0x2a70c7, + 0x2ca505, + 0x2d1c05, + 0x3b1385, + 0x310686, + 0x32fa44, + 0x32fa46, + 0x2ab289, + 0x203c8c, + 0x2bac48, + 0x22b284, + 0x30ac46, + 0x285706, + 0x2d79c8, + 0x2bbc48, + 0x203b89, + 0x343d47, + 0x356589, + 0x2726c6, + 0x22c144, + 0x2082c4, + 0x27f6c4, + 0x281788, + 0x287d0a, + 0x334206, + 0x3677c7, + 0x392c07, + 0x244205, + 0x36c944, + 0x28fe06, + 0x2bc6c6, + 0x21d2c3, + 0x330b47, + 0x20d088, + 0x33bb0a, + 0x22be48, + 0x20ad88, + 0x298b05, + 0x2a49c5, + 0x3564c5, + 0x2445c6, + 0x247486, + 0x33c885, + 0x32aec9, + 0x36c74c, + 0x2f4ec7, + 0x29f988, + 0x2521c5, + 0x668c84, + 0x265444, + 0x2d6e44, + 0x218706, + 0x2a650e, + 0x23f147, + 0x21c345, + 0x2dec0c, + 0x310b07, + 0x224d47, + 0x226fc9, + 0x219e49, + 0x285f85, + 0x330d08, + 0x2bd9c9, + 0x38ffc5, + 0x2ca448, + 0x2c0886, + 0x38f646, + 0x202c44, + 0x28ee48, + 0x21ba43, + 0x215604, + 0x270b45, + 0x396f07, + 0x2c2605, + 0x281bc9, + 0x2a118d, + 0x2b3046, + 0x3df784, + 0x3b9d08, + 0x20e7ca, + 0x21c847, + 0x367d45, + 0x215643, + 0x2a550e, + 0x3707cc, + 0x30b147, + 0x2a66c7, + 0x443960c7, + 0xaf286, + 0x647c4, + 0x203083, + 0x2f2fc5, + 0x2d6e45, + 0x2a0948, + 0x29dc09, + 0x22b186, + 0x277d04, + 0x2fce46, + 0x331bcb, + 0x2e844c, + 0x24df87, + 0x2de805, + 0x3a9f48, + 0x2ed3c5, + 0x2ccdc7, + 0x2f4cc7, + 0x245fc5, + 0x226043, + 0x20c584, + 0x2e4205, + 0x269e05, + 0x269e06, + 0x2a9dc8, + 0x224dc7, + 0x385206, + 0x33a686, + 0x362a86, + 0x225249, + 0x2d0f87, + 0x250f86, + 0x2e85c6, + 0x276d06, + 0x2b0ac5, + 0x20a586, + 0x39b0c5, + 0x28d808, + 0x29428b, + 0x28fb46, + 0x392c44, + 0x304e49, + 0x2a9fc4, + 0x2c0808, + 0x30e907, + 0x283ec4, + 0x2c5dc8, + 0x2cb5c4, + 0x2b0b04, + 0x274785, + 0x318886, + 0x36fac7, + 0x23db43, + 0x2a4d85, + 0x2fd1c4, + 0x23b406, + 0x33ba48, + 0x202705, + 0x293f49, + 0x350105, + 0x267788, + 0x21a4c7, + 0x32b1c8, + 0x2c5a07, + 0x241889, + 0x280886, + 0x33e906, + 0x2a78c4, + 0x355e85, + 0x31320c, + 0x279487, + 0x279c87, + 0x361708, + 0x2b3046, + 0x2a7004, + 0x34b0c4, + 0x389409, + 0x2d5786, + 0x270507, + 0x2d0804, + 0x326b06, + 0x38a805, + 0x2dc647, + 0x2de4c6, + 0x251249, + 0x2f0387, + 0x29bc87, + 0x2a8b46, + 0x326a45, + 0x27f408, + 0x21d988, + 0x245a06, + 0x202745, + 0x2cca86, + 0x20af03, + 0x2a07c9, + 0x2a4e4e, + 0x2c5748, + 0x371ec8, + 0x24580b, + 0x294186, + 0x385544, + 0x230644, + 0x2a4f4a, + 0x211987, + 0x251045, + 0x212849, + 0x2c9685, + 0x3cfc87, + 0x2305c4, + 0x3c7b07, + 0x318988, + 0x2d4906, + 0x2c0d09, + 0x2c6a0a, + 0x211906, + 0x29e6c6, + 0x2b39c5, + 0x398545, + 0x36ac07, + 0x245608, + 0x38a748, + 0x228dc6, + 0x35c985, + 0x36184e, + 0x2c70c4, + 0x245985, + 0x277489, + 0x2eab08, + 0x28e286, + 0x2a2acc, + 0x2a3990, + 0x2a614f, + 0x2a8148, + 0x350107, + 0x3c8785, + 0x292e05, + 0x36f949, + 0x292e09, + 0x2cfe06, + 0x2deac7, + 0x355d85, + 0x237c49, + 0x35e486, + 0x2f2dcd, + 0x27f589, + 0x281484, + 0x2c54c8, + 0x2327c9, + 0x3343c6, + 0x278a05, + 0x33e906, + 0x346c49, + 0x2d0688, + 0x206a05, + 0x281e04, + 0x2a2c8b, + 0x334285, + 0x246586, + 0x283246, + 0x3b4246, + 0x2875cb, + 0x294049, + 0x33a5c5, + 0x393807, + 0x2c1e86, + 0x231f46, + 0x281a88, + 0x224f09, + 0x37ed0c, + 0x37b108, + 0x31aac6, + 0x32dc83, + 0x22f306, + 0x241745, + 0x27e208, + 0x3d9d46, + 0x2dc888, + 0x380445, + 0x291805, + 0x21a608, + 0x3bba07, + 0x384e47, + 0x34c747, + 0x302a48, + 0x2d7848, + 0x2e9f06, + 0x2bcd87, + 0x21f707, + 0x2b3f4a, + 0x2168c3, + 0x203e06, + 0x22b3c5, + 0x213504, + 0x27ab89, + 0x241804, + 0x204844, + 0x2a4204, + 0x2a66cb, + 0x32b6c7, + 0x310645, + 0x29c3c8, + 0x277b06, + 0x277b08, + 0x27cb86, + 0x28ed85, + 0x28f045, + 0x290746, + 0x292408, + 0x292988, + 0x27ad46, + 0x29c20f, + 0x2a0290, + 0x3d0845, + 0x203d03, + 0x22c205, + 0x31bd08, + 0x292d09, + 0x390108, + 0x2de8c8, + 0x235288, + 0x32b787, + 0x2777c9, + 0x2dca88, + 0x291004, + 0x2a4088, + 0x35ab89, + 0x2bd387, + 0x34de44, + 0x2d0a88, + 0x2a934a, + 0x2fd446, + 0x2a6dc6, + 0x226089, + 0x2a3bc7, + 0x2d9c88, + 0x21fd08, + 0x33ad48, + 0x24ef85, + 0x3d3205, + 0x21c145, + 0x2d6e05, + 0x2bb447, + 0x226045, + 0x2ca505, + 0x3dde06, + 0x390047, + 0x3a3407, + 0x2a9646, + 0x2e0285, + 0x246586, + 0x241985, + 0x2c4d88, + 0x355d04, + 0x2d3e86, + 0x324604, + 0x2c5bc8, + 0x318c0a, + 0x27b4cc, + 0x23aa05, + 0x21c206, + 0x37eec6, + 0x202586, + 0x31ab44, + 0x3b9a05, + 0x27c447, + 0x2a3c49, + 0x2d9307, + 0x668c84, + 0x668c84, + 0x32b545, + 0x2dda04, + 0x2a204a, + 0x277986, + 0x2bd7c4, + 0x3c2d85, + 0x3bd405, + 0x2bc5c4, + 0x282e87, + 0x3c3a87, + 0x2d8ec8, + 0x26d5c8, + 0x206a09, + 0x372488, + 0x2a220b, + 0x2acc44, + 0x232045, + 0x3897c5, + 0x34c6c9, + 0x224f09, + 0x304d48, + 0x34cc48, + 0x288484, + 0x285745, + 0x2041c3, + 0x2d7705, + 0x29ee86, + 0x29da4c, + 0x20c006, + 0x278906, + 0x28e505, + 0x310708, + 0x2e86c6, + 0x357fc6, + 0x2a6dc6, + 0x22bbcc, + 0x389884, + 0x362bca, + 0x28e448, + 0x29d887, + 0x2fd0c6, + 0x22b247, + 0x2fca45, + 0x367a06, + 0x35ee86, + 0x372987, + 0x2c6704, + 0x210ac5, + 0x277484, + 0x2baf87, + 0x2776c8, + 0x27828a, + 0x280b87, + 0x2aa847, + 0x350087, + 0x2ed509, + 0x29da4a, + 0x22c103, + 0x357285, + 0x212ec3, + 0x2bb909, + 0x2d7c08, + 0x372247, + 0x390209, + 0x21da86, + 0x339f88, + 0x395385, + 0x24694a, + 0x343809, + 0x370209, + 0x3db607, + 0x2ea109, + 0x212d88, + 0x288d86, + 0x21c3c8, + 0x2d1f47, + 0x264187, + 0x3db9c7, + 0x2daf48, + 0x30aac6, + 0x2a9105, + 0x27c447, + 0x29e1c8, + 0x362a04, + 0x306044, + 0x293407, + 0x2b5647, + 0x2bd84a, + 0x288d06, + 0x32eeca, + 0x2c9ac7, + 0x2c6e87, + 0x210b84, + 0x29d444, + 0x2dc546, + 0x35c184, + 0x35c18c, + 0x30e845, + 0x2172c9, + 0x2ef004, + 0x2bc685, + 0x20e748, + 0x292a45, + 0x391106, + 0x292f44, + 0x2acb4a, + 0x2ef646, + 0x255fca, + 0x3d0007, + 0x215f85, + 0x22a305, + 0x24424a, + 0x292585, + 0x2a6cc6, + 0x241084, + 0x2ba346, + 0x36acc5, + 0x3d9e06, + 0x2ff98c, + 0x2e18ca, + 0x291bc4, + 0x245806, + 0x2a3bc7, + 0x2de444, + 0x307588, + 0x24c286, + 0x392a89, + 0x2c8349, + 0x341189, + 0x2d9606, + 0x2d2046, + 0x21c507, + 0x32ae08, + 0x2d1e49, + 0x32b6c7, + 0x29c546, + 0x26c347, + 0x237605, + 0x2c70c4, + 0x21c0c7, + 0x21f8c5, + 0x28a2c5, + 0x200cc7, + 0x245e88, + 0x3a9ec6, + 0x29f00d, + 0x2a0b4f, + 0x2a534d, + 0x202d84, + 0x233e86, + 0x2e1c88, + 0x33d345, + 0x2b4108, + 0x252f0a, + 0x281484, + 0x331e06, + 0x2abe07, + 0x2b7d47, + 0x2da209, + 0x21c385, + 0x2bc5c4, + 0x2be14a, + 0x2c64c9, + 0x2ea207, + 0x30b706, + 0x3343c6, + 0x285686, + 0x381886, + 0x2e158f, + 0x2e1b49, + 0x202806, + 0x389046, + 0x297e89, + 0x2bce87, + 0x2146c3, + 0x22bd46, + 0x212503, + 0x31e448, + 0x26c187, + 0x2a8349, + 0x2bf588, + 0x384f88, + 0x33c506, + 0x20bf49, + 0x2f4e05, + 0x22f244, + 0x312847, + 0x38cf05, + 0x202d84, + 0x361b48, + 0x211c44, + 0x2bcbc7, + 0x36c106, + 0x263645, + 0x2b23c8, + 0x33428b, + 0x331207, + 0x2444c6, + 0x2d4e84, + 0x3854c6, + 0x26a705, + 0x21f8c5, + 0x27f189, + 0x282a89, + 0x2641c4, + 0x264205, + 0x245845, + 0x2467c6, + 0x330e08, + 0x2c8e86, + 0x20cecb, + 0x3bc9ca, + 0x2c5b05, + 0x28f0c6, + 0x23eb85, + 0x24a285, + 0x292647, + 0x204088, + 0x292484, + 0x37fb46, + 0x292a06, + 0x212f47, + 0x31f1c4, + 0x27d886, + 0x3c2245, + 0x3c2249, + 0x2d2244, + 0x36cac9, + 0x27ad46, + 0x2cac48, + 0x245845, + 0x392d05, + 0x3d9e06, + 0x37ec09, + 0x219e49, + 0x278986, + 0x2eac08, + 0x2a12c8, + 0x23eb44, + 0x2be9c4, + 0x2be9c8, + 0x3b2b88, + 0x356689, + 0x29ee06, + 0x2a6dc6, + 0x33384d, + 0x3ae006, + 0x3218c9, + 0x268945, + 0x214e06, + 0x33aec8, + 0x32f985, + 0x21f744, + 0x26a705, + 0x2825c8, + 0x2a1e09, + 0x277544, + 0x2c0b86, + 0x30cb4a, + 0x30b048, + 0x2bd9c9, + 0x26ad4a, + 0x390186, + 0x2a0d08, + 0x2ccb85, + 0x2f0988, + 0x2fcac5, + 0x21d949, + 0x336449, + 0x20c642, + 0x2c5345, + 0x272346, + 0x27ac87, + 0x213505, + 0x3469c6, + 0x316908, + 0x2b3046, + 0x2c7489, + 0x279d86, + 0x281908, + 0x278d45, + 0x38e4c6, + 0x3037c8, + 0x281788, + 0x357c08, + 0x318488, + 0x20a584, + 0x20c243, + 0x2c76c4, + 0x280d86, + 0x237644, + 0x371e07, + 0x357ec9, + 0x2d4445, + 0x21fd06, + 0x22bd46, + 0x2a9c0b, + 0x2bc046, + 0x298d46, + 0x2d3f88, + 0x264a46, + 0x215d83, + 0x208503, + 0x2c70c4, + 0x22f545, + 0x244847, + 0x2776c8, + 0x2776cf, + 0x27c34b, + 0x330c08, + 0x2c0c06, + 0x330f0e, + 0x23b443, + 0x2447c4, + 0x2bbfc5, + 0x2bc446, + 0x28ff0b, + 0x294a86, + 0x221089, + 0x263645, + 0x23da88, + 0x3d29c8, + 0x219d0c, + 0x2a6706, + 0x2d7746, + 0x2e2d45, + 0x28ad88, + 0x27b4c5, + 0x34f108, + 0x2a2e4a, + 0x2a5789, + 0x668c84, + 0x2000c2, + 0x4a201242, + 0x200382, + 0x221dc4, + 0x209e82, + 0x306c44, + 0x208482, + 0x3dc3, + 0x2003c2, + 0x2090c2, + 0x9a048, + 0x29904, + 0x214a83, + 0x232dc3, + 0x308003, + 0xccc2, + 0x49582, + 0x23c803, + 0x21a3c3, + 0x242543, + 0xc782, + 0xc2c2, + 0x1b82, + 0x202703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x241f83, + 0x2d3684, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x2e3504, + 0x308003, + 0x2137c7, + 0x23c803, + 0x203dc3, + 0x31bf88, + 0x242543, + 0x27cfcb, + 0x2fdbc3, + 0x2431c6, + 0x233442, + 0x2f850b, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x242543, + 0x21a103, + 0x208a03, + 0x2000c2, + 0x9a048, + 0x399c45, + 0x21f948, + 0x2e3648, + 0x201242, + 0x343045, + 0x3c8847, + 0x203c42, + 0x242a07, + 0x200382, + 0x2555c7, + 0x3742c9, + 0x26d188, + 0x33abc9, + 0x20b342, + 0x3c7387, + 0x22dd84, + 0x3c8907, + 0x3bc8c7, + 0x25ac42, + 0x23c803, + 0x202382, + 0x208482, + 0x2003c2, + 0x214282, + 0x200902, + 0x2090c2, + 0x2df885, + 0x210205, + 0x1242, + 0x32dc3, + 0x214a83, + 0x232dc3, + 0x29a643, + 0x308003, + 0x206c03, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0xa983, + 0x101, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x214903, + 0x4d4ae8c6, + 0x239c3, + 0xd50c5, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x1b02, + 0x9a048, + 0x12a4c3, + 0x3dc3, + 0x1b4103, + 0x455c4, + 0x14226c4, + 0xed7c5, + 0x2000c2, + 0x393bc4, + 0x214a83, + 0x232dc3, + 0x308003, + 0x231a43, + 0x22d805, + 0x21bc83, + 0x21a8c3, + 0x21a3c3, + 0x24e283, + 0x242543, + 0x20e2c3, + 0x266603, + 0x207783, + 0x5c2, + 0x2aec2, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x2000c2, + 0x202703, + 0x201242, + 0x2a42, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x2090c2, + 0x9a048, + 0x308003, + 0x1b4103, + 0x9a048, + 0x1b4103, + 0x26f6c3, + 0x214a83, + 0x22fe44, + 0x232dc3, + 0x308003, + 0x206182, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x206182, + 0x2137c3, + 0x21a3c3, + 0x242543, + 0x2f7103, + 0x20e2c3, + 0x2000c2, + 0x201242, + 0x308003, + 0x21a3c3, + 0x242543, + 0x2431c5, + 0x14fc86, + 0x2d3684, + 0x233442, + 0x882, + 0x9a048, + 0x2a42, + 0x49582, + 0x2982, + 0x2000c2, + 0x139b05, + 0x1ce08, + 0x991c3, + 0x201242, + 0x3c604, + 0x51c6c486, + 0x8d04, + 0x10fe4b, + 0x34ac6, + 0xd1407, + 0x12eb09, + 0x232dc3, + 0x48248, + 0x4824b, + 0x486cb, + 0x48d4b, + 0x4908b, + 0x4934b, + 0x4978b, + 0x1d2f06, + 0x308003, + 0xf3605, + 0x68a44, + 0x210983, + 0x1182c7, + 0xe6d44, + 0x6cbc4, + 0x21a3c3, + 0x78a86, + 0x5684, + 0x1b4103, + 0x242543, + 0x2fe7c4, + 0x12bcc7, + 0x14f889, + 0x10fc08, + 0x1b44c4, + 0x1c8a44, + 0x365c6, + 0xa788, + 0x16a605, + 0x8649, + 0x2fb03, + 0x139b05, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x203dc3, + 0x242543, + 0x2fdbc3, + 0x233442, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21bac3, + 0x219a04, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x2e3504, + 0x308003, + 0x21a3c3, + 0x242543, + 0x2431c6, + 0x232dc3, + 0x308003, + 0x10e83, + 0x1b4103, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x139b05, + 0xd1407, + 0x3103, + 0x2fb03, + 0x9a048, + 0x308003, + 0x214a83, + 0x232dc3, + 0x308003, + 0x5cf43, + 0x21a3c3, + 0x242543, + 0x55214a83, + 0x232dc3, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x2000c2, + 0x201242, + 0x214a83, + 0x308003, + 0x21a3c3, + 0x2003c2, + 0x242543, + 0x336987, + 0x2cd68b, + 0x20dcc3, + 0x2cfac8, + 0x32ab87, + 0x3de706, + 0x218c05, + 0x343189, + 0x242f48, + 0x3359c9, + 0x3359d0, + 0x37ab8b, + 0x2e7589, + 0x203103, + 0x2f8bc9, + 0x231506, + 0x23150c, + 0x335bc8, + 0x3db448, + 0x374789, + 0x2c368e, + 0x37408b, + 0x2ba58c, + 0x220dc3, + 0x28c68c, + 0x3d8f49, + 0x23bb47, + 0x232d0c, + 0x2b858a, + 0x24c0c4, + 0x2ee78d, + 0x28c548, + 0x3ba7cd, + 0x3a6cc6, + 0x2d368b, + 0x34fa09, + 0x3892c7, + 0x295946, + 0x267b49, + 0x33b64a, + 0x30c108, + 0x2fd7c4, + 0x2b5a07, + 0x3c51c7, + 0x204684, + 0x223804, + 0x201fc9, + 0x286ac9, + 0x3d9ac8, + 0x398bc5, + 0x20b285, + 0x2068c6, + 0x2ee649, + 0x25318d, + 0x24c488, + 0x2067c7, + 0x218c88, + 0x2355c6, + 0x239c04, + 0x284405, + 0x3cfb46, + 0x3d1e84, + 0x3d8e47, + 0x3e094a, + 0x20d384, + 0x211846, + 0x2124c9, + 0x2124cf, + 0x212a8d, + 0x213306, + 0x21ca10, + 0x21ce06, + 0x21df07, + 0x21e987, + 0x21e98f, + 0x21f1c9, + 0x225986, + 0x227207, + 0x227208, + 0x2275c9, + 0x3ba588, + 0x305c87, + 0x20ed43, + 0x3d87c6, + 0x29d1c8, + 0x2c394a, + 0x215849, + 0x243083, + 0x342f46, + 0x37f98a, + 0x2f9f87, + 0x23b98a, + 0x31458e, + 0x21f306, + 0x338547, + 0x238886, + 0x2435c6, + 0x3d300b, + 0x39964a, + 0x2cdccd, + 0x2d2107, + 0x266688, + 0x266689, + 0x26668f, + 0x3070cc, + 0x34b789, + 0x27e48e, + 0x2138ca, + 0x216406, + 0x2f4806, + 0x3adc8c, + 0x31fdcc, + 0x320308, + 0x35a487, + 0x235185, + 0x3c8ac4, + 0x28918e, + 0x3a6744, + 0x201247, + 0x39dcca, + 0x3ab1d4, + 0x3d548f, + 0x21eb48, + 0x3d8688, + 0x378c8d, + 0x378c8e, + 0x22cd09, + 0x22e548, + 0x22e54f, + 0x232a0c, + 0x232a0f, + 0x233bc7, + 0x23714a, + 0x3087cb, + 0x239808, + 0x23b107, + 0x25c7cd, + 0x3620c6, + 0x2ee946, + 0x23d449, + 0x22ba08, + 0x2433c8, + 0x2433ce, + 0x2b7687, + 0x3043c5, + 0x245385, + 0x202404, + 0x3de9c6, + 0x3d99c8, + 0x296d83, + 0x2e710e, + 0x25cb88, + 0x2aae8b, + 0x26f887, + 0x228c05, + 0x273506, + 0x2b2b07, + 0x31b348, + 0x36a409, + 0x3cd545, + 0x285c48, + 0x2209c6, + 0x3a618a, + 0x289089, + 0x232dc9, + 0x232dcb, + 0x25d908, + 0x204549, + 0x398c86, + 0x3c5a8a, + 0x2bfe4a, + 0x23734c, + 0x3488c7, + 0x26cf8a, + 0x3b1fcb, + 0x3b1fd9, + 0x324208, + 0x243245, + 0x25c986, + 0x2a0049, + 0x39f606, + 0x219aca, + 0x26e286, + 0x2196c4, + 0x2d604d, + 0x3458c7, + 0x2196c9, + 0x247105, + 0x247ac8, + 0x248009, + 0x24b904, + 0x24bfc7, + 0x24bfc8, + 0x24cc87, + 0x265c08, + 0x250dc7, + 0x2d8b85, + 0x257e8c, + 0x258349, + 0x33144a, + 0x3a8e89, + 0x2f8cc9, + 0x388e0c, + 0x25b4cb, + 0x25c008, + 0x25d0c8, + 0x260cc4, + 0x283b88, + 0x284d09, + 0x2b8647, + 0x212706, + 0x2a43c7, + 0x29fd49, + 0x24768b, + 0x36aa87, + 0x2947c7, + 0x3d0147, + 0x3ba744, + 0x3ba745, + 0x2e3205, + 0x358b4b, + 0x33d684, + 0x323a88, + 0x30060a, + 0x220a87, + 0x3caac7, + 0x28f6d2, + 0x291646, + 0x22f7c6, + 0x28870e, + 0x29ab46, + 0x299288, + 0x29a60f, + 0x3bab88, + 0x28a808, + 0x2dd1ca, + 0x2dd1d1, + 0x2a98ce, + 0x25514a, + 0x25514c, + 0x22e747, + 0x22e750, + 0x3c7108, + 0x2a9ac5, + 0x2b2e0a, + 0x3d1ecc, + 0x29c88d, + 0x3c7c86, + 0x3c7c87, + 0x3c7c8c, + 0x3d2b8c, + 0x21bc8c, + 0x3bd6cb, + 0x38b644, + 0x226204, + 0x2b6f89, + 0x34b147, + 0x37d009, + 0x2bfc89, + 0x2b8247, + 0x2b8406, + 0x2b8409, + 0x2b8803, + 0x2b314a, + 0x2961c7, + 0x3c8e0b, + 0x2cdb4a, + 0x22de04, + 0x32f4c6, + 0x280e09, + 0x35c004, + 0x2df48a, + 0x2e0685, + 0x2c7945, + 0x2c794d, + 0x2c7c8e, + 0x2c7805, + 0x335046, + 0x242dc7, + 0x22b78a, + 0x3a6a46, + 0x37bc84, + 0x3cdb87, + 0x2fab0b, + 0x265907, + 0x262944, + 0x3a39c6, + 0x3a39cd, + 0x2e568c, + 0x21a286, + 0x24c68a, + 0x34ca86, + 0x21e648, + 0x30c487, + 0x2d3b8a, + 0x23c486, + 0x27d903, + 0x2f3886, + 0x29d048, + 0x245aca, + 0x2dcc07, + 0x2dcc08, + 0x249ac4, + 0x28fc47, + 0x2f4348, + 0x291848, + 0x2bbdc8, + 0x2ffc0a, + 0x2ec0c5, + 0x2c1ac7, + 0x254f93, + 0x26b2c6, + 0x24aec8, + 0x221589, + 0x2428c8, + 0x33c58b, + 0x385308, + 0x2c02c4, + 0x21a706, + 0x320c06, + 0x3186c9, + 0x2d39c7, + 0x257f88, + 0x2a51c6, + 0x200bc4, + 0x208405, + 0x3a3188, + 0x344e4a, + 0x2d5cc8, + 0x2dad46, + 0x2a0f0a, + 0x269f88, + 0x2de248, + 0x2df708, + 0x2dff46, + 0x2e1e86, + 0x3a4d0c, + 0x2e2410, + 0x2cc145, + 0x2230c8, + 0x2230d0, + 0x3ba990, + 0x33584e, + 0x3a498e, + 0x3a4994, + 0x3a804f, + 0x3a8406, + 0x3dbe51, + 0x345213, + 0x345688, + 0x2035c5, + 0x2d0008, + 0x3a05c5, + 0x33f34c, + 0x229f09, + 0x3a6589, + 0x356947, + 0x26c649, + 0x39f1c7, + 0x334686, + 0x284207, + 0x204c05, + 0x20a9c3, + 0x210e83, + 0x213404, + 0x36adcd, + 0x3c304f, + 0x200c05, + 0x33f246, + 0x20cb87, + 0x399a87, + 0x208886, + 0x20888b, + 0x2aa785, + 0x259fc6, + 0x30be47, + 0x251ac9, + 0x229b46, + 0x3860c5, + 0x3c910b, + 0x3d6e86, + 0x21d685, + 0x241588, + 0x290b08, + 0x299b8c, + 0x299b90, + 0x2ac2c9, + 0x2c15c7, + 0x2b918b, + 0x2c8206, + 0x305b4a, + 0x36ff8b, + 0x31b58a, + 0x398806, + 0x2f6fc5, + 0x32aa86, + 0x279f48, + 0x356a0a, + 0x37891c, + 0x2fdc8c, + 0x2fdf88, + 0x2431c5, + 0x382747, + 0x24a006, + 0x24aac5, + 0x2177c6, + 0x208a48, + 0x2c6747, + 0x2c3588, + 0x26b38a, + 0x3b954c, + 0x297009, + 0x3b97c7, + 0x285244, + 0x245446, + 0x28a38a, + 0x2bfd85, + 0x22348c, + 0x223b48, + 0x26a208, + 0x2aebcc, + 0x38878c, + 0x22d949, + 0x22db87, + 0x25494c, + 0x3082c4, + 0x3713ca, + 0x30de8c, + 0x24fdcb, + 0x25044b, + 0x252b06, + 0x256447, + 0x22e987, + 0x22e98f, + 0x30f351, + 0x2e8d92, + 0x258c0d, + 0x258c0e, + 0x258f4e, + 0x3a8208, + 0x3a8212, + 0x25be08, + 0x221bc7, + 0x24ec0a, + 0x2ac988, + 0x29ab05, + 0x2bb28a, + 0x21d187, + 0x2ef184, + 0x210883, + 0x236085, + 0x2dd447, + 0x30d3c7, + 0x29ca8e, + 0x352e8d, + 0x354009, + 0x302905, + 0x361043, + 0x34a886, + 0x25a5c5, + 0x2ab0c8, + 0x224249, + 0x25c9c5, + 0x25c9cf, + 0x2e0b07, + 0x218a85, + 0x27024a, + 0x3d0b06, + 0x312b09, + 0x381b4c, + 0x3ce889, + 0x2062c6, + 0x30040c, + 0x32dd86, + 0x30cfc8, + 0x3b1ec6, + 0x365486, + 0x2bc1c4, + 0x31d203, + 0x21124a, + 0x227e11, + 0x34b94a, + 0x23ea05, + 0x25b907, + 0x2559c7, + 0x2e6f04, + 0x2f444b, + 0x33aa48, + 0x2c55c6, + 0x361785, + 0x261f44, + 0x3828c9, + 0x2008c4, + 0x20e087, + 0x37a385, + 0x37a387, + 0x288945, + 0x3801c3, + 0x221a88, + 0x2d020a, + 0x23db43, + 0x399c8a, + 0x2a74c6, + 0x25c74f, + 0x2b7609, + 0x2e7090, + 0x305748, + 0x2db3c9, + 0x29df47, + 0x3a394f, + 0x3905c4, + 0x2e3584, + 0x203946, + 0x2344c6, + 0x2ef40a, + 0x254686, + 0x2b5e07, + 0x315048, + 0x315247, + 0x3166c7, + 0x31784a, + 0x316fcb, + 0x33bf85, + 0x2e89c8, + 0x201343, + 0x3bb3cc, + 0x3965cf, + 0x234f8d, + 0x258787, + 0x354149, + 0x357087, + 0x2401c8, + 0x3ab3cc, + 0x2c01c8, + 0x23e708, + 0x32c9ce, + 0x341b94, + 0x3420a4, + 0x36080a, + 0x37b90b, + 0x39f284, + 0x39f289, + 0x331e88, + 0x245d85, + 0x29688a, + 0x291087, + 0x2135c4, + 0x202703, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x23c803, + 0x2e2406, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x2000c2, + 0x202703, + 0x201242, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x308003, + 0x21bc83, + 0x2e2406, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x228503, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2000c2, + 0x27ee03, + 0x201242, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x2086c2, + 0x215702, + 0x201242, + 0x214a83, + 0x208c02, + 0x2005c2, + 0x221dc4, + 0x306c44, + 0x223f82, + 0x219a04, + 0x2003c2, + 0x242543, + 0x2141c3, + 0x252b06, + 0x20c782, + 0x201b82, + 0x2221c2, + 0x57a07403, + 0x57e2e743, + 0x56246, + 0x56246, + 0x2d3684, + 0x203dc3, + 0x160d, + 0x1d984a, + 0x16300c, + 0x1d76cc, + 0xd4ecd, + 0x139b05, + 0x86209, + 0x8d2cc, + 0x29907, + 0xdb86, + 0x13dc8, + 0x1bf87, + 0x201c8, + 0x1ac0ca, + 0x10d707, + 0x58a8d505, + 0xe4f09, + 0x58c3480b, + 0x125c08, + 0x1558b, + 0x12c5c8, + 0x1c48c9, + 0x4060a, + 0x1b1b8e, + 0x1d158d, + 0x2cd0d, + 0x14426cb, + 0xe554a, + 0x8d04, + 0x5a106, + 0x19b808, + 0x79108, + 0x25687, + 0x1d35c5, + 0xc607, + 0x33249, + 0x15c087, + 0x106c8, + 0x26a89, + 0x4ce04, + 0x4e945, + 0x98e8e, + 0x12c207, + 0x59225a86, + 0x78d8d, + 0xd1288, + 0x59694f86, + 0x5a094f88, + 0x56f88, + 0x136b90, + 0x53f8c, + 0x61b47, + 0x62347, + 0x6a947, + 0x72047, + 0x6882, + 0x120687, + 0x19980c, + 0x13c945, + 0x107c07, + 0xac186, + 0xacdc9, + 0xaff88, + 0x6502, + 0x5c2, + 0x18d986, + 0x1b9ecb, + 0x1ba1c6, + 0x174d04, + 0x978c7, + 0x41a89, + 0xf0c09, + 0x1b1148, + 0x49582, + 0x193a49, + 0xd788, + 0xef24a, + 0x15adc9, + 0x1b4186, + 0xd8949, + 0xe54c7, + 0xe5c09, + 0xe7ac8, + 0xea3c7, + 0xec049, + 0xf0005, + 0xf1210, + 0x1b6786, + 0x97805, + 0x91487, + 0xec74d, + 0x41485, + 0xf8ac6, + 0xf92c7, + 0xfe7d8, + 0xd1608, + 0x13db8a, + 0xca42, + 0x5020a, + 0x60e4d, + 0x45c2, + 0xce946, + 0x11ec6, + 0xa1788, + 0xafd0a, + 0x472c8, + 0x6de89, + 0x115488, + 0x6eace, + 0x6e0c8, + 0x14a887, + 0x5a694ec4, + 0xae8cd, + 0x10a085, + 0x69148, + 0x34088, + 0x111b86, + 0xc2c2, + 0xc53c4, + 0xe2c06, + 0x365c6, + 0x5a8ef74b, + 0x1442, + 0x401, + 0x81, + 0xb8f08, + 0x5bc87, + 0x150503, + 0x59a37f04, + 0x59e9b383, + 0xc1, + 0xf586, + 0xc1, + 0x201, + 0xf586, + 0x150503, + 0x66603, + 0x647c4, + 0x1e7c7, + 0x7787, + 0x15c27c5, + 0x4e684, + 0x13d707, + 0x1242, + 0x24c0c4, + 0x214a83, + 0x24d9c4, + 0x221dc4, + 0x21a3c3, + 0x221445, + 0x214903, + 0x22b983, + 0x208805, + 0x207783, + 0x1243, + 0x5ba14a83, + 0x232dc3, + 0x4d9c4, + 0x7083, + 0x308003, + 0x200181, + 0x1a8c3, + 0x23c803, + 0x306c44, + 0x219a04, + 0x21a3c3, + 0x4e283, + 0x242543, + 0x20e2c3, + 0x9a048, + 0x2000c2, + 0x202703, + 0x201242, + 0x214a83, + 0x232dc3, + 0x228503, + 0x2005c2, + 0x221dc4, + 0x21bc83, + 0x23c803, + 0x21a3c3, + 0x203dc3, + 0x242543, + 0x207783, + 0x196504, + 0x9a048, + 0x106947, + 0x1242, + 0x1a3105, + 0x540cf, + 0xe0986, + 0x144ca88, + 0x1160ce, + 0x5ca345c2, + 0x297ac8, + 0x35c5c6, + 0x24e806, + 0x395e87, + 0x5ce00c82, + 0x5d2b7488, + 0x20bd4a, + 0x2615c8, + 0x200ac2, + 0x3c8c49, + 0x33bfc7, + 0x212686, + 0x2217c9, + 0x2c1c04, + 0x3c8b46, + 0x2cc7c4, + 0x20e904, + 0x257889, + 0x30dbc6, + 0x265445, + 0x266245, + 0x22d547, + 0x2dbd87, + 0x34c8c4, + 0x31e606, + 0x2ff485, + 0x210845, + 0x23eac5, + 0x3bd9c7, + 0x26f6c5, + 0x248489, + 0x343fc5, + 0x31b484, + 0x3a6987, + 0x36344e, + 0x2031c9, + 0x2885c9, + 0x348706, + 0x23f9c8, + 0x36f2cb, + 0x2a5a0c, + 0x322686, + 0x2ba447, + 0x2eee85, + 0x3270ca, + 0x3d9bc9, + 0x345c89, + 0x295146, + 0x30bc05, + 0x245705, + 0x36a209, + 0x23ec4b, + 0x2c2246, + 0x352686, + 0x2067c4, + 0x2ecd46, + 0x304448, + 0x3c1e46, + 0x2e3e06, + 0x3dd908, + 0x2019c7, + 0x201d49, + 0x205a85, + 0x9a048, + 0x3cd4c4, + 0x316c44, + 0x20b105, + 0x3403c9, + 0x220747, + 0x22074b, + 0x22284a, + 0x228585, + 0x5d60c282, + 0x2cda07, + 0x5da29cc8, + 0x295387, + 0x301345, + 0x348aca, + 0x1242, + 0x27c58b, + 0x27d98a, + 0x248906, + 0x20a803, + 0x206c8d, + 0x3c4c4c, + 0x3c534d, + 0x230585, + 0x27bbc5, + 0x296dc7, + 0x3d1149, + 0x20bc46, + 0x254505, + 0x37b708, + 0x2ce983, + 0x2e3948, + 0x2ecc48, + 0x383fc7, + 0x3b8a88, + 0x3c0809, + 0x2fd2c7, + 0x2cd207, + 0x3de588, + 0x23ae04, + 0x23ae07, + 0x3a6bc8, + 0x360f06, + 0x3c0ecf, + 0x22a907, + 0x31e106, + 0x22dcc5, + 0x222343, + 0x246287, + 0x387fc3, + 0x24d046, + 0x24e586, + 0x24f0c6, + 0x293d45, + 0x265c03, + 0x3936c8, + 0x38a109, + 0x39bf8b, + 0x24f248, + 0x250a85, + 0x252305, + 0x5de2dec2, + 0x2842c9, + 0x221e47, + 0x25a045, + 0x257787, + 0x258ac6, + 0x381745, + 0x25a40b, + 0x25c004, + 0x261185, + 0x2612c7, + 0x276806, + 0x276c45, + 0x283d87, + 0x2847c7, + 0x2a7484, + 0x28d0ca, + 0x28dbc8, + 0x2ccc09, + 0x23f285, + 0x205886, + 0x30460a, + 0x266146, + 0x2ed087, + 0x26d30d, + 0x2aa2c9, + 0x391c45, + 0x363847, + 0x289708, + 0x303588, + 0x3286c7, + 0x384d06, + 0x21abc7, + 0x24dbc3, + 0x30db44, + 0x37d485, + 0x3a7747, + 0x3b0d49, + 0x229588, + 0x2ecf85, + 0x2425c4, + 0x247ec5, + 0x24f40d, + 0x200cc2, + 0x2bca46, + 0x2eaf06, + 0x308cca, + 0x39a786, + 0x3a3345, + 0x26d6c5, + 0x26d6c7, + 0x3a5fcc, + 0x256e0a, + 0x28f246, + 0x2e1d85, + 0x2ecb86, + 0x28f507, + 0x291246, + 0x293c4c, + 0x221909, + 0x5e20fa07, + 0x29a9c5, + 0x29a9c6, + 0x29ae08, + 0x2c4005, + 0x2aab45, + 0x2ab848, + 0x2aba4a, + 0x5e67b8c2, + 0x5ea09e42, + 0x355fc5, + 0x237643, + 0x326008, + 0x228703, + 0x2abcc4, + 0x312c4b, + 0x36f688, + 0x2b9648, + 0x5ef03cc9, + 0x2b1009, + 0x2b19c6, + 0x2b2788, + 0x2b2989, + 0x2b3806, + 0x2b3985, + 0x246c06, + 0x2b4749, + 0x2c8947, + 0x38e386, + 0x20af47, + 0x345fc7, + 0x207584, + 0x5f2d1909, + 0x24ad08, + 0x2b7388, + 0x2257c7, + 0x2d5946, + 0x3d0f49, + 0x24e7c7, + 0x24a58a, + 0x32ed08, + 0x3bb707, + 0x3d0606, + 0x2f0e0a, + 0x23df48, + 0x2ea985, + 0x227b85, + 0x3cbc87, + 0x3190c9, + 0x31cf0b, + 0x351f08, + 0x344049, + 0x24fb47, + 0x2c2bcc, + 0x2c3bcc, + 0x2c3eca, + 0x2c414c, + 0x2cc348, + 0x2cc548, + 0x2cc744, + 0x2ce109, + 0x2ce349, + 0x2ce58a, + 0x2ce809, + 0x2ceb87, + 0x3bec0c, + 0x3d2406, + 0x26ccc8, + 0x266206, + 0x38fe86, + 0x391b47, + 0x3a1088, + 0x3debcb, + 0x295247, + 0x257549, + 0x25ba49, + 0x2844c7, + 0x2cca04, + 0x200fc7, + 0x2f0806, + 0x20e486, + 0x24c845, + 0x2f7d48, + 0x26c544, + 0x26c546, + 0x256ccb, + 0x2b3449, + 0x235686, + 0x2e4009, + 0x20b1c6, + 0x345048, + 0x210543, + 0x30bd85, + 0x21a9c9, + 0x21c7c5, + 0x30e1c4, + 0x275d46, + 0x235a05, + 0x254306, + 0x319a07, + 0x247946, + 0x22c2cb, + 0x3c5987, + 0x3a28c6, + 0x2730c6, + 0x22d606, + 0x34c889, + 0x3b604a, + 0x2c58c5, + 0x3d6f8d, + 0x2abb46, + 0x23c346, + 0x2e6f86, + 0x21e5c5, + 0x2f1507, + 0x228ec7, + 0x27390e, + 0x23c803, + 0x2d5909, + 0x297289, + 0x22d287, + 0x26bbc7, + 0x2919c5, + 0x367b05, + 0x5f60210f, + 0x2db607, + 0x2db7c8, + 0x2dbb84, + 0x2dc046, + 0x5fa45402, + 0x2e01c6, + 0x2e2406, + 0x29744e, + 0x2e378a, + 0x207106, + 0x2b7c0a, + 0x3c7709, + 0x2fbe85, + 0x2ee188, + 0x3cbb46, + 0x2b7188, + 0x202ac8, + 0x277fcb, + 0x395f85, + 0x26f748, + 0x3dda4c, + 0x301207, + 0x24eb46, + 0x30c2c8, + 0x3de888, + 0x5fe30a42, + 0x21504b, + 0x205c89, + 0x28d989, + 0x21c647, + 0x3b5dc8, + 0x603d32c8, + 0x20934b, + 0x349bc9, + 0x25b18d, + 0x202908, + 0x2f1008, + 0x60604042, + 0x20d5c4, + 0x60a2aec2, + 0x3cd9c6, + 0x60e01282, + 0x2fbc8a, + 0x2a3806, + 0x34bd48, + 0x3c6908, + 0x3d9746, + 0x2ba946, + 0x3054c6, + 0x2ab045, + 0x239e44, + 0x6122ae04, + 0x359946, + 0x276247, + 0x6160d8c7, + 0x278b4b, + 0x295589, + 0x27bc0a, + 0x26d804, + 0x2f3b08, + 0x38e14d, + 0x2fc409, + 0x2fc648, + 0x2fc8c9, + 0x2fe7c4, + 0x2aae04, + 0x38d205, + 0x346f0b, + 0x36f606, + 0x359785, + 0x236209, + 0x31e6c8, + 0x22af84, + 0x327249, + 0x24a345, + 0x2dbdc8, + 0x2cd8c7, + 0x2889c8, + 0x281006, + 0x3ba447, + 0x2e6b09, + 0x3c9289, + 0x21d705, + 0x3682c5, + 0x61a1e342, + 0x31b244, + 0x21fe85, + 0x395d86, + 0x346905, + 0x244b07, + 0x359a45, + 0x276844, + 0x3487c6, + 0x254587, + 0x238f46, + 0x30a945, + 0x217108, + 0x35c7c5, + 0x21a847, + 0x2277c9, + 0x2b358a, + 0x264cc7, + 0x264ccc, + 0x265406, + 0x2423c9, + 0x31f045, + 0x369188, + 0x211ec3, + 0x398c45, + 0x3b9285, + 0x27b207, + 0x61e08dc2, + 0x2f8087, + 0x2eea86, + 0x38dc46, + 0x2f6146, + 0x3de7c6, + 0x230988, + 0x2d0145, + 0x31e1c7, + 0x31e1cd, + 0x210883, + 0x3d28c5, + 0x270007, + 0x2f83c8, + 0x26fbc5, + 0x214408, + 0x37cf06, + 0x2e50c7, + 0x2d4605, + 0x396006, + 0x393c45, + 0x20ba0a, + 0x310586, + 0x2645c7, + 0x2c9485, + 0x3a8a87, + 0x3cdb04, + 0x30e146, + 0x3cba85, + 0x39a18b, + 0x2f0689, + 0x27ef0a, + 0x21d788, + 0x314248, + 0x31968c, + 0x31adc7, + 0x330a08, + 0x335d88, + 0x3382c5, + 0x358dca, + 0x361049, + 0x62203242, + 0x2945c6, + 0x25c9c4, + 0x2fa949, + 0x35d749, + 0x2451c7, + 0x29b947, + 0x2bfb09, + 0x2ffe08, + 0x2ffe0f, + 0x21b5c6, + 0x2e4bcb, + 0x259dc5, + 0x259dc7, + 0x37bd49, + 0x20c8c6, + 0x3271c7, + 0x2e9105, + 0x230484, + 0x2f5006, + 0x220904, + 0x2f9c47, + 0x321c88, + 0x6270bb08, + 0x30c645, + 0x30c787, + 0x324389, + 0x20d184, + 0x241048, + 0x62bd0448, + 0x2e6f04, + 0x31d648, + 0x295a04, + 0x3b6349, + 0x21e505, + 0x62e33442, + 0x21b605, + 0x2dd945, + 0x289548, + 0x233a07, + 0x632008c2, + 0x22af45, + 0x2de0c6, + 0x243906, + 0x31b208, + 0x338fc8, + 0x3468c6, + 0x34afc6, + 0x306a09, + 0x38db86, + 0x20c78b, + 0x3c2705, + 0x2ac8c6, + 0x3c4a88, + 0x33f6c6, + 0x224786, + 0x216bca, + 0x2df94a, + 0x248a45, + 0x30ce07, + 0x274586, + 0x63603642, + 0x270147, + 0x33c305, + 0x304584, + 0x304585, + 0x2f3a06, + 0x272c47, + 0x203945, + 0x2dfac4, + 0x352248, + 0x224845, + 0x37ae87, + 0x3ca445, + 0x20b945, + 0x2d2904, + 0x2d2909, + 0x2ff2c8, + 0x23a5c6, + 0x35aa06, + 0x302d06, + 0x63bd5b08, + 0x311d07, + 0x31234d, + 0x312f0c, + 0x313509, + 0x313749, + 0x63f75442, + 0x3d4a03, + 0x2010c3, + 0x2f08c5, + 0x3a784a, + 0x338e86, + 0x23cec5, + 0x31a504, + 0x31a50b, + 0x32d64c, + 0x32df0c, + 0x32e215, + 0x32f70d, + 0x33208f, + 0x332452, + 0x3328cf, + 0x332c92, + 0x333113, + 0x3335cd, + 0x333b8d, + 0x333f0e, + 0x33480e, + 0x334e0c, + 0x3351cc, + 0x33560b, + 0x33668e, + 0x336f92, + 0x338c4c, + 0x3391d0, + 0x34cfd2, + 0x34e08c, + 0x34e74d, + 0x34ea8c, + 0x351591, + 0x35280d, + 0x3546cd, + 0x354cca, + 0x354f4c, + 0x35890c, + 0x35948c, + 0x359e8c, + 0x35df93, + 0x35e710, + 0x35eb10, + 0x35f10d, + 0x35f70c, + 0x360549, + 0x36224d, + 0x362593, + 0x364111, + 0x364913, + 0x36560f, + 0x3659cc, + 0x365ccf, + 0x36608d, + 0x36668f, + 0x366a50, + 0x3674ce, + 0x36b40e, + 0x36ba90, + 0x36d08d, + 0x36da0e, + 0x36dd8c, + 0x36ed53, + 0x37268e, + 0x372c10, + 0x373011, + 0x37344f, + 0x373813, + 0x374fcd, + 0x37530f, + 0x3756ce, + 0x375c50, + 0x376049, + 0x3773d0, + 0x3778cf, + 0x377f4f, + 0x378312, + 0x3792ce, + 0x37a00d, + 0x37a54d, + 0x37a88d, + 0x37bf8d, + 0x37c2cd, + 0x37c610, + 0x37ca0b, + 0x37d24c, + 0x37d5cc, + 0x37dbcc, + 0x37dece, + 0x38d350, + 0x38f7d2, + 0x38fc4b, + 0x39078e, + 0x390b0e, + 0x39138e, + 0x39190b, + 0x64391d96, + 0x39268d, + 0x393214, + 0x393f0d, + 0x3955d5, + 0x3978cd, + 0x39824f, + 0x398e0f, + 0x39c24f, + 0x39c60e, + 0x39c98d, + 0x39e251, + 0x3a084c, + 0x3a0b4c, + 0x3a0e4b, + 0x3a128c, + 0x3a1ccf, + 0x3a2092, + 0x3a2bcd, + 0x3a470c, + 0x3a500c, + 0x3a530d, + 0x3a564f, + 0x3a5a0e, + 0x3a750c, + 0x3a7acd, + 0x3a7e0b, + 0x3a8c4c, + 0x3a954d, + 0x3a988e, + 0x3a9c09, + 0x3abb53, + 0x3ac94d, + 0x3ad04d, + 0x3ad64c, + 0x3ae88e, + 0x3aef8f, + 0x3af34c, + 0x3af64d, + 0x3af98f, + 0x3afd4c, + 0x3b034c, + 0x3b080c, + 0x3b0b0c, + 0x3b35cd, + 0x3b3912, + 0x3b45cc, + 0x3b48cc, + 0x3b4bd1, + 0x3b500f, + 0x3b53cf, + 0x3b5793, + 0x3b6f8e, + 0x3b730f, + 0x3b76cc, + 0x647b7d8e, + 0x3b810f, + 0x3b84d6, + 0x3bae52, + 0x3bcccc, + 0x3bdb8f, + 0x3be20d, + 0x3c94cf, + 0x3c988c, + 0x3c9b8d, + 0x3c9ecd, + 0x3cb4ce, + 0x3cc38c, + 0x3ceecc, + 0x3cf1d0, + 0x3d3d91, + 0x3d41cb, + 0x3d460c, + 0x3d490e, + 0x3d6011, + 0x3d644e, + 0x3d67cd, + 0x3dbc0b, + 0x3dc88f, + 0x3dd454, + 0x23c782, + 0x23c782, + 0x23e083, + 0x23c782, + 0x23e083, + 0x23c782, + 0x203802, + 0x246c45, + 0x3d5d0c, + 0x23c782, + 0x23c782, + 0x203802, + 0x23c782, + 0x29b485, + 0x2b3585, + 0x23c782, + 0x23c782, + 0x201542, + 0x29b485, + 0x32fec9, + 0x363e0c, + 0x23c782, + 0x23c782, + 0x23c782, + 0x23c782, + 0x246c45, + 0x23c782, + 0x23c782, + 0x23c782, + 0x23c782, + 0x201542, + 0x32fec9, + 0x23c782, + 0x23c782, + 0x23c782, + 0x2b3585, + 0x23c782, + 0x2b3585, + 0x363e0c, + 0x3d5d0c, + 0x202703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x1d904f, + 0x145988, + 0x1a704, + 0x3dc3, + 0x86808, + 0x1cc203, + 0x2000c2, + 0x65601242, + 0x240983, + 0x224c84, + 0x207083, + 0x384584, + 0x22f7c6, + 0x310c83, + 0x310c44, + 0x2f0b05, + 0x23c803, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x21e2ca, + 0x252b06, + 0x390e8c, + 0x9a048, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x2137c3, + 0x2e2406, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x2fb03, + 0xac508, + 0x661d2145, + 0x47d47, + 0x139b05, + 0x156c9, + 0x1742, + 0x13a14a, + 0x66fa0505, + 0x139b05, + 0x29907, + 0x6dfc8, + 0x9c4e, + 0x8b392, + 0x9630b, + 0x10d806, + 0x6728d505, + 0x6768d50c, + 0x13d547, + 0x17e707, + 0x12364a, + 0x3be50, + 0x146145, + 0x10fe4b, + 0x79108, + 0x25687, + 0x2490b, + 0x33249, + 0x46e07, + 0x15c087, + 0xc2487, + 0x34a06, + 0x106c8, + 0x67c28886, + 0x47207, + 0x18ec46, + 0x78d8d, + 0xf3c90, + 0x680aac82, + 0xd1288, + 0x40350, + 0x17f5cc, + 0x687825cd, + 0x5a988, + 0x5ae0b, + 0x6b187, + 0x70749, + 0x56306, + 0x9b008, + 0x3ee42, + 0x9218a, + 0x157647, + 0x107c07, + 0xacdc9, + 0xaff88, + 0xf3605, + 0x18d986, + 0x1ba1c6, + 0xfd84e, + 0xaf88e, + 0x3874f, + 0x41a89, + 0xf0c09, + 0x91d0b, + 0xb3b4f, + 0xbd08c, + 0xca18b, + 0x131388, + 0x171887, + 0x197088, + 0xb580b, + 0xb5bcc, + 0xb5fcc, + 0xb63cc, + 0xb66cd, + 0x1b1148, + 0x52e82, + 0x193a49, + 0x112988, + 0x19fe8b, + 0xd5b46, + 0xdda8b, + 0x136acb, + 0xe884a, + 0xea585, + 0xf1210, + 0xf5c86, + 0x184806, + 0x97805, + 0x91487, + 0xe0448, + 0xf92c7, + 0xf9587, + 0x12c807, + 0xc7346, + 0x1cd80a, + 0x99eca, + 0x11ec6, + 0xb130d, + 0x472c8, + 0x115488, + 0x115cc9, + 0xc0545, + 0x1aec8c, + 0xb68cb, + 0x86fc9, + 0x1ccb44, + 0x111949, + 0x111b86, + 0x4cec6, + 0x3c686, + 0x1b82, + 0x365c6, + 0x13dacb, + 0x129187, + 0x11ac47, + 0x1442, + 0xd7445, + 0x27e04, + 0x101, + 0x4fd83, + 0x67a37806, + 0x9b383, + 0x382, + 0x26bc4, + 0xac2, + 0xd3684, + 0x882, + 0x31c2, + 0x16c2, + 0x20f82, + 0x86c2, + 0x8d502, + 0xd42, + 0x167c2, + 0x373c2, + 0x5582, + 0x2a42, + 0x4e782, + 0x32dc3, + 0x942, + 0x3c42, + 0xdec2, + 0x5dc2, + 0x642, + 0x315c2, + 0x6502, + 0x5bc2, + 0xf42, + 0x5c2, + 0x1bc83, + 0x4582, + 0x7882, + 0x49582, + 0x1e42, + 0x2042, + 0x8282, + 0x23502, + 0x17c2, + 0x9e82, + 0x3f82, + 0x6c9c2, + 0x15402, + 0x1a3c3, + 0x602, + 0x30a42, + 0x2902, + 0x1ad42, + 0x1d685, + 0xa882, + 0x14b42, + 0x3d383, + 0x682, + 0xca42, + 0x45c2, + 0x7842, + 0x2f82, + 0x8c2, + 0xc2c2, + 0x1b82, + 0x1805, + 0x68a03802, + 0x68edf283, + 0xf283, + 0x69203802, + 0xf283, + 0x74c47, + 0x201503, + 0x2000c2, + 0x214a83, + 0x232dc3, + 0x228503, + 0x2005c3, + 0x2137c3, + 0x21a3c3, + 0x203dc3, + 0x242543, + 0x29b3c3, + 0xc0584, + 0x19405, + 0x104305, + 0x3a83, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x228503, + 0x23c803, + 0x21a3c3, + 0x203dc3, + 0x1b4103, + 0x242543, + 0x214a83, + 0x232dc3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x200181, + 0x23c803, + 0x21a3c3, + 0x24e283, + 0x242543, + 0x69944, + 0x202703, + 0x214a83, + 0x232dc3, + 0x218bc3, + 0x228503, + 0x2c26c3, + 0x208943, + 0x2a37c3, + 0x216243, + 0x308003, + 0x221dc4, + 0x21a3c3, + 0x242543, + 0x207783, + 0x204244, + 0x24f603, + 0x20dc3, + 0x29cfc3, + 0x328fc8, + 0x2f0e44, + 0x20020a, + 0x235406, + 0x124184, + 0x3a71c7, + 0x21ec8a, + 0x21b489, + 0x3bb287, + 0x3c024a, + 0x202703, + 0x35604b, + 0x216189, + 0x2f4245, + 0x3b0647, + 0x1242, + 0x214a83, + 0x20fcc7, + 0x263bc5, + 0x2cc8c9, + 0x232dc3, + 0x373ec6, + 0x2cb983, + 0xeeb03, + 0x118f86, + 0x98186, + 0x1d3bc7, + 0x212286, + 0x220fc5, + 0x205b47, + 0x316507, + 0x6bf08003, + 0x34e2c7, + 0x23c783, + 0x3d3905, + 0x221dc4, + 0x26f3c8, + 0x385acc, + 0x2b8d05, + 0x2aa446, + 0x20fb87, + 0x3b9887, + 0x3a2a07, + 0x248b48, + 0x317ccf, + 0x21b6c5, + 0x240a87, + 0x28e747, + 0x276e0a, + 0x37b549, + 0x3dd185, + 0x3212ca, + 0xc4ac6, + 0xc0a07, + 0x2cba05, + 0x2f6684, + 0x3d9686, + 0x101406, + 0x37f847, + 0x252d87, + 0x33b388, + 0x218405, + 0x263ac6, + 0x156ec8, + 0x2e3d85, + 0xe3f46, + 0x3268c5, + 0x28ce44, + 0x24a407, + 0x2307ca, + 0x23ab88, + 0x288e06, + 0x137c3, + 0x2ec0c5, + 0x320506, + 0x3bee46, + 0x297706, + 0x23c803, + 0x3a2e47, + 0x28e6c5, + 0x21a3c3, + 0x2e8b0d, + 0x203dc3, + 0x33b488, + 0x213484, + 0x276b05, + 0x2abd06, + 0x205406, + 0x2ac7c7, + 0x25b047, + 0x350ac5, + 0x242543, + 0x271d87, + 0x371989, + 0x2708c9, + 0x384a4a, + 0x215542, + 0x3d38c4, + 0x2fb304, + 0x2f7c07, + 0x2f7f48, + 0x2fa3c9, + 0x3d2789, + 0x2fadc7, + 0x109049, + 0x362f06, + 0xfd5c6, + 0x2fe7c4, + 0x22cf8a, + 0x302448, + 0x305389, + 0x305946, + 0x2bc745, + 0x23aa48, + 0x2d5dca, + 0x32bf03, + 0x2043c6, + 0x2faec7, + 0x35a785, + 0x3b4045, + 0x2432c3, + 0x23e804, + 0x227b45, + 0x2848c7, + 0x2ff405, + 0x2ff846, + 0x111e85, + 0x2071c3, + 0x2071c9, + 0x2768cc, + 0x2c61cc, + 0x3444c8, + 0x2ab3c7, + 0x30d588, + 0x10e747, + 0x30eaca, + 0x30f18b, + 0x2162c8, + 0x205508, + 0x22b686, + 0x302bc5, + 0x25d70a, + 0x2df2c5, + 0x233442, + 0x2d44c7, + 0x253c46, + 0x376785, + 0x310949, + 0x2d0405, + 0x372185, + 0x3c2409, + 0x320446, + 0x201348, + 0x3d39c3, + 0x20aa46, + 0x275c86, + 0x31cd05, + 0x31cd09, + 0x2c4709, + 0x25d487, + 0x11cb84, + 0x31cb87, + 0x3d2689, + 0x21ee85, + 0x39f48, + 0x349845, + 0x353885, + 0x39b489, + 0x204b42, + 0x357204, + 0x209282, + 0x204582, + 0x2ed985, + 0x323f08, + 0x2c0485, + 0x2ced43, + 0x2ced45, + 0x2e03c3, + 0x20a742, + 0x2b4384, + 0x269f03, + 0x200a82, + 0x3b17c4, + 0x309703, + 0x20cb42, + 0x2c0503, + 0x211e44, + 0x305ac3, + 0x255544, + 0x205142, + 0x2140c3, + 0x21ab03, + 0x2071c2, + 0x294ec2, + 0x2c4549, + 0x205b02, + 0x28bec4, + 0x206542, + 0x23a8c4, + 0x362ec4, + 0x3b4384, + 0x201b82, + 0x22b2c2, + 0x22db03, + 0x29cec3, + 0x3269c4, + 0x3aa684, + 0x2dae84, + 0x2ea884, + 0x31bcc3, + 0x312743, + 0x2c4a44, + 0x31f184, + 0x31f2c6, + 0x21d642, + 0x1242, + 0x41483, + 0x201242, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x6c05, + 0x2000c2, + 0x202703, + 0x214a83, + 0x232dc3, + 0x209b03, + 0x308003, + 0x221dc4, + 0x2c4804, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x2fedc4, + 0x297a83, + 0x2ad843, + 0x37a2c4, + 0x349646, + 0x210603, + 0x139b05, + 0x17e707, + 0x2d2c43, + 0x6da46f08, + 0x2532c3, + 0x2bb143, + 0x25cc03, + 0x2137c3, + 0x3c0ac5, + 0x1b0603, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x20a883, + 0x22ee03, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21bc83, + 0x21a3c3, + 0x2801c4, + 0x1b4103, + 0x242543, + 0x24a004, + 0x139b05, + 0x2c8f85, + 0x17e707, + 0x201242, + 0x2052c2, + 0x200382, + 0x208482, + 0x3dc3, + 0x2003c2, + 0x4f04, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x20e2c3, + 0x2d3684, + 0x9a048, + 0x214a83, + 0x203dc3, + 0x3a83, + 0x122504, + 0x24c0c4, + 0x9a048, + 0x214a83, + 0x24d9c4, + 0x221dc4, + 0x203dc3, + 0x204042, + 0x1b4103, + 0x242543, + 0x22b983, + 0x3e804, + 0x208805, + 0x233442, + 0x325e43, + 0x68b49, + 0xe5986, + 0x149948, + 0x2000c2, + 0x9a048, + 0x201242, + 0x232dc3, + 0x308003, + 0x2005c2, + 0x3dc3, + 0x242543, + 0x7c42, + 0x82, + 0xc2, + 0x1c0407, + 0x142c09, + 0x7aec3, + 0x9a048, + 0x20f43, + 0x713233c7, + 0x14a83, + 0x944c8, + 0x32dc3, + 0x108003, + 0x1ab9c6, + 0x1bc83, + 0x92788, + 0xcae48, + 0xcff06, + 0x3c803, + 0xd8cc8, + 0x44b83, + 0x714eb886, + 0xf1c05, + 0x32fc7, + 0x1a3c3, + 0x11003, + 0x42543, + 0xeb02, + 0x17cd0a, + 0x2cc3, + 0xeda43, + 0x10a104, + 0x117acb, + 0x118088, + 0x90602, + 0x14540c7, + 0x15636c7, + 0x14cee08, + 0x14cf583, + 0x143acb, + 0xb342, + 0x12bcc7, + 0x11b504, + 0x2000c2, + 0x201242, + 0x235b44, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x2137c3, + 0x21a3c3, + 0x242543, + 0x215d43, + 0x20e2c3, + 0x2fb03, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x602, + 0x3a83, + 0x108003, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x2137c3, + 0x21a3c3, + 0x242543, + 0x20c782, + 0x2000c1, + 0x2000c2, + 0x200201, + 0x332182, + 0x9a048, + 0x21ca05, + 0x200101, + 0x14a83, + 0x2fe44, + 0x201301, + 0x200501, + 0x205dc1, + 0x246bc2, + 0x387fc4, + 0x246bc3, + 0x200041, + 0x200801, + 0x200181, + 0x200701, + 0x302fc7, + 0x30e38f, + 0x3ccc06, + 0x2004c1, + 0x322546, + 0x200bc1, + 0x200581, + 0x3affce, + 0x2003c1, + 0x242543, + 0x200a81, + 0x34c105, + 0x20eb02, + 0x2431c5, + 0x200401, + 0x200741, + 0x2007c1, + 0x233442, + 0x200081, + 0x201341, + 0x204f01, + 0x201b41, + 0x201441, + 0x50849, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x214903, + 0x214a83, + 0x308003, + 0x90548, + 0x23c803, + 0x21a3c3, + 0x7283, + 0x242543, + 0x14f62c8, + 0x1e0603, + 0xa788, + 0x139b05, + 0x9a048, + 0x3dc3, + 0x139b05, + 0xcd184, + 0xd1488, + 0x455c4, + 0xcf487, + 0xd3b05, + 0x50849, + 0x11d287, + 0x14f62ca, + 0x9a048, + 0x1b4103, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x220dc3, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x2e3504, + 0x242543, + 0x24f8c5, + 0x2d0204, + 0x214a83, + 0x232dc3, + 0x308003, + 0x209e82, + 0x21a3c3, + 0x242543, + 0xe2c3, + 0xac60a, + 0xe8006, + 0x102804, + 0x122046, + 0x202703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x21a3c3, + 0x242543, + 0x201242, + 0x214a83, + 0x2303c9, + 0x232dc3, + 0x2aa909, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x78a84, + 0x3dc3, + 0x242543, + 0x2fe5c8, + 0x23c207, + 0x208805, + 0xdbc48, + 0x1d4408, + 0x1c0407, + 0xf81ca, + 0x6f98b, + 0x122787, + 0x3f888, + 0xd174a, + 0xf648, + 0x142c09, + 0x27a07, + 0x1fa87, + 0x3ec8, + 0x944c8, + 0x40d4f, + 0x3ad45, + 0x947c7, + 0x1ab9c6, + 0x3cd87, + 0x1dd2c6, + 0x92788, + 0x99786, + 0x1147, + 0x2fc9, + 0x18ab07, + 0x179dc9, + 0xc2749, + 0xc8d06, + 0xcae48, + 0xdbf05, + 0x7b74a, + 0xd8cc8, + 0x44b83, + 0xe07c8, + 0x32fc7, + 0x95d05, + 0x51590, + 0x11003, + 0x1b4103, + 0x2e47, + 0x1acc5, + 0xf9888, + 0x66605, + 0xeda43, + 0x1cb7c8, + 0xee06, + 0x32109, + 0xb2b87, + 0x68e0b, + 0x6cc44, + 0x111444, + 0x117acb, + 0x118088, + 0x118e87, + 0x139b05, + 0x214a83, + 0x232dc3, + 0x228503, + 0x242543, + 0x23e343, + 0x308003, + 0x1b4103, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x91e4b, + 0x2000c2, + 0x201242, + 0x242543, + 0xd42, + 0x9e82, + 0x7782, + 0x9a048, + 0x1b3089, + 0x1242, + 0x2000c2, + 0x201242, + 0x200382, + 0x2005c2, + 0x210942, + 0x21a3c3, + 0x13f246, + 0x2003c2, + 0x3e804, + 0x2000c2, + 0x202703, + 0x201242, + 0x214a83, + 0x232dc3, + 0x200382, + 0x308003, + 0x21bc83, + 0x23c803, + 0x219a04, + 0x21a3c3, + 0x2125c3, + 0x3dc3, + 0x242543, + 0x30a104, + 0x207783, + 0x308003, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x203dc3, + 0x242543, + 0x3bd187, + 0x214a83, + 0x27b0c7, + 0x397206, + 0x216c83, + 0x21bb43, + 0x308003, + 0x206c03, + 0x221dc4, + 0x28a404, + 0x3383c6, + 0x213a43, + 0x21a3c3, + 0x242543, + 0x24f8c5, + 0x2af384, + 0x323b43, + 0x2ce043, + 0x2d44c7, + 0x2cd845, + 0x68703, + 0x214a83, + 0x232dc3, + 0x308003, + 0x23c803, + 0x21a3c3, + 0x6e544, + 0x242543, + 0x14583, + 0x7c30988c, + 0x53547, + 0xe4846, + 0x91487, + 0x67f05, + 0x202b02, + 0x247403, + 0x214f03, + 0x202703, + 0x7ce14a83, + 0x208c02, + 0x232dc3, + 0x207083, + 0x308003, + 0x221dc4, + 0x2059c3, + 0x21b6c3, + 0x23c803, + 0x219a04, + 0x7d20ce02, + 0x21a3c3, + 0x242543, + 0x2308c3, + 0x21bd03, + 0x21a443, + 0x20c782, + 0x207783, + 0x9a048, + 0x308003, + 0x3a83, + 0x2135c4, + 0x202703, + 0x201242, + 0x214a83, + 0x235b44, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x3473c4, + 0x306c44, + 0x2e2406, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x253c46, + 0x34c8b, + 0x28886, + 0xec90a, + 0x11b94a, + 0x9a048, + 0x2136c4, + 0x7e614a83, + 0x2026c4, + 0x232dc3, + 0x270744, + 0x308003, + 0x2f3983, + 0x23c803, + 0x21a3c3, + 0x1b4103, + 0x242543, + 0x4cbc3, + 0x347f8b, + 0x3ca20a, + 0x3e010c, + 0xebe48, + 0x2000c2, + 0x201242, + 0x200382, + 0x22d805, + 0x221dc4, + 0x209e82, + 0x23c803, + 0x306c44, + 0x208482, + 0x2003c2, + 0x2090c2, + 0x20c782, + 0x2703, + 0x15702, + 0x2cb209, + 0x365308, + 0x307e89, + 0x2073c9, + 0x20b40a, + 0x210f0a, + 0x206082, + 0x2167c2, + 0x1242, + 0x214a83, + 0x22ba02, + 0x240c46, + 0x377dc2, + 0x208d42, + 0x26fd0e, + 0x21410e, + 0x27e307, + 0x21a347, + 0x24dc82, + 0x232dc3, + 0x308003, + 0x210d82, + 0x2005c2, + 0x1bac3, + 0x235d4f, + 0x21fb02, + 0x2b8887, + 0x3520c7, + 0x2bc287, + 0x2e9ccc, + 0x2dc18c, + 0x20c304, + 0x38d04a, + 0x214042, + 0x201e42, + 0x2c5104, + 0x200702, + 0x2cc342, + 0x2dc3c4, + 0x20fe82, + 0x202042, + 0x1a8c3, + 0x299807, + 0x23a705, + 0x223502, + 0x23cd04, + 0x203f82, + 0x2eba08, + 0x21a3c3, + 0x376b08, + 0x2029c2, + 0x20c4c5, + 0x396e06, + 0x242543, + 0x20a882, + 0x2fa607, + 0xeb02, + 0x39e785, + 0x3c2f45, + 0x206442, + 0x20b382, + 0x33a90a, + 0x35094a, + 0x23c7c2, + 0x2a4284, + 0x203282, + 0x3d3788, + 0x20a5c2, + 0x359208, + 0xf01, + 0x314447, + 0x3149c9, + 0x2b7402, + 0x319985, + 0x3b9c45, + 0x2184cb, + 0x33894c, + 0x22c088, + 0x32bb08, + 0x21d642, + 0x2ac882, + 0x2000c2, + 0x9a048, + 0x201242, + 0x214a83, + 0x200382, + 0x208482, + 0x3dc3, + 0x2003c2, + 0x242543, + 0x2090c2, + 0x2000c2, + 0x139b05, + 0x7fa01242, + 0x1099c4, + 0x37e85, + 0x80708003, + 0x21a8c3, + 0x209e82, + 0x21a3c3, + 0x3b68c3, + 0x80a42543, + 0x2f7103, + 0x274d46, + 0x160e2c3, + 0x139b05, + 0x13f10b, + 0x9a048, + 0x7ff02e08, + 0x5c1c7, + 0x802c108a, + 0x6ddc7, + 0x97805, + 0x2a54d, + 0x8e242, + 0x118682, + 0xe01, + 0xad28a, + 0x150787, + 0x20c04, + 0x20c43, + 0x3c704, + 0x81202842, + 0x81600ac2, + 0x81a01182, + 0x81e02d02, + 0x82206b42, + 0x826086c2, + 0x17e707, + 0x82a01242, + 0x82e2ec02, + 0x8321f2c2, + 0x83602a42, + 0x214103, + 0xca04, + 0x22dcc3, + 0x83a0e442, + 0x5a988, + 0x83e015c2, + 0x4e2c7, + 0x1ad887, + 0x84200042, + 0x84600d82, + 0x84a00182, + 0x84e06182, + 0x85200f42, + 0x856005c2, + 0xf4185, + 0x24dec3, + 0x35c004, + 0x85a00702, + 0x85e14d42, + 0x86206002, + 0x7a04b, + 0x86600c42, + 0x86e01f42, + 0x87209e82, + 0x87610942, + 0x87a1d542, + 0x87e00bc2, + 0x88202382, + 0x8866c9c2, + 0x88a0ce02, + 0x88e03142, + 0x89208482, + 0x89637242, + 0x89a510c2, + 0x89e43802, + 0x5684, + 0x310543, + 0x8a200ec2, + 0x8a610e82, + 0x8aa0e742, + 0x8ae006c2, + 0x8b2003c2, + 0x8b600a82, + 0xf6bc8, + 0x91fc7, + 0x8ba141c2, + 0x8be06142, + 0x8c2090c2, + 0x8c6023c2, + 0x1aec8c, + 0x8ca02c02, + 0x8ce25b82, + 0x8d20f482, + 0x8d603642, + 0x8da00f02, + 0x8de0b582, + 0x8e201342, + 0x8e607302, + 0x8ea76002, + 0x8ee76542, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x23703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x86a059c3, + 0x223703, + 0x3c0b44, + 0x307d86, + 0x306403, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x374689, + 0x215702, + 0x39b6c3, + 0x2c2a43, + 0x2894c5, + 0x207083, + 0x2059c3, + 0x223703, + 0x267d83, + 0x211243, + 0x3c4409, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x2059c3, + 0x223703, + 0x215702, + 0x215702, + 0x2059c3, + 0x223703, + 0x8f614a83, + 0x232dc3, + 0x207603, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x9a048, + 0x201242, + 0x214a83, + 0x21a3c3, + 0x242543, + 0x141842, + 0x214a83, + 0x232dc3, + 0x308003, + 0x901192c2, + 0x23c803, + 0x21a3c3, + 0x3dc3, + 0x242543, + 0x1301, + 0x24c0c4, + 0x201242, + 0x214a83, + 0x200983, + 0x232dc3, + 0x24d9c4, + 0x228503, + 0x308003, + 0x221dc4, + 0x21bc83, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x22b983, + 0x208805, + 0x211243, + 0x207783, + 0x882, + 0x3dc3, + 0x201242, + 0x214a83, + 0x2059c3, + 0x21a3c3, + 0x242543, + 0x2000c2, + 0x202703, + 0x9a048, + 0x214a83, + 0x232dc3, + 0x308003, + 0x22f7c6, + 0x221dc4, + 0x21bc83, + 0x219a04, + 0x21a3c3, + 0x242543, + 0x2141c3, + 0x29904, + 0x214a83, + 0x239c3, + 0x232dc3, + 0x9e82, + 0x21a3c3, + 0x242543, + 0x2aec2, + 0x2982, + 0x147ee07, + 0x1807, + 0x214a83, + 0x28886, + 0x232dc3, + 0x308003, + 0xedf86, + 0x21a3c3, + 0x242543, + 0x328e48, + 0x32b949, + 0x33e209, + 0x34ae08, + 0x399488, + 0x399489, + 0x322c0a, + 0x3602ca, + 0x39424a, + 0x39abca, + 0x3ca20a, + 0x3d818b, + 0x30838d, + 0x23fd4f, + 0x35d210, + 0x361d4d, + 0x37d8cc, + 0x39a90b, + 0x6dfc8, + 0x11d548, + 0x19d705, + 0x1486107, + 0xd7445, + 0x2000c2, + 0x2cd685, + 0x202003, + 0x93601242, + 0x232dc3, + 0x308003, + 0x27e7c7, + 0x25cc03, + 0x23c803, + 0x21a3c3, + 0x24e283, + 0x2125c3, + 0x206a03, + 0x203dc3, + 0x242543, + 0x252b06, + 0x233442, + 0x207783, + 0x9a048, + 0x2000c2, + 0x202703, + 0x201242, + 0x214a83, + 0x232dc3, + 0x308003, + 0x221dc4, + 0x23c803, + 0x21a3c3, + 0x242543, + 0x20e2c3, + 0x1807, + 0xb342, + 0x68b44, + 0x151c306, + 0x2000c2, + 0x201242, + 0x308003, + 0x23c803, + 0x242543, +} + +// children is the list of nodes' children, the parent's wildcard bit and the +// parent's node type. If a node has no children then their children index +// will be in the range [0, 6), depending on the wildcard bit and node type. +// +// The layout within the uint32, from MSB to LSB, is: +// [ 1 bits] unused +// [ 1 bits] wildcard bit +// [ 2 bits] node type +// [14 bits] high nodes index (exclusive) of children +// [14 bits] low nodes index (inclusive) of children +var children = [...]uint32{ + 0x0, + 0x10000000, + 0x20000000, + 0x40000000, + 0x50000000, + 0x60000000, + 0x17ec5f5, + 0x17f05fb, + 0x17f45fc, + 0x18185fd, + 0x1970606, + 0x198865c, + 0x199c662, + 0x19b4667, + 0x19d466d, + 0x19f4675, + 0x1a0c67d, + 0x1a2c683, + 0x1a3068b, + 0x1a5868c, + 0x1a5c696, + 0x1a74697, + 0x1a7869d, + 0x1a7c69e, + 0x1ab869f, + 0x1abc6ae, + 0x1ac06af, + 0x61ac86b0, + 0x21ad06b2, + 0x1b186b4, + 0x1b1c6c6, + 0x1b406c7, + 0x1b446d0, + 0x1b486d1, + 0x1b5c6d2, + 0x1b606d7, + 0x1b806d8, + 0x1bb06e0, + 0x1bcc6ec, + 0x1bf46f3, + 0x1c046fd, + 0x1c08701, + 0x1ca0702, + 0x1cb4728, + 0x1cc872d, + 0x1d00732, + 0x1d10740, + 0x1d24744, + 0x1d3c749, + 0x1de074f, + 0x1fe4778, + 0x1fe87f9, + 0x20547fa, + 0x20c0815, + 0x20d8830, + 0x20ec836, + 0x20f083b, + 0x20f883c, + 0x210c83e, + 0x2110843, + 0x2130844, + 0x218084c, + 0x2184860, + 0x22188861, + 0x21a4862, + 0x21a8869, + 0x21ac86a, + 0x21d086b, + 0x2214874, + 0x2218885, + 0x6221c886, + 0x2238887, + 0x226488e, + 0x2270899, + 0x228089c, + 0x23348a0, + 0x23388cd, + 0x223488ce, + 0x2234c8d2, + 0x223548d3, + 0x23ac8d5, + 0x23b08eb, + 0x23b48ec, + 0x28dc8ed, + 0x28e0a37, + 0x22988a38, + 0x2298ca62, + 0x22990a63, + 0x2299ca64, + 0x229a0a67, + 0x229aca68, + 0x229b0a6b, + 0x229b4a6c, + 0x229b8a6d, + 0x229bca6e, + 0x229c0a6f, + 0x229cca70, + 0x229d0a73, + 0x229dca74, + 0x229e0a77, + 0x229e4a78, + 0x229e8a79, + 0x229f4a7a, + 0x229f8a7d, + 0x22a04a7e, + 0x22a08a81, + 0x22a0ca82, + 0x22a10a83, + 0x2a14a84, + 0x22a18a85, + 0x22a24a86, + 0x22a28a89, + 0x2a2ca8a, + 0x2a34a8b, + 0x62a40a8d, + 0x2a84a90, + 0x22aa4aa1, + 0x22aa8aa9, + 0x22aacaaa, + 0x22ab0aab, + 0x22ab8aac, + 0x22abcaae, + 0x2ac0aaf, + 0x22ac4ab0, + 0x22ac8ab1, + 0x22accab2, + 0x22ad0ab3, + 0x2ad8ab4, + 0x2ae0ab6, + 0x2ae4ab8, + 0x2b00ab9, + 0x2b18ac0, + 0x2b1cac6, + 0x2b2cac7, + 0x2b38acb, + 0x2b6cace, + 0x2b74adb, + 0x22b78add, + 0x2b90ade, + 0x22b98ae4, + 0x22b9cae6, + 0x22ba4ae7, + 0x2ca0ae9, + 0x22ca4b28, + 0x2cacb29, + 0x2cb0b2b, + 0x22cb4b2c, + 0x2cb8b2d, + 0x2ce0b2e, + 0x2ce4b38, + 0x2ce8b39, + 0x2cecb3a, + 0x2d04b3b, + 0x2d18b41, + 0x2d40b46, + 0x2d60b50, + 0x2d64b58, + 0x62d68b59, + 0x2d9cb5a, + 0x2da0b67, + 0x22da4b68, + 0x2da8b69, + 0x2dd0b6a, + 0x2dd4b74, + 0x2df8b75, + 0x2dfcb7e, + 0x2e10b7f, + 0x2e14b84, + 0x2e18b85, + 0x2e38b86, + 0x2e54b8e, + 0x2e58b95, + 0x22e5cb96, + 0x2e60b97, + 0x2e64b98, + 0x2e68b99, + 0x2e70b9a, + 0x2e84b9c, + 0x2e88ba1, + 0x2e8cba2, + 0x2eb4ba3, + 0x2eb8bad, + 0x2f2cbae, + 0x2f30bcb, + 0x2f34bcc, + 0x2f54bcd, + 0x2f6cbd5, + 0x2f70bdb, + 0x2f84bdc, + 0x2f9cbe1, + 0x2fbcbe7, + 0x2fd4bef, + 0x2fd8bf5, + 0x2ff4bf6, + 0x3010bfd, + 0x3014c04, + 0x3040c05, + 0x3060c10, + 0x3080c18, + 0x30e4c20, + 0x3104c39, + 0x3120c41, + 0x3124c48, + 0x313cc49, + 0x3180c4f, + 0x3200c60, + 0x3230c80, + 0x3234c8c, + 0x3240c8d, + 0x3260c90, + 0x3264c98, + 0x3288c99, + 0x3290ca2, + 0x32ccca4, + 0x3320cb3, + 0x3324cc8, + 0x3328cc9, + 0x3404cca, + 0x2340cd01, + 0x23410d03, + 0x23414d04, + 0x3418d05, + 0x2341cd06, + 0x23420d07, + 0x3424d08, + 0x23428d09, + 0x23438d0a, + 0x2343cd0e, + 0x23440d0f, + 0x23444d10, + 0x23448d11, + 0x2344cd12, + 0x3464d13, + 0x3488d19, + 0x34a8d22, + 0x3b14d2a, + 0x3b20ec5, + 0x3b40ec8, + 0x3d00ed0, + 0x3dd0f40, + 0x3e40f74, + 0x3e98f90, + 0x3f80fa6, + 0x3fd8fe0, + 0x4014ff6, + 0x4111005, + 0x41dd044, + 0x4275077, + 0x430509d, + 0x43690c1, + 0x45a10da, + 0x4659168, + 0x4725196, + 0x47711c9, + 0x47f91dc, + 0x48351fe, + 0x488520d, + 0x48fd221, + 0x6490123f, + 0x64905240, + 0x64909241, + 0x4985242, + 0x49e1261, + 0x4a5d278, + 0x4ad5297, + 0x4b552b5, + 0x4bc12d5, + 0x4ced2f0, + 0x4d4533b, + 0x64d49351, + 0x4de1352, + 0x4de9378, + 0x24ded37a, + 0x4e7537b, + 0x4ec139d, + 0x4f293b0, + 0x4fd13ca, + 0x50993f4, + 0x5101426, + 0x5215440, + 0x65219485, + 0x6521d486, + 0x5279487, + 0x52d549e, + 0x53654b5, + 0x53e14d9, + 0x54254f8, + 0x5509509, + 0x553d542, + 0x559d54f, + 0x5611567, + 0x5699584, + 0x56d95a6, + 0x57495b6, + 0x6574d5d2, + 0x57755d3, + 0x57795dd, + 0x57a95de, + 0x57c55ea, + 0x58095f1, + 0x5819602, + 0x5831606, + 0x58a960c, + 0x58b162a, + 0x58cd62c, + 0x58e1633, + 0x58fd638, + 0x592963f, + 0x592d64a, + 0x593564b, + 0x594964d, + 0x5969652, + 0x597965a, + 0x598565e, + 0x59c1661, + 0x59c9670, + 0x59dd672, + 0x5a05677, + 0x5a11681, + 0x5a19684, + 0x5a41686, + 0x5a65690, + 0x5a7d699, + 0x5a8169f, + 0x5a896a0, + 0x5a9d6a2, + 0x5b456a7, + 0x5b496d1, + 0x5b4d6d2, + 0x5b516d3, + 0x5b756d4, + 0x5b996dd, + 0x5bb56e6, + 0x5bc96ed, + 0x5bdd6f2, + 0x5be56f7, + 0x5bed6f9, + 0x5bf56fb, + 0x5c0d6fd, + 0x5c1d703, + 0x5c21707, + 0x5c3d708, + 0x64c570f, + 0x64fd931, + 0x652993f, + 0x654594a, + 0x6565951, + 0x6585959, + 0x65c9961, + 0x65d1972, + 0x265d5974, + 0x265d9975, + 0x65e1976, + 0x67cd978, + 0x267d19f3, + 0x67d59f4, + 0x267d99f5, + 0x267e99f6, + 0x267f19fa, + 0x267fd9fc, + 0x68019ff, + 0x26809a00, + 0x6811a02, + 0x6821a04, + 0x6849a08, + 0x6885a12, + 0x6889a21, + 0x68c1a22, + 0x68e5a30, + 0x743da39, + 0x7441d0f, + 0x7445d10, + 0x27449d11, + 0x744dd12, + 0x27451d13, + 0x7455d14, + 0x27461d15, + 0x7465d18, + 0x7469d19, + 0x2746dd1a, + 0x7471d1b, + 0x27479d1c, + 0x747dd1e, + 0x7481d1f, + 0x27491d20, + 0x7495d24, + 0x7499d25, + 0x749dd26, + 0x74a1d27, + 0x274a5d28, + 0x74a9d29, + 0x74add2a, + 0x74b1d2b, + 0x74b5d2c, + 0x274bdd2d, + 0x74c1d2f, + 0x74c5d30, + 0x74c9d31, + 0x274cdd32, + 0x74d1d33, + 0x274d9d34, + 0x274ddd36, + 0x74f9d37, + 0x7511d3e, + 0x7555d44, + 0x7559d55, + 0x757dd56, + 0x7589d5f, + 0x758dd62, + 0x7591d63, + 0x7755d64, + 0x27759dd5, + 0x27761dd6, + 0x27765dd8, + 0x27769dd9, + 0x7771dda, + 0x784dddc, + 0x27859e13, + 0x2785de16, + 0x27861e17, + 0x27865e18, + 0x7869e19, + 0x7895e1a, + 0x78a1e25, + 0x78a5e28, + 0x78c9e29, + 0x78d5e32, + 0x78f5e35, + 0x78f9e3d, + 0x7931e3e, + 0x7be1e4c, + 0x7c9def8, + 0x7ca1f27, + 0x7ca5f28, + 0x7cb9f29, + 0x7cbdf2e, + 0x7cf1f2f, + 0x7d29f3c, + 0x27d2df4a, + 0x7d49f4b, + 0x7d71f52, + 0x7d75f5c, + 0x7d99f5d, + 0x7db5f66, + 0x7dddf6d, + 0x7dedf77, + 0x7df1f7b, + 0x7df5f7c, + 0x7e2df7d, + 0x7e39f8b, + 0x7e61f8e, + 0x7ee1f98, + 0x27ee5fb8, + 0x7ef5fb9, + 0x7f05fbd, + 0x7f21fc1, + 0x7f41fc8, + 0x7f45fd0, + 0x7f59fd1, + 0x7f6dfd6, + 0x7f71fdb, + 0x7f75fdc, + 0x7f79fdd, + 0x7f99fde, + 0x8041fe6, + 0x8046010, + 0x8062011, + 0x808a018, + 0x808e022, + 0x8096023, + 0x80ba025, + 0x80c202e, + 0x80d6030, + 0x80f6035, + 0x811203d, + 0x8122044, + 0x813a048, + 0x817204e, + 0x817605c, + 0x824a05d, + 0x824e092, + 0x8262093, + 0x826a098, + 0x828209a, + 0x82860a0, + 0x82920a1, + 0x829e0a4, + 0x82a20a7, + 0x82a60a8, + 0x82aa0a9, + 0x82ce0aa, + 0x830e0b3, + 0x83120c3, + 0x83320c4, + 0x83820cc, + 0x83ae0e0, + 0x283b20eb, + 0x83ba0ec, + 0x84120ee, + 0x8416104, + 0x841a105, + 0x841e106, + 0x8462107, + 0x8472118, + 0x84b211c, + 0x84b612c, + 0x84e612d, + 0x8632139, + 0x865a18c, + 0x8692196, + 0x86b61a4, + 0x286be1ad, + 0x286c21af, + 0x86ca1b0, + 0x86d61b2, + 0x87f21b5, + 0x87fe1fc, + 0x880a1ff, + 0x8816202, + 0x8822205, + 0x882e208, + 0x883a20b, + 0x884620e, + 0x8852211, + 0x885e214, + 0x886a217, + 0x887621a, + 0x888221d, + 0x888e220, + 0x8896223, + 0x88a2225, + 0x88ae228, + 0x88ba22b, + 0x88c622e, + 0x88d2231, + 0x88de234, + 0x88ea237, + 0x88f623a, + 0x890223d, + 0x890e240, + 0x891a243, + 0x8946246, + 0x8952251, + 0x895e254, + 0x896a257, + 0x897625a, + 0x898225d, + 0x898a260, + 0x8996262, + 0x89a2265, + 0x89ae268, + 0x89ba26b, + 0x89c626e, + 0x89d2271, + 0x89de274, + 0x89ea277, + 0x89f627a, + 0x8a0227d, + 0x8a0e280, + 0x8a16283, + 0x8a22285, + 0x8a2a288, + 0x8a3628a, + 0x8a4228d, + 0x8a4e290, + 0x8a5a293, + 0x8a66296, + 0x8a72299, + 0x8a7e29c, + 0x8a8a29f, + 0x8a8e2a2, + 0x8a9a2a3, + 0x8ab62a6, + 0x8aba2ad, + 0x8aca2ae, + 0x8aee2b2, + 0x8af22bb, + 0x8b362bc, + 0x8b3e2cd, + 0x8b522cf, + 0x8b862d4, + 0x8ba22e1, + 0x8baa2e8, + 0x8bce2ea, + 0x8be62f3, + 0x8bfe2f9, + 0x8c162ff, + 0x8c2a305, + 0x28c7230a, + 0x8c7631c, + 0x8ca231d, + 0x8cb2328, + 0x8cc632c, +} + +// max children 592 (capacity 1023) +// max text offset 30772 (capacity 32767) +// max text length 36 (capacity 63) +// max hi 9009 (capacity 16383) +// max lo 9004 (capacity 16383) diff --git a/vendor/modules.txt b/vendor/modules.txt index 4ff83ac66..f762d95c8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,6 +2,9 @@ ## explicit github.com/apex/log github.com/apex/log/handlers/cli +# github.com/bloodorangeio/reggie v0.5.0 +## explicit +github.com/bloodorangeio/reggie # github.com/cpuguy83/go-md2man/v2 v2.0.0 ## explicit github.com/cpuguy83/go-md2man/v2/md2man @@ -15,6 +18,8 @@ github.com/davecgh/go-spew/spew github.com/docker/go-units # github.com/fatih/color v1.9.0 github.com/fatih/color +# github.com/go-resty/resty/v2 v2.1.0 +github.com/go-resty/resty/v2 # github.com/golang/protobuf v1.4.2 ## explicit github.com/golang/protobuf/proto @@ -40,6 +45,8 @@ github.com/konsorten/go-windows-terminal-sequences github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-isatty +# github.com/mitchellh/mapstructure v1.1.2 +github.com/mitchellh/mapstructure # github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 ## explicit github.com/mohae/deepcopy @@ -92,6 +99,7 @@ golang.org/x/crypto/ripemd160 # golang.org/x/net v0.0.0-20200602114024-627f9648deb9 ## explicit golang.org/x/net/context +golang.org/x/net/publicsuffix # golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 ## explicit golang.org/x/sys/internal/unsafeheader