func hostHasOtherPort(allConfigs []*SiteConfig, thisConfigIdx int, otherPort string) bool {
	for i, otherCfg := range allConfigs {
		if i == thisConfigIdx {
			continue  
		}
		if otherCfg.Addr.Host == allConfigs[thisConfigIdx].Addr.Host &&
			otherCfg.Addr.Port == otherPort {
			return true
		}
	}
	return false
}
hostHasOtherPort returns true if there is another config in the list with the same
hostname that has port otherPort, or false otherwise. All the configs are checked
against the hostname of allConfigs[thisConfigIdx].
package httpserver
import (
	"fmt"
	"net"
	"net/http"
	"strconv"
	"github.com/tmpim/casket"
	"github.com/tmpim/casket/caskettls"
	"github.com/tmpim/certmagic"
)
func activateHTTPS(cctx casket.Context) error {
	operatorPresent := !casket.Started()
	if !casket.Quiet && operatorPresent {
		fmt.Print("Activating privacy features... ")
	}
	ctx := cctx.(*httpContext)
	markQualifiedForAutoHTTPS(ctx.siteConfigs)
	for _, c := range ctx.siteConfigs {
		if !c.TLS.Managed {
			continue
		}
		if c.TLS.Manager.OnDemand != nil {
			continue  
		}
		err := c.TLS.Manager.ObtainCert(c.TLS.Hostname, operatorPresent)
		if err != nil {
			return err
		}
	}
	err := enableAutoHTTPS(ctx.siteConfigs, true)
	if err != nil {
		return err
	}
	ctx.siteConfigs = makePlaintextRedirects(ctx.siteConfigs)
	if !casket.IsUpgrade() {
		ctx.instance.StorageMu.RLock()
		certCache, ok := ctx.instance.Storage[caskettls.CertCacheInstStorageKey].(*certmagic.Cache)
		ctx.instance.StorageMu.RUnlock()
		if ok && certCache != nil {
			err = certCache.RenewManagedCertificates()
			if err != nil {
				return err
			}
		}
	}
	if !casket.Quiet && operatorPresent {
		fmt.Println("done.")
	}
	return nil
}
func markQualifiedForAutoHTTPS(configs []*SiteConfig) {
	for _, cfg := range configs {
		if !casket.IsLoopback(cfg.Addr.Host) &&
			!casket.IsLoopback(cfg.ListenHost) &&
			!casket.IsInternal(cfg.Addr.Host) &&
			!casket.IsInternal(cfg.ListenHost) &&
			caskettls.QualifiesForManagedTLS(cfg) &&
			cfg.Addr.Scheme != "http" {
			cfg.TLS.Managed = true
		}
	}
}
func enableAutoHTTPS(configs []*SiteConfig, loadCertificates bool) error {
	for _, cfg := range configs {
		if cfg == nil || cfg.TLS == nil || !cfg.TLS.Managed ||
			cfg.TLS.Manager == nil || cfg.TLS.Manager.OnDemand != nil {
			continue
		}
		cfg.TLS.Enabled = true
		cfg.Addr.Scheme = "https"
		if loadCertificates && certmagic.HostQualifies(cfg.TLS.Hostname) {
			_, err := cfg.TLS.Manager.CacheManagedCertificate(cfg.TLS.Hostname)
			if err != nil {
				return err
			}
		}
		caskettls.SetDefaultTLSParams(cfg.TLS)
		if cfg.Addr.Port == "" &&
			cfg.TLS.Enabled &&
			(!cfg.TLS.Manual || cfg.TLS.Manager.OnDemand != nil) &&
			cfg.Addr.Host != "localhost" {
			cfg.Addr.Port = strconv.Itoa(certmagic.HTTPSPort)
		}
	}
	return nil
}
func makePlaintextRedirects(allConfigs []*SiteConfig) []*SiteConfig {
	httpPort := strconv.Itoa(certmagic.HTTPPort)
	httpsPort := strconv.Itoa(certmagic.HTTPSPort)
	for i, cfg := range allConfigs {
		if cfg.TLS.Managed &&
			!hostHasOtherPort(allConfigs, i, httpPort) &&
			(cfg.Addr.Port == httpsPort || !hostHasOtherPort(allConfigs, i, httpsPort)) {
			allConfigs = append(allConfigs, redirPlaintextHost(cfg))
		}
	}
	return allConfigs
}