// Copyright 2019 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 checksum database lookup

// +build !cmd_go_bootstrap

package modfetch

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"cmd/go/internal/base"
	"cmd/go/internal/cfg"
	"cmd/go/internal/get"
	"cmd/go/internal/lockedfile"
	"cmd/go/internal/str"
	"cmd/go/internal/web"

	"golang.org/x/mod/module"
	"golang.org/x/mod/sumdb"
	"golang.org/x/mod/sumdb/note"
)

// useSumDB reports whether to use the Go checksum database for the given module.
func useSumDB(mod module.Version) bool {
	return cfg.GOSUMDB != "off" && !get.Insecure && !str.GlobsMatchPath(cfg.GONOSUMDB, mod.Path)
}

// lookupSumDB returns the Go checksum database's go.sum lines for the given module,
// along with the name of the database.
func lookupSumDB(mod module.Version) (dbname string, lines []string, err error) {
	dbOnce.Do(func() {
		dbName, db, dbErr = dbDial()
	})
	if dbErr != nil {
		return "", nil, dbErr
	}
	lines, err = db.Lookup(mod.Path, mod.Version)
	return dbName, lines, err
}

var (
	dbOnce sync.Once
	dbName string
	db     *sumdb.Client
	dbErr  error
)

func dbDial() (dbName string, db *sumdb.Client, err error) {
	// $GOSUMDB can be "key" or "key url",
	// and the key can be a full verifier key
	// or a host on our list of known keys.

	// Special case: sum.golang.google.cn
	// is an alias, reachable inside mainland China,
	// for sum.golang.org. If there are more
	// of these we should add a map like knownGOSUMDB.
	gosumdb := cfg.GOSUMDB
	if gosumdb == "sum.golang.google.cn" {
		gosumdb = "sum.golang.org https://sum.golang.google.cn"
	}

	key := strings.Fields(gosumdb)
	if len(key) >= 1 {
		if k := knownGOSUMDB[key[0]]; k != "" {
			key[0] = k
		}
	}
	if len(key) == 0 {
		return "", nil, fmt.Errorf("missing GOSUMDB")
	}
	if len(key) > 2 {
		return "", nil, fmt.Errorf("invalid GOSUMDB: too many fields")
	}
	vkey, err := note.NewVerifier(key[0])
	if err != nil {
		return "", nil, fmt.Errorf("invalid GOSUMDB: %v", err)
	}
	name := vkey.Name()

	// No funny business in the database name.
	direct, err := url.Parse("https://" + name)
	if err != nil || strings.HasSuffix(name, "/") || *direct != (url.URL{Scheme: "https", Host: direct.Host, Path: direct.Path, RawPath: direct.RawPath}) || direct.RawPath != "" || direct.Host == "" {
		return "", nil, fmt.Errorf("invalid sumdb name (must be host[/path]): %s %+v", name, *direct)
	}

	// Determine how to get to database.
	var base *url.URL
	if len(key) >= 2 {
		// Use explicit alternate URL listed in $GOSUMDB,
		// bypassing both the default URL derivation and any proxies.
		u, err := url.Parse(key[1])
		if err != nil {
			return "", nil, fmt.Errorf("invalid GOSUMDB URL: %v", err)
		}
		base = u
	}

	return name, sumdb.NewClient(&dbClient{key: key[0], name: name, direct: direct, base: base}), nil
}

type dbClient struct {
	key    string
	name   string
	direct *url.URL

	once    sync.Once
	base    *url.URL
	baseErr error
}

func (c *dbClient) ReadRemote(path string) ([]byte, error) {
	c.once.Do(c.initBase)
	if c.baseErr != nil {
		return nil, c.baseErr
	}

	var data []byte
	start := time.Now()
	targ := web.Join(c.base, path)
	data, err := web.GetBytes(targ)
	if false {
		fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), web.Redacted(targ))
	}
	return data, err
}

// initBase determines the base URL for connecting to the database.
// Determining the URL requires sending network traffic to proxies,
// so this work is delayed until we need to download something from
// the database. If everything we need is in the local cache and
// c.ReadRemote is never called, we will never do this work.
func (c *dbClient) initBase() {
	if c.base != nil {
		return
	}

	// Try proxies in turn until we find out how to connect to this database.
	//
	// Before accessing any checksum database URL using a proxy, the proxy
	// client should first fetch <proxyURL>/sumdb/<sumdb-name>/supported.
	//
	// If that request returns a successful (HTTP 200) response, then the proxy
	// supports proxying checksum database requests. In that case, the client
	// should use the proxied access method only, never falling back to a direct
	// connection to the database.
	//
	// If the /sumdb/<sumdb-name>/supported check fails with a “not found” (HTTP
	// 404) or “gone” (HTTP 410) response, or if the proxy is configured to fall
	// back on errors, the client will try the next proxy. If there are no
	// proxies left or if the proxy is "direct" or "off", the client should
	// connect directly to that database.
	//
	// Any other response is treated as the database being unavailable.
	//
	// See https://golang.org/design/25530-sumdb#proxying-a-checksum-database.
	err := TryProxies(func(proxy string) error {
		switch proxy {
		case "noproxy":
			return errUseProxy
		case "direct", "off":
			return errProxyOff
		default:
			proxyURL, err := url.Parse(proxy)
			if err != nil {
				return err
			}
			if _, err := web.GetBytes(web.Join(proxyURL, "sumdb/"+c.name+"/supported")); err != nil {
				return err
			}
			// Success! This proxy will help us.
			c.base = web.Join(proxyURL, "sumdb/"+c.name)
			return nil
		}
	})
	if errors.Is(err, os.ErrNotExist) {
		// No proxies, or all proxies failed (with 404, 410, or were were allowed
		// to fall back), or we reached an explicit "direct" or "off".
		c.base = c.direct
	} else if err != nil {
		c.baseErr = err
	}
}

// ReadConfig reads the key from c.key
// and otherwise reads the config (a latest tree head) from GOPATH/pkg/sumdb/<file>.
func (c *dbClient) ReadConfig(file string) (data []byte, err error) {
	if file == "key" {
		return []byte(c.key), nil
	}

	// GOPATH/pkg is PkgMod/..
	targ := filepath.Join(PkgMod, "../sumdb/"+file)
	data, err = lockedfile.Read(targ)
	if errors.Is(err, os.ErrNotExist) {
		// Treat non-existent as empty, to bootstrap the "latest" file
		// the first time we connect to a given database.
		return []byte{}, nil
	}
	return data, err
}

// WriteConfig rewrites the latest tree head.
func (*dbClient) WriteConfig(file string, old, new []byte) error {
	if file == "key" {
		// Should not happen.
		return fmt.Errorf("cannot write key")
	}
	targ := filepath.Join(PkgMod, "../sumdb/"+file)
	os.MkdirAll(filepath.Dir(targ), 0777)
	f, err := lockedfile.Edit(targ)
	if err != nil {
		return err
	}
	defer f.Close()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}
	if len(data) > 0 && !bytes.Equal(data, old) {
		return sumdb.ErrWriteConflict
	}
	if _, err := f.Seek(0, 0); err != nil {
		return err
	}
	if err := f.Truncate(0); err != nil {
		return err
	}
	if _, err := f.Write(new); err != nil {
		return err
	}
	return f.Close()
}

// ReadCache reads cached lookups or tiles from
// GOPATH/pkg/mod/cache/download/sumdb,
// which will be deleted by "go clean -modcache".
func (*dbClient) ReadCache(file string) ([]byte, error) {
	targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
	data, err := lockedfile.Read(targ)
	// lockedfile.Write does not atomically create the file with contents.
	// There is a moment between file creation and locking the file for writing,
	// during which the empty file can be locked for reading.
	// Treat observing an empty file as file not found.
	if err == nil && len(data) == 0 {
		err = &os.PathError{Op: "read", Path: targ, Err: os.ErrNotExist}
	}
	return data, err
}

// WriteCache updates cached lookups or tiles.
func (*dbClient) WriteCache(file string, data []byte) {
	targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
	os.MkdirAll(filepath.Dir(targ), 0777)
	lockedfile.Write(targ, bytes.NewReader(data), 0666)
}

func (*dbClient) Log(msg string) {
	// nothing for now
}

func (*dbClient) SecurityError(msg string) {
	base.Fatalf("%s", msg)
}
