<commit_before>package daemon // import "github.com/docker/docker/daemon"

import (
	"encoding/json"
	"fmt"

	"github.com/docker/docker/daemon/config"
	"github.com/docker/docker/daemon/discovery"
	"github.com/sirupsen/logrus"
)

// Reload reads configuration changes and modifies the
// daemon according to those changes.
// These are the settings that Reload changes:
// - Platform runtime
// - Daemon debug log level
// - Daemon max concurrent downloads
// - Daemon max concurrent uploads
// - Daemon shutdown timeout (in seconds)
// - Cluster discovery (reconfigure and restart)
// - Daemon labels
// - Insecure registries
// - Registry mirrors
// - Daemon live restore
func (daemon *Daemon) Reload(conf *config.Config) (err error) {
	daemon.configStore.Lock()
	attributes := map[string]string{}

	defer func() {
		jsonString, _ := json.Marshal(daemon.configStore)

		// we're unlocking here, because
		// LogDaemonEventWithAttributes() -> SystemInfo() -> GetAllRuntimes()
		// holds that lock too.
		daemon.configStore.Unlock()
		if err == nil {
			logrus.Infof("Reloaded configuration: %s", jsonString)
			daemon.LogDaemonEventWithAttributes("reload", attributes)
		}
	}()

	if err := daemon.reloadPlatform(conf, attributes); err != nil {
		return err
	}
	daemon.reloadDebug(conf, attributes)
	daemon.reloadMaxConcurrentDownloadsAndUploads(conf, attributes)
	daemon.reloadShutdownTimeout(conf, attributes)
	daemon.reloadFeatures(conf, attributes)

	if err := daemon.reloadClusterDiscovery(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadLabels(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadAllowNondistributableArtifacts(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadInsecureRegistries(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadRegistryMirrors(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadLiveRestore(conf, attributes); err != nil {
		return err
	}
	return daemon.reloadNetworkDiagnosticPort(conf, attributes)
}

// reloadDebug updates configuration with Debug option
// and updates the passed attributes
func (daemon *Daemon) reloadDebug(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	if conf.IsValueSet("debug") {
		daemon.configStore.Debug = conf.Debug
	}
	// prepare reload event attributes with updatable configurations
	attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug)
}

// reloadMaxConcurrentDownloadsAndUploads updates configuration with max concurrent
// download and upload options and updates the passed attributes
func (daemon *Daemon) reloadMaxConcurrentDownloadsAndUploads(conf *config.Config, attributes map[string]string) {
	// If no value is set for max-concurrent-downloads we assume it is the default value
	// We always "reset" as the cost is lightweight and easy to maintain.
	if conf.IsValueSet("max-concurrent-downloads") && conf.MaxConcurrentDownloads != nil {
		*daemon.configStore.MaxConcurrentDownloads = *conf.MaxConcurrentDownloads
	} else {
		maxConcurrentDownloads := config.DefaultMaxConcurrentDownloads
		daemon.configStore.MaxConcurrentDownloads = &maxConcurrentDownloads
	}
	logrus.Debugf("Reset Max Concurrent Downloads: %d", *daemon.configStore.MaxConcurrentDownloads)

	// If no value is set for max-concurrent-upload we assume it is the default value
	// We always "reset" as the cost is lightweight and easy to maintain.
	if conf.IsValueSet("max-concurrent-uploads") && conf.MaxConcurrentUploads != nil {
		*daemon.configStore.MaxConcurrentUploads = *conf.MaxConcurrentUploads
	} else {
		maxConcurrentUploads := config.DefaultMaxConcurrentUploads
		daemon.configStore.MaxConcurrentUploads = &maxConcurrentUploads
	}
	logrus.Debugf("Reset Max Concurrent Uploads: %d", *daemon.configStore.MaxConcurrentUploads)

	daemon.imageService.UpdateConfig(conf.MaxConcurrentDownloads, conf.MaxConcurrentUploads)
	// prepare reload event attributes with updatable configurations
	attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads)
	// prepare reload event attributes with updatable configurations
	attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads)
}

// reloadShutdownTimeout updates configuration with daemon shutdown timeout option
// and updates the passed attributes
func (daemon *Daemon) reloadShutdownTimeout(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	if conf.IsValueSet("shutdown-timeout") {
		daemon.configStore.ShutdownTimeout = conf.ShutdownTimeout
		logrus.Debugf("Reset Shutdown Timeout: %d", daemon.configStore.ShutdownTimeout)
	}

	// prepare reload event attributes with updatable configurations
	attributes["shutdown-timeout"] = fmt.Sprintf("%d", daemon.configStore.ShutdownTimeout)
}

// reloadClusterDiscovery updates configuration with cluster discovery options
// and updates the passed attributes
func (daemon *Daemon) reloadClusterDiscovery(conf *config.Config, attributes map[string]string) (err error) {
	defer func() {
		// prepare reload event attributes with updatable configurations
		attributes["cluster-store"] = conf.ClusterStore
		attributes["cluster-advertise"] = conf.ClusterAdvertise

		attributes["cluster-store-opts"] = "{}"
		if daemon.configStore.ClusterOpts != nil {
			opts, err2 := json.Marshal(conf.ClusterOpts)
			if err != nil {
				err = err2
			}
			attributes["cluster-store-opts"] = string(opts)
		}
	}()

	newAdvertise := conf.ClusterAdvertise
	newClusterStore := daemon.configStore.ClusterStore
	if conf.IsValueSet("cluster-advertise") {
		if conf.IsValueSet("cluster-store") {
			newClusterStore = conf.ClusterStore
		}
		newAdvertise, err = config.ParseClusterAdvertiseSettings(newClusterStore, conf.ClusterAdvertise)
		if err != nil && err != discovery.ErrDiscoveryDisabled {
			return err
		}
	}

	if daemon.clusterProvider != nil {
		if err := conf.IsSwarmCompatible(); err != nil {
			return err
		}
	}

	// check discovery modifications
	if !config.ModifiedDiscoverySettings(daemon.configStore, newClusterStore, newAdvertise, conf.ClusterOpts) {
		return nil
	}

	// enable discovery for the first time if it was not previously enabled
	if daemon.discoveryWatcher == nil {
		discoveryWatcher, err := discovery.Init(newClusterStore, newAdvertise, conf.ClusterOpts)
		if err != nil {
			return fmt.Errorf("failed to initialize discovery: %v", err)
		}
		daemon.discoveryWatcher = discoveryWatcher
	} else if err == discovery.ErrDiscoveryDisabled {
		// disable discovery if it was previously enabled and it's disabled now
		daemon.discoveryWatcher.Stop()
	} else if err = daemon.discoveryWatcher.Reload(conf.ClusterStore, newAdvertise, conf.ClusterOpts); err != nil {
		// reload discovery
		return err
	}

	daemon.configStore.ClusterStore = newClusterStore
	daemon.configStore.ClusterOpts = conf.ClusterOpts
	daemon.configStore.ClusterAdvertise = newAdvertise

	if daemon.netController == nil {
		return nil
	}
	netOptions, err := daemon.networkOptions(daemon.configStore, daemon.PluginStore, nil)
	if err != nil {
		logrus.WithError(err).Warn("failed to get options with network controller")
		return nil
	}
	err = daemon.netController.ReloadConfiguration(netOptions...)
	if err != nil {
		logrus.Warnf("Failed to reload configuration with network controller: %v", err)
	}
	return nil
}

// reloadLabels updates configuration with engine labels
// and updates the passed attributes
func (daemon *Daemon) reloadLabels(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("labels") {
		daemon.configStore.Labels = conf.Labels
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.Labels != nil {
		labels, err := json.Marshal(daemon.configStore.Labels)
		if err != nil {
			return err
		}
		attributes["labels"] = string(labels)
	} else {
		attributes["labels"] = "[]"
	}

	return nil
}

// reloadAllowNondistributableArtifacts updates the configuration with allow-nondistributable-artifacts options
// and updates the passed attributes.
func (daemon *Daemon) reloadAllowNondistributableArtifacts(conf *config.Config, attributes map[string]string) error {
	// Update corresponding configuration.
	if conf.IsValueSet("allow-nondistributable-artifacts") {
		daemon.configStore.AllowNondistributableArtifacts = conf.AllowNondistributableArtifacts
		if err := daemon.RegistryService.LoadAllowNondistributableArtifacts(conf.AllowNondistributableArtifacts); err != nil {
			return err
		}
	}

	// Prepare reload event attributes with updatable configurations.
	if daemon.configStore.AllowNondistributableArtifacts != nil {
		v, err := json.Marshal(daemon.configStore.AllowNondistributableArtifacts)
		if err != nil {
			return err
		}
		attributes["allow-nondistributable-artifacts"] = string(v)
	} else {
		attributes["allow-nondistributable-artifacts"] = "[]"
	}

	return nil
}

// reloadInsecureRegistries updates configuration with insecure registry option
// and updates the passed attributes
func (daemon *Daemon) reloadInsecureRegistries(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("insecure-registries") {
		daemon.configStore.InsecureRegistries = conf.InsecureRegistries
		if err := daemon.RegistryService.LoadInsecureRegistries(conf.InsecureRegistries); err != nil {
			return err
		}
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.InsecureRegistries != nil {
		insecureRegistries, err := json.Marshal(daemon.configStore.InsecureRegistries)
		if err != nil {
			return err
		}
		attributes["insecure-registries"] = string(insecureRegistries)
	} else {
		attributes["insecure-registries"] = "[]"
	}

	return nil
}

// reloadRegistryMirrors updates configuration with registry mirror options
// and updates the passed attributes
func (daemon *Daemon) reloadRegistryMirrors(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("registry-mirrors") {
		daemon.configStore.Mirrors = conf.Mirrors
		if err := daemon.RegistryService.LoadMirrors(conf.Mirrors); err != nil {
			return err
		}
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.Mirrors != nil {
		mirrors, err := json.Marshal(daemon.configStore.Mirrors)
		if err != nil {
			return err
		}
		attributes["registry-mirrors"] = string(mirrors)
	} else {
		attributes["registry-mirrors"] = "[]"
	}

	return nil
}

// reloadLiveRestore updates configuration with live retore option
// and updates the passed attributes
func (daemon *Daemon) reloadLiveRestore(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("live-restore") {
		daemon.configStore.LiveRestoreEnabled = conf.LiveRestoreEnabled
	}

	// prepare reload event attributes with updatable configurations
	attributes["live-restore"] = fmt.Sprintf("%t", daemon.configStore.LiveRestoreEnabled)
	return nil
}

// reloadNetworkDiagnosticPort updates the network controller starting the diagnostic if the config is valid
func (daemon *Daemon) reloadNetworkDiagnosticPort(conf *config.Config, attributes map[string]string) error {
	if conf == nil || daemon.netController == nil || !conf.IsValueSet("network-diagnostic-port") ||
		conf.NetworkDiagnosticPort < 1 || conf.NetworkDiagnosticPort > 65535 {
		// If there is no config make sure that the diagnostic is off
		if daemon.netController != nil {
			daemon.netController.StopDiagnostic()
		}
		return nil
	}
	// Enable the network diagnostic if the flag is set with a valid port within the range
	logrus.WithFields(logrus.Fields{"port": conf.NetworkDiagnosticPort, "ip": "127.0.0.1"}).Warn("Starting network diagnostic server")
	daemon.netController.StartDiagnostic(conf.NetworkDiagnosticPort)

	return nil
}

// reloadFeatures updates configuration with enabled/disabled features
func (daemon *Daemon) reloadFeatures(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	// note that we allow features option to be entirely unset
	daemon.configStore.Features = conf.Features

	// prepare reload event attributes with updatable configurations
	attributes["features"] = fmt.Sprintf("%v", daemon.configStore.Features)
}
<commit_msg>Typo fix: retore -> restore<commit_after>package daemon // import "github.com/docker/docker/daemon"

import (
	"encoding/json"
	"fmt"

	"github.com/docker/docker/daemon/config"
	"github.com/docker/docker/daemon/discovery"
	"github.com/sirupsen/logrus"
)

// Reload reads configuration changes and modifies the
// daemon according to those changes.
// These are the settings that Reload changes:
// - Platform runtime
// - Daemon debug log level
// - Daemon max concurrent downloads
// - Daemon max concurrent uploads
// - Daemon shutdown timeout (in seconds)
// - Cluster discovery (reconfigure and restart)
// - Daemon labels
// - Insecure registries
// - Registry mirrors
// - Daemon live restore
func (daemon *Daemon) Reload(conf *config.Config) (err error) {
	daemon.configStore.Lock()
	attributes := map[string]string{}

	defer func() {
		jsonString, _ := json.Marshal(daemon.configStore)

		// we're unlocking here, because
		// LogDaemonEventWithAttributes() -> SystemInfo() -> GetAllRuntimes()
		// holds that lock too.
		daemon.configStore.Unlock()
		if err == nil {
			logrus.Infof("Reloaded configuration: %s", jsonString)
			daemon.LogDaemonEventWithAttributes("reload", attributes)
		}
	}()

	if err := daemon.reloadPlatform(conf, attributes); err != nil {
		return err
	}
	daemon.reloadDebug(conf, attributes)
	daemon.reloadMaxConcurrentDownloadsAndUploads(conf, attributes)
	daemon.reloadShutdownTimeout(conf, attributes)
	daemon.reloadFeatures(conf, attributes)

	if err := daemon.reloadClusterDiscovery(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadLabels(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadAllowNondistributableArtifacts(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadInsecureRegistries(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadRegistryMirrors(conf, attributes); err != nil {
		return err
	}
	if err := daemon.reloadLiveRestore(conf, attributes); err != nil {
		return err
	}
	return daemon.reloadNetworkDiagnosticPort(conf, attributes)
}

// reloadDebug updates configuration with Debug option
// and updates the passed attributes
func (daemon *Daemon) reloadDebug(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	if conf.IsValueSet("debug") {
		daemon.configStore.Debug = conf.Debug
	}
	// prepare reload event attributes with updatable configurations
	attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug)
}

// reloadMaxConcurrentDownloadsAndUploads updates configuration with max concurrent
// download and upload options and updates the passed attributes
func (daemon *Daemon) reloadMaxConcurrentDownloadsAndUploads(conf *config.Config, attributes map[string]string) {
	// If no value is set for max-concurrent-downloads we assume it is the default value
	// We always "reset" as the cost is lightweight and easy to maintain.
	if conf.IsValueSet("max-concurrent-downloads") && conf.MaxConcurrentDownloads != nil {
		*daemon.configStore.MaxConcurrentDownloads = *conf.MaxConcurrentDownloads
	} else {
		maxConcurrentDownloads := config.DefaultMaxConcurrentDownloads
		daemon.configStore.MaxConcurrentDownloads = &maxConcurrentDownloads
	}
	logrus.Debugf("Reset Max Concurrent Downloads: %d", *daemon.configStore.MaxConcurrentDownloads)

	// If no value is set for max-concurrent-upload we assume it is the default value
	// We always "reset" as the cost is lightweight and easy to maintain.
	if conf.IsValueSet("max-concurrent-uploads") && conf.MaxConcurrentUploads != nil {
		*daemon.configStore.MaxConcurrentUploads = *conf.MaxConcurrentUploads
	} else {
		maxConcurrentUploads := config.DefaultMaxConcurrentUploads
		daemon.configStore.MaxConcurrentUploads = &maxConcurrentUploads
	}
	logrus.Debugf("Reset Max Concurrent Uploads: %d", *daemon.configStore.MaxConcurrentUploads)

	daemon.imageService.UpdateConfig(conf.MaxConcurrentDownloads, conf.MaxConcurrentUploads)
	// prepare reload event attributes with updatable configurations
	attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads)
	// prepare reload event attributes with updatable configurations
	attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads)
}

// reloadShutdownTimeout updates configuration with daemon shutdown timeout option
// and updates the passed attributes
func (daemon *Daemon) reloadShutdownTimeout(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	if conf.IsValueSet("shutdown-timeout") {
		daemon.configStore.ShutdownTimeout = conf.ShutdownTimeout
		logrus.Debugf("Reset Shutdown Timeout: %d", daemon.configStore.ShutdownTimeout)
	}

	// prepare reload event attributes with updatable configurations
	attributes["shutdown-timeout"] = fmt.Sprintf("%d", daemon.configStore.ShutdownTimeout)
}

// reloadClusterDiscovery updates configuration with cluster discovery options
// and updates the passed attributes
func (daemon *Daemon) reloadClusterDiscovery(conf *config.Config, attributes map[string]string) (err error) {
	defer func() {
		// prepare reload event attributes with updatable configurations
		attributes["cluster-store"] = conf.ClusterStore
		attributes["cluster-advertise"] = conf.ClusterAdvertise

		attributes["cluster-store-opts"] = "{}"
		if daemon.configStore.ClusterOpts != nil {
			opts, err2 := json.Marshal(conf.ClusterOpts)
			if err != nil {
				err = err2
			}
			attributes["cluster-store-opts"] = string(opts)
		}
	}()

	newAdvertise := conf.ClusterAdvertise
	newClusterStore := daemon.configStore.ClusterStore
	if conf.IsValueSet("cluster-advertise") {
		if conf.IsValueSet("cluster-store") {
			newClusterStore = conf.ClusterStore
		}
		newAdvertise, err = config.ParseClusterAdvertiseSettings(newClusterStore, conf.ClusterAdvertise)
		if err != nil && err != discovery.ErrDiscoveryDisabled {
			return err
		}
	}

	if daemon.clusterProvider != nil {
		if err := conf.IsSwarmCompatible(); err != nil {
			return err
		}
	}

	// check discovery modifications
	if !config.ModifiedDiscoverySettings(daemon.configStore, newClusterStore, newAdvertise, conf.ClusterOpts) {
		return nil
	}

	// enable discovery for the first time if it was not previously enabled
	if daemon.discoveryWatcher == nil {
		discoveryWatcher, err := discovery.Init(newClusterStore, newAdvertise, conf.ClusterOpts)
		if err != nil {
			return fmt.Errorf("failed to initialize discovery: %v", err)
		}
		daemon.discoveryWatcher = discoveryWatcher
	} else if err == discovery.ErrDiscoveryDisabled {
		// disable discovery if it was previously enabled and it's disabled now
		daemon.discoveryWatcher.Stop()
	} else if err = daemon.discoveryWatcher.Reload(conf.ClusterStore, newAdvertise, conf.ClusterOpts); err != nil {
		// reload discovery
		return err
	}

	daemon.configStore.ClusterStore = newClusterStore
	daemon.configStore.ClusterOpts = conf.ClusterOpts
	daemon.configStore.ClusterAdvertise = newAdvertise

	if daemon.netController == nil {
		return nil
	}
	netOptions, err := daemon.networkOptions(daemon.configStore, daemon.PluginStore, nil)
	if err != nil {
		logrus.WithError(err).Warn("failed to get options with network controller")
		return nil
	}
	err = daemon.netController.ReloadConfiguration(netOptions...)
	if err != nil {
		logrus.Warnf("Failed to reload configuration with network controller: %v", err)
	}
	return nil
}

// reloadLabels updates configuration with engine labels
// and updates the passed attributes
func (daemon *Daemon) reloadLabels(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("labels") {
		daemon.configStore.Labels = conf.Labels
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.Labels != nil {
		labels, err := json.Marshal(daemon.configStore.Labels)
		if err != nil {
			return err
		}
		attributes["labels"] = string(labels)
	} else {
		attributes["labels"] = "[]"
	}

	return nil
}

// reloadAllowNondistributableArtifacts updates the configuration with allow-nondistributable-artifacts options
// and updates the passed attributes.
func (daemon *Daemon) reloadAllowNondistributableArtifacts(conf *config.Config, attributes map[string]string) error {
	// Update corresponding configuration.
	if conf.IsValueSet("allow-nondistributable-artifacts") {
		daemon.configStore.AllowNondistributableArtifacts = conf.AllowNondistributableArtifacts
		if err := daemon.RegistryService.LoadAllowNondistributableArtifacts(conf.AllowNondistributableArtifacts); err != nil {
			return err
		}
	}

	// Prepare reload event attributes with updatable configurations.
	if daemon.configStore.AllowNondistributableArtifacts != nil {
		v, err := json.Marshal(daemon.configStore.AllowNondistributableArtifacts)
		if err != nil {
			return err
		}
		attributes["allow-nondistributable-artifacts"] = string(v)
	} else {
		attributes["allow-nondistributable-artifacts"] = "[]"
	}

	return nil
}

// reloadInsecureRegistries updates configuration with insecure registry option
// and updates the passed attributes
func (daemon *Daemon) reloadInsecureRegistries(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("insecure-registries") {
		daemon.configStore.InsecureRegistries = conf.InsecureRegistries
		if err := daemon.RegistryService.LoadInsecureRegistries(conf.InsecureRegistries); err != nil {
			return err
		}
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.InsecureRegistries != nil {
		insecureRegistries, err := json.Marshal(daemon.configStore.InsecureRegistries)
		if err != nil {
			return err
		}
		attributes["insecure-registries"] = string(insecureRegistries)
	} else {
		attributes["insecure-registries"] = "[]"
	}

	return nil
}

// reloadRegistryMirrors updates configuration with registry mirror options
// and updates the passed attributes
func (daemon *Daemon) reloadRegistryMirrors(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("registry-mirrors") {
		daemon.configStore.Mirrors = conf.Mirrors
		if err := daemon.RegistryService.LoadMirrors(conf.Mirrors); err != nil {
			return err
		}
	}

	// prepare reload event attributes with updatable configurations
	if daemon.configStore.Mirrors != nil {
		mirrors, err := json.Marshal(daemon.configStore.Mirrors)
		if err != nil {
			return err
		}
		attributes["registry-mirrors"] = string(mirrors)
	} else {
		attributes["registry-mirrors"] = "[]"
	}

	return nil
}

// reloadLiveRestore updates configuration with live restore option
// and updates the passed attributes
func (daemon *Daemon) reloadLiveRestore(conf *config.Config, attributes map[string]string) error {
	// update corresponding configuration
	if conf.IsValueSet("live-restore") {
		daemon.configStore.LiveRestoreEnabled = conf.LiveRestoreEnabled
	}

	// prepare reload event attributes with updatable configurations
	attributes["live-restore"] = fmt.Sprintf("%t", daemon.configStore.LiveRestoreEnabled)
	return nil
}

// reloadNetworkDiagnosticPort updates the network controller starting the diagnostic if the config is valid
func (daemon *Daemon) reloadNetworkDiagnosticPort(conf *config.Config, attributes map[string]string) error {
	if conf == nil || daemon.netController == nil || !conf.IsValueSet("network-diagnostic-port") ||
		conf.NetworkDiagnosticPort < 1 || conf.NetworkDiagnosticPort > 65535 {
		// If there is no config make sure that the diagnostic is off
		if daemon.netController != nil {
			daemon.netController.StopDiagnostic()
		}
		return nil
	}
	// Enable the network diagnostic if the flag is set with a valid port within the range
	logrus.WithFields(logrus.Fields{"port": conf.NetworkDiagnosticPort, "ip": "127.0.0.1"}).Warn("Starting network diagnostic server")
	daemon.netController.StartDiagnostic(conf.NetworkDiagnosticPort)

	return nil
}

// reloadFeatures updates configuration with enabled/disabled features
func (daemon *Daemon) reloadFeatures(conf *config.Config, attributes map[string]string) {
	// update corresponding configuration
	// note that we allow features option to be entirely unset
	daemon.configStore.Features = conf.Features

	// prepare reload event attributes with updatable configurations
	attributes["features"] = fmt.Sprintf("%v", daemon.configStore.Features)
}
<|endoftext|>


<commit_before>package cliapp

import "github.com/mitchellh/cli"
import "github.com/bpicode/fritzctl/configurer"
import "github.com/bpicode/fritzctl/assert"

type configureCommand struct {
}

func (cmd *configureCommand) Help() string {
	return "Walk through the configuration of fritzctl"
}

func (cmd *configureCommand) Synopsis() string {
	return "Configure fritzctl"
}

func (cmd *configureCommand) Run(args []string) int {
	cli := configurer.New()
	cli.ApplyDefaults(configurer.Defaults())
	cli.Obtain()
	err := cli.Write()
	assert.NoError(err, "Error writing configuration file:", err)
	return 0
}

func configure() (cli.Command, error) {
	p := configureCommand{}
	return &p, nil
}
<commit_msg>improve help message<commit_after>package cliapp

import "github.com/mitchellh/cli"
import "github.com/bpicode/fritzctl/configurer"
import "github.com/bpicode/fritzctl/assert"

import "strings"

type configureCommand struct {
}

func (cmd *configureCommand) Help() string {
	return strings.Join([]string{
		"Walk through the configuration of fritzctl interactively.",
		"Configuration file is saved at the end of the survey.",
		"Run fritzctl with administrator privileges if the configuration file cannot be saved by a normal user.",
	}, "\n")
}

func (cmd *configureCommand) Synopsis() string {
	return "Configure fritzctl"
}

func (cmd *configureCommand) Run(args []string) int {
	cli := configurer.New()
	cli.ApplyDefaults(configurer.Defaults())
	cli.Obtain()
	err := cli.Write()
	assert.NoError(err, "Error writing configuration file:", err)
	return 0
}

func configure() (cli.Command, error) {
	p := configureCommand{}
	return &p, nil
}
<|endoftext|>


<commit_before>package anomalyFilters

import (
	"fmt"
	"strings"

	"github.com/trackit/trackit-server/costs/anomalies/anomalyType"
)

type (
	// product will only show entries in the
	// given string array.
	//
	// Format (array of string):
	// ["AmazonEC2", "AmazonES"]
	product struct{}
)

func init() {
	registerFilter("product", product{})
}

// valid verifies the validity of the data
func (f product) valid(data interface{}) error {
	if typed, ok := data.([]interface{}); !ok {
		return fmt.Errorf("%s: not an array", filtersName[f])
	} else if len(typed) == 0 {
		return fmt.Errorf("%s: empty array", filtersName[f])
	} else {
		for i := range typed {
			if _, ok := typed[i].(string); !ok {
				return fmt.Errorf("%s: not an array of string", filtersName[f])
			}
		}
	}
	return nil
}

// apply applies the filter to the anomaly and returns the result.
func (f product) apply(data interface{}, an anomalyType.ProductAnomaly, product string) bool {
	if typed, ok := data.([]interface{}); !ok {
	} else {
		for _, p := range typed {
			if strings.ToLower(product) == strings.ToLower(p) {
				return false
			}
		}
		return true
	}
	return false
}
<commit_msg>Product filter: containing instead of comparing<commit_after>package anomalyFilters

import (
	"fmt"
	"strings"

	"github.com/trackit/trackit-server/costs/anomalies/anomalyType"
)

type (
	// product will only show entries in the
	// given string array.
	//
	// Format (array of string):
	// ["AmazonEC2", "AmazonES"]
	product struct{}
)

func init() {
	registerFilter("product", product{})
}

// valid verifies the validity of the data
func (f product) valid(data interface{}) error {
	if typed, ok := data.([]interface{}); !ok {
		return fmt.Errorf("%s: not an array", filtersName[f])
	} else if len(typed) == 0 {
		return fmt.Errorf("%s: empty array", filtersName[f])
	} else {
		for i := range typed {
			if _, ok := typed[i].(string); !ok {
				return fmt.Errorf("%s: not an array of string", filtersName[f])
			}
		}
	}
	return nil
}

// apply applies the filter to the anomaly and returns the result.
func (f product) apply(data interface{}, an anomalyType.ProductAnomaly, product string) bool {
	if typed, ok := data.([]interface{}); !ok {
	} else {
		for _, p := range typed {
			if ps, ok := p.(string); ok && strings.Contains(strings.ToLower(product), strings.ToLower(ps)) {
				return false
			}
		}
		return true
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interp

import (
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"

	"mvdan.cc/sh/v3/expand"
)

// FromModuleContext returns the ModuleCtx value stored in ctx, if any.
func FromModuleContext(ctx context.Context) (ModuleCtx, bool) {
	mc, ok := ctx.Value(moduleCtxKey{}).(ModuleCtx)
	return mc, ok
}

type moduleCtxKey struct{}

// ModuleCtx is the data passed to all the module functions via a context value.
// It contains some of the current state of the Runner, as well as some fields
// necessary to implement some of the modules.
type ModuleCtx struct {
	Env         expand.Environ
	Dir         string
	Stdin       io.Reader
	Stdout      io.Writer
	Stderr      io.Writer
	KillTimeout time.Duration
}

// UnixPath fixes absolute unix paths on Windows, for example converting
// "C:\\CurDir\\dev\\null" to "/dev/null".
func (mc ModuleCtx) UnixPath(path string) string {
	if runtime.GOOS != "windows" {
		return path
	}
	path = strings.TrimPrefix(path, mc.Dir)
	return strings.Replace(path, `\`, `/`, -1)
}

// ExecModule is the module responsible for executing a simple command. It is
// executed for all CallExpr nodes where the first argument is neither a
// declared function nor a builtin.
//
// Use a return error of type ExitStatus to set the exit status. A nil error has
// the same effect as ExitStatus(0). If the error is of any other type, the
// interpreter will come to a stop.
type ExecModule = func(ctx context.Context, args []string) error

func DefaultExec(ctx context.Context, args []string) error {
	mc, _ := FromModuleContext(ctx)
	path, err := LookPath(mc.Env, args[0])
	if err != nil {
		fmt.Fprintln(mc.Stderr, err)
		return ExitStatus(127)
	}
	cmd := exec.Cmd{
		Path:   path,
		Args:   args,
		Env:    execEnv(mc.Env),
		Dir:    mc.Dir,
		Stdin:  mc.Stdin,
		Stdout: mc.Stdout,
		Stderr: mc.Stderr,
	}

	err = cmd.Start()
	if err == nil {
		if done := ctx.Done(); done != nil {
			go func() {
				<-done

				if mc.KillTimeout <= 0 || runtime.GOOS == "windows" {
					_ = cmd.Process.Signal(os.Kill)
					return
				}

				// TODO: don't temporarily leak this goroutine
				// if the program stops itself with the
				// interrupt.
				go func() {
					time.Sleep(mc.KillTimeout)
					_ = cmd.Process.Signal(os.Kill)
				}()
				_ = cmd.Process.Signal(os.Interrupt)
			}()
		}

		err = cmd.Wait()
	}

	switch x := err.(type) {
	case *exec.ExitError:
		// started, but errored - default to 1 if OS
		// doesn't have exit statuses
		if status, ok := x.Sys().(syscall.WaitStatus); ok {
			if status.Signaled() && ctx.Err() != nil {
				return ctx.Err()
			}
			return ExitStatus(status.ExitStatus())
		}
		return ExitStatus(1)
	case *exec.Error:
		// did not start
		fmt.Fprintf(mc.Stderr, "%v\n", err)
		return ExitStatus(127)
	default:
		return err
	}
}

func checkStat(dir, file string) (string, error) {
	if !filepath.IsAbs(file) {
		file = filepath.Join(dir, file)
	}
	info, err := os.Stat(file)
	if err != nil {
		return "", err
	}
	m := info.Mode()
	if m.IsDir() {
		return "", fmt.Errorf("is a directory")
	}
	if runtime.GOOS != "windows" && m&0111 == 0 {
		return "", fmt.Errorf("permission denied")
	}
	return file, nil
}

func winHasExt(file string) bool {
	i := strings.LastIndex(file, ".")
	if i < 0 {
		return false
	}
	return strings.LastIndexAny(file, `:\/`) < i
}

func findExecutable(dir, file string, exts []string) (string, error) {
	if len(exts) == 0 {
		// non-windows
		return checkStat(dir, file)
	}
	if winHasExt(file) {
		if file, err := checkStat(dir, file); err == nil {
			return file, nil
		}
	}
	for _, e := range exts {
		f := file + e
		if f, err := checkStat(dir, f); err == nil {
			return f, nil
		}
	}
	return "", fmt.Errorf("not found")
}

func driveLetter(c byte) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}

// splitList is like filepath.SplitList, but always using the unix path
// list separator ':'. On Windows, it also makes sure not to split
// [A-Z]:[/\].
func splitList(path string) []string {
	if path == "" {
		return []string{""}
	}
	list := strings.Split(path, ":")
	if runtime.GOOS != "windows" {
		return list
	}
	// join "C", "/foo" into "C:/foo"
	var fixed []string
	for i := 0; i < len(list); i++ {
		s := list[i]
		switch {
		case len(s) != 1, !driveLetter(s[0]):
		case i+1 >= len(list):
			// last element
		case strings.IndexAny(list[i+1], `/\`) != 0:
			// next element doesn't start with / or \
		default:
			fixed = append(fixed, s+":"+list[i+1])
			i++
			continue
		}
		fixed = append(fixed, s)
	}
	return fixed
}

// LookPath is similar to os/exec.LookPath, with the difference that it uses the
// provided environment. env is used to fetch relevant environment variables
// such as PWD and PATH.
//
// If no error is returned, the returned path must be valid.
func LookPath(env expand.Environ, file string) (string, error) {
	pathList := splitList(env.Get("PATH").String())
	chars := `/`
	if runtime.GOOS == "windows" {
		chars = `:\/`
		// so that "foo" always tries "./foo"
		pathList = append([]string{"."}, pathList...)
	}
	exts := pathExts(env)
	dir := env.Get("PWD").String()
	if strings.ContainsAny(file, chars) {
		return findExecutable(dir, file, exts)
	}
	for _, elem := range pathList {
		var path string
		switch elem {
		case "", ".":
			// otherwise "foo" won't be "./foo"
			path = "." + string(filepath.Separator) + file
		default:
			path = filepath.Join(elem, file)
		}
		if f, err := findExecutable(dir, path, exts); err == nil {
			return f, nil
		}
	}
	return "", fmt.Errorf("%q: executable file not found in $PATH", file)
}

func pathExts(env expand.Environ) []string {
	if runtime.GOOS != "windows" {
		return nil
	}
	pathext := env.Get("PATHEXT").String()
	if pathext == "" {
		return []string{".com", ".exe", ".bat", ".cmd"}
	}
	var exts []string
	for _, e := range strings.Split(strings.ToLower(pathext), `;`) {
		if e == "" {
			continue
		}
		if e[0] != '.' {
			e = "." + e
		}
		exts = append(exts, e)
	}
	return exts
}

// OpenModule is the module responsible for opening a file. It is
// executed for all files that are opened directly by the shell, such as
// in redirects. Files opened by executed programs are not included.
//
// The path parameter is absolute and has been cleaned.
//
// Use a return error of type *os.PathError to have the error printed to
// stderr and the exit status set to 1. If the error is of any other type, the
// interpreter will come to a stop.
type OpenModule = func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)

func DefaultOpen(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
	return os.OpenFile(path, flag, perm)
}

func OpenDevImpls(next OpenModule) OpenModule {
	return func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
		mc, _ := FromModuleContext(ctx)
		switch mc.UnixPath(path) {
		case "/dev/null":
			return devNull{}, nil
		}
		return next(ctx, path, flag, perm)
	}
}

var _ io.ReadWriteCloser = devNull{}

type devNull struct{}

func (devNull) Read(p []byte) (int, error)  { return 0, io.EOF }
func (devNull) Write(p []byte) (int, error) { return len(p), nil }
func (devNull) Close() error                { return nil }
<commit_msg>interp: don't use type aliases for functions<commit_after>// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package interp

import (
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"

	"mvdan.cc/sh/v3/expand"
)

// FromModuleContext returns the ModuleCtx value stored in ctx, if any.
func FromModuleContext(ctx context.Context) (ModuleCtx, bool) {
	mc, ok := ctx.Value(moduleCtxKey{}).(ModuleCtx)
	return mc, ok
}

type moduleCtxKey struct{}

// ModuleCtx is the data passed to all the module functions via a context value.
// It contains some of the current state of the Runner, as well as some fields
// necessary to implement some of the modules.
type ModuleCtx struct {
	Env         expand.Environ
	Dir         string
	Stdin       io.Reader
	Stdout      io.Writer
	Stderr      io.Writer
	KillTimeout time.Duration
}

// UnixPath fixes absolute unix paths on Windows, for example converting
// "C:\\CurDir\\dev\\null" to "/dev/null".
func (mc ModuleCtx) UnixPath(path string) string {
	if runtime.GOOS != "windows" {
		return path
	}
	path = strings.TrimPrefix(path, mc.Dir)
	return strings.Replace(path, `\`, `/`, -1)
}

// ExecModule is the module responsible for executing a simple command. It is
// executed for all CallExpr nodes where the first argument is neither a
// declared function nor a builtin.
//
// Use a return error of type ExitStatus to set the exit status. A nil error has
// the same effect as ExitStatus(0). If the error is of any other type, the
// interpreter will come to a stop.
type ExecModule func(ctx context.Context, args []string) error

func DefaultExec(ctx context.Context, args []string) error {
	mc, _ := FromModuleContext(ctx)
	path, err := LookPath(mc.Env, args[0])
	if err != nil {
		fmt.Fprintln(mc.Stderr, err)
		return ExitStatus(127)
	}
	cmd := exec.Cmd{
		Path:   path,
		Args:   args,
		Env:    execEnv(mc.Env),
		Dir:    mc.Dir,
		Stdin:  mc.Stdin,
		Stdout: mc.Stdout,
		Stderr: mc.Stderr,
	}

	err = cmd.Start()
	if err == nil {
		if done := ctx.Done(); done != nil {
			go func() {
				<-done

				if mc.KillTimeout <= 0 || runtime.GOOS == "windows" {
					_ = cmd.Process.Signal(os.Kill)
					return
				}

				// TODO: don't temporarily leak this goroutine
				// if the program stops itself with the
				// interrupt.
				go func() {
					time.Sleep(mc.KillTimeout)
					_ = cmd.Process.Signal(os.Kill)
				}()
				_ = cmd.Process.Signal(os.Interrupt)
			}()
		}

		err = cmd.Wait()
	}

	switch x := err.(type) {
	case *exec.ExitError:
		// started, but errored - default to 1 if OS
		// doesn't have exit statuses
		if status, ok := x.Sys().(syscall.WaitStatus); ok {
			if status.Signaled() && ctx.Err() != nil {
				return ctx.Err()
			}
			return ExitStatus(status.ExitStatus())
		}
		return ExitStatus(1)
	case *exec.Error:
		// did not start
		fmt.Fprintf(mc.Stderr, "%v\n", err)
		return ExitStatus(127)
	default:
		return err
	}
}

func checkStat(dir, file string) (string, error) {
	if !filepath.IsAbs(file) {
		file = filepath.Join(dir, file)
	}
	info, err := os.Stat(file)
	if err != nil {
		return "", err
	}
	m := info.Mode()
	if m.IsDir() {
		return "", fmt.Errorf("is a directory")
	}
	if runtime.GOOS != "windows" && m&0111 == 0 {
		return "", fmt.Errorf("permission denied")
	}
	return file, nil
}

func winHasExt(file string) bool {
	i := strings.LastIndex(file, ".")
	if i < 0 {
		return false
	}
	return strings.LastIndexAny(file, `:\/`) < i
}

func findExecutable(dir, file string, exts []string) (string, error) {
	if len(exts) == 0 {
		// non-windows
		return checkStat(dir, file)
	}
	if winHasExt(file) {
		if file, err := checkStat(dir, file); err == nil {
			return file, nil
		}
	}
	for _, e := range exts {
		f := file + e
		if f, err := checkStat(dir, f); err == nil {
			return f, nil
		}
	}
	return "", fmt.Errorf("not found")
}

func driveLetter(c byte) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}

// splitList is like filepath.SplitList, but always using the unix path
// list separator ':'. On Windows, it also makes sure not to split
// [A-Z]:[/\].
func splitList(path string) []string {
	if path == "" {
		return []string{""}
	}
	list := strings.Split(path, ":")
	if runtime.GOOS != "windows" {
		return list
	}
	// join "C", "/foo" into "C:/foo"
	var fixed []string
	for i := 0; i < len(list); i++ {
		s := list[i]
		switch {
		case len(s) != 1, !driveLetter(s[0]):
		case i+1 >= len(list):
			// last element
		case strings.IndexAny(list[i+1], `/\`) != 0:
			// next element doesn't start with / or \
		default:
			fixed = append(fixed, s+":"+list[i+1])
			i++
			continue
		}
		fixed = append(fixed, s)
	}
	return fixed
}

// LookPath is similar to os/exec.LookPath, with the difference that it uses the
// provided environment. env is used to fetch relevant environment variables
// such as PWD and PATH.
//
// If no error is returned, the returned path must be valid.
func LookPath(env expand.Environ, file string) (string, error) {
	pathList := splitList(env.Get("PATH").String())
	chars := `/`
	if runtime.GOOS == "windows" {
		chars = `:\/`
		// so that "foo" always tries "./foo"
		pathList = append([]string{"."}, pathList...)
	}
	exts := pathExts(env)
	dir := env.Get("PWD").String()
	if strings.ContainsAny(file, chars) {
		return findExecutable(dir, file, exts)
	}
	for _, elem := range pathList {
		var path string
		switch elem {
		case "", ".":
			// otherwise "foo" won't be "./foo"
			path = "." + string(filepath.Separator) + file
		default:
			path = filepath.Join(elem, file)
		}
		if f, err := findExecutable(dir, path, exts); err == nil {
			return f, nil
		}
	}
	return "", fmt.Errorf("%q: executable file not found in $PATH", file)
}

func pathExts(env expand.Environ) []string {
	if runtime.GOOS != "windows" {
		return nil
	}
	pathext := env.Get("PATHEXT").String()
	if pathext == "" {
		return []string{".com", ".exe", ".bat", ".cmd"}
	}
	var exts []string
	for _, e := range strings.Split(strings.ToLower(pathext), `;`) {
		if e == "" {
			continue
		}
		if e[0] != '.' {
			e = "." + e
		}
		exts = append(exts, e)
	}
	return exts
}

// OpenModule is the module responsible for opening a file. It is
// executed for all files that are opened directly by the shell, such as
// in redirects. Files opened by executed programs are not included.
//
// The path parameter is absolute and has been cleaned.
//
// Use a return error of type *os.PathError to have the error printed to
// stderr and the exit status set to 1. If the error is of any other type, the
// interpreter will come to a stop.
type OpenModule func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)

func DefaultOpen(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
	return os.OpenFile(path, flag, perm)
}

func OpenDevImpls(next OpenModule) OpenModule {
	return func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
		mc, _ := FromModuleContext(ctx)
		switch mc.UnixPath(path) {
		case "/dev/null":
			return devNull{}, nil
		}
		return next(ctx, path, flag, perm)
	}
}

var _ io.ReadWriteCloser = devNull{}

type devNull struct{}

func (devNull) Read(p []byte) (int, error)  { return 0, io.EOF }
func (devNull) Write(p []byte) (int, error) { return len(p), nil }
func (devNull) Close() error                { return nil }
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"

	"github.com/gorilla/mux"
	"github.com/unixvoid/glogger"
	"golang.org/x/crypto/sha3"
	"gopkg.in/redis.v5"
)

func handlerdynamic(w http.ResponseWriter, r *http.Request, redisClient *redis.Client) {
	vars := mux.Vars(r)
	dataId := vars["dataId"]
	secureKey := vars["secureKey"]

	// hash the token that is passed
	fileIdHash := sha3.Sum512([]byte(dataId))
	longFileId := fmt.Sprintf("%x", fileIdHash)

	// get the client's ip
	ip := strings.Split(r.RemoteAddr, ":")[0]

	// set client as localhost if it comes from localhost
	if ip == "[" {
		ip = "localhost"
	}

	// pull the client's real header if proxied. (if X-Forwarded-For is set)
	realIp := r.Header.Get("X-Forwarded-For")
	if realIp != "" {
		ip = realIp
	}

	// try and pull the data from redis
	val, err := redisClient.Get(longFileId).Result()
	encryptedFilename, err := redisClient.HGet(fmt.Sprintf("meta:%s", longFileId), "filename").Result()
	if err != nil {
		// handle the error if the token does not exist
		glogger.Debug.Printf("data does not exist %s :: from: %s\n", dataId, ip)
		fmt.Fprintf(w, "token not found")
	} else {
		// token exists, try and decrypt

		// serve up the content to the client
		glogger.Debug.Printf("Responsing to %s :: from: %s\n", dataId, ip)

		// DEBUG
		//glogger.Debug.Printf("file id:    %s\n", dataId)
		//glogger.Debug.Printf("secure key: %s\n", secureKey)
		//glogger.Debug.Printf("val:        %s\n", val)

		// decrypt
		plainFile, err := decrypt([]byte(secureKey), []byte(val))
		if err != nil {
			glogger.Debug.Println("unauthorized access.")
			// error decrypting file, looks like the wrong key
			w.WriteHeader(http.StatusForbidden)
			return
		}
		decodeVal, _ := base64.StdEncoding.DecodeString(string(plainFile))

		file, _ := os.Create("tmpfile")
		io.WriteString(file, string(decodeVal))
		file.Close()

		// unencrypt filename
		filename, err := decrypt([]byte(secureKey), []byte(encryptedFilename))
		if err != nil {
			glogger.Debug.Println("error decrypting filename")
			panic(err.Error())
		}

		// dont add the filename header to links
		if string(filename) != "bitnuke:link" {
			finalFname := fmt.Sprintf("INLINE; filename=%s", filename)
			w.Header().Set("Content-Disposition", finalFname)
		}
		http.ServeFile(w, r, "tmpfile")
		os.Remove("tmpfile")
	}
}
<commit_msg>Add forced garbage collection<commit_after>package main

import (
	"encoding/base64"
	"fmt"
	"io"
	"net/http"
	"os"
	"runtime"
	"strings"

	"github.com/gorilla/mux"
	"github.com/unixvoid/glogger"
	"golang.org/x/crypto/sha3"
	"gopkg.in/redis.v5"
)

func handlerdynamic(w http.ResponseWriter, r *http.Request, redisClient *redis.Client) {
	vars := mux.Vars(r)
	dataId := vars["dataId"]
	secureKey := vars["secureKey"]

	// hash the token that is passed
	fileIdHash := sha3.Sum512([]byte(dataId))
	longFileId := fmt.Sprintf("%x", fileIdHash)

	// get the client's ip
	ip := strings.Split(r.RemoteAddr, ":")[0]

	// set client as localhost if it comes from localhost
	if ip == "[" {
		ip = "localhost"
	}

	// pull the client's real header if proxied. (if X-Forwarded-For is set)
	realIp := r.Header.Get("X-Forwarded-For")
	if realIp != "" {
		ip = realIp
	}

	// try and pull the data from redis
	val, err := redisClient.Get(longFileId).Result()
	encryptedFilename, err := redisClient.HGet(fmt.Sprintf("meta:%s", longFileId), "filename").Result()
	if err != nil {
		// handle the error if the token does not exist
		glogger.Debug.Printf("data does not exist %s :: from: %s\n", dataId, ip)
		fmt.Fprintf(w, "token not found")
	} else {
		// token exists, try and decrypt

		// serve up the content to the client
		glogger.Debug.Printf("Responsing to %s :: from: %s\n", dataId, ip)

		// DEBUG
		//glogger.Debug.Printf("file id:    %s\n", dataId)
		//glogger.Debug.Printf("secure key: %s\n", secureKey)
		//glogger.Debug.Printf("val:        %s\n", val)

		// decrypt
		plainFile, err := decrypt([]byte(secureKey), []byte(val))
		if err != nil {
			glogger.Debug.Println("unauthorized access.")
			// error decrypting file, looks like the wrong key
			w.WriteHeader(http.StatusForbidden)
			return
		}
		decodeVal, _ := base64.StdEncoding.DecodeString(string(plainFile))

		// force garbage collection
		runtime.GC()

		file, _ := os.Create("tmpfile")
		io.WriteString(file, string(decodeVal))
		file.Close()

		// force garbage collection
		runtime.GC()

		// unencrypt filename
		filename, err := decrypt([]byte(secureKey), []byte(encryptedFilename))
		if err != nil {
			glogger.Debug.Println("error decrypting filename")
			panic(err.Error())
		}

		// dont add the filename header to links
		if string(filename) != "bitnuke:link" {
			finalFname := fmt.Sprintf("INLINE; filename=%s", filename)
			w.Header().Set("Content-Disposition", finalFname)
		}
		http.ServeFile(w, r, "tmpfile")
		os.Remove("tmpfile")
	}
}
<|endoftext|>


<commit_before>// +build linux

package send

import (
	"fmt"
	"log"
	"os"

	"github.com/coreos/go-systemd/journal"
	"github.com/tychoish/grip/level"
	"github.com/tychoish/grip/message"
)

type systemdJournal struct {
	options map[string]string
	*base
}

// NewJournaldLogger creates a Sender object that writes log messages
// to the system's systemd journald logging facility. If there's an
// error with the sending to the journald, messages fallback to
// writing to standard output.
func NewSystemdLogger(name string, l LevelInfo) (Sender, error) {
	return setup(MakeSystemdLogger(), name, l)
}

// MakeSystemdLogger constructs an unconfigured systemd journald
// logger. Pass to Journaler.SetSender or call SetName before using.
func MakeSystemdLogger() Sender {
	s := &systemdJournal{
		options: make(map[string]string),
		base:    newBase(""),
	}

	fallback := log.New(os.Stdout, "", log.LstdFlags)
	s.SetErrorHandler(ErrorHandlerFromLogger(fallback))

	s.reset = func() {
		fallback.SetPrefix(fmt.Sprintf("[%s]", s.Name()))
	}

	return s
}

func (s *systemdJournal) Close() error { return nil }

func (s *systemdJournal) Send(m message.Composer) {
	if s.level.ShouldLog(m) {
		err := journal.Send(m.String(), s.level.convertPrioritySystemd(m.Priority()), s.options)
		if err != nil {
			s.errHandler(err, m)
		}
	}
}

func (l LevelInfo) convertPrioritySystemd(p level.Priority) journal.Priority {
	switch p {
	case level.Emergency:
		return journal.PriEmerg
	case level.Alert:
		return journal.PriAlert
	case level.Critical:
		return journal.PriCrit
	case level.Error:
		return journal.PriErr
	case level.Warning:
		return journal.PriWarning
	case level.Notice:
		return journal.PriNotice
	case level.Info:
		return journal.PriInfo
	case level.Debug, level.Trace:
		return journal.PriDebug
	default:
		return l.convertPrioritySystemd(l.Default)
	}
}
<commit_msg>fix systemd sender on linux<commit_after>// +build linux

package send

import (
	"fmt"
	"log"
	"os"

	"github.com/coreos/go-systemd/journal"
	"github.com/tychoish/grip/level"
	"github.com/tychoish/grip/message"
)

type systemdJournal struct {
	options map[string]string
	*Base
}

// NewJournaldLogger creates a Sender object that writes log messages
// to the system's systemd journald logging facility. If there's an
// error with the sending to the journald, messages fallback to
// writing to standard output.
func NewSystemdLogger(name string, l LevelInfo) (Sender, error) {
	return setup(MakeSystemdLogger(), name, l)
}

// MakeSystemdLogger constructs an unconfigured systemd journald
// logger. Pass to Journaler.SetSender or call SetName before using.
func MakeSystemdLogger() Sender {
	s := &systemdJournal{
		options: make(map[string]string),
		Base:    NewBase(""),
	}

	fallback := log.New(os.Stdout, "", log.LstdFlags)
	s.SetErrorHandler(ErrorHandlerFromLogger(fallback))

	s.reset = func() {
		fallback.SetPrefix(fmt.Sprintf("[%s]", s.Name()))
	}

	return s
}

func (s *systemdJournal) Close() error { return nil }

func (s *systemdJournal) Send(m message.Composer) {
	if s.level.ShouldLog(m) {
		err := journal.Send(m.String(), s.level.convertPrioritySystemd(m.Priority()), s.options)
		if err != nil {
			s.errHandler(err, m)
		}
	}
}

func (l LevelInfo) convertPrioritySystemd(p level.Priority) journal.Priority {
	switch p {
	case level.Emergency:
		return journal.PriEmerg
	case level.Alert:
		return journal.PriAlert
	case level.Critical:
		return journal.PriCrit
	case level.Error:
		return journal.PriErr
	case level.Warning:
		return journal.PriWarning
	case level.Notice:
		return journal.PriNotice
	case level.Info:
		return journal.PriInfo
	case level.Debug, level.Trace:
		return journal.PriDebug
	default:
		return l.convertPrioritySystemd(l.Default)
	}
}
<|endoftext|>


<commit_before>package command

import (
	"strings"

	"github.com/mohae/cli"
	"github.com/mohae/contour"
	"github.com/mohae/peu/app"
)

// DCommand is a Command implementation for decompression
type DCommand struct {
	UI cli.Ui
}

// Help prints the help text for the run sub-command.
func (d *DCommand) Help() string {
	helpText := `
Usage: peu d [flags] <filelist string...>

d will take a 1 or more files and decompress them. If the -o flag is not
passed, the files will be decompressed in place. The algorithm that is
used for decompression is determined by matching magic numbers. If a match
is not found, the algorithm is not supported and an error will be returned.

    $ peu d example.txt

    $ peu d -o=out/path example.txt

peu supports 1 flag:

    -o=output/path    save the output of the command to the path specified.
`
	return strings.TrimSpace(helpText)
}

// Run runs the d command; the args are a variadic list of filenames to process.
func (c *DCommand) Run(args []string) int {
	// set up the command flags
	contour.SetUsage(func() { c.UI.Output(c.Help()) })
	// Filter the flags from the args and update the config with them.
	// The args remaining after being filtered are returned.
	filteredArgs, err := contour.FilterArgs(args)
	if err != nil {
		c.UI.Error(err.Error())
		return 1
	}
	// Run the command in the package.
	message, err := app.D(filteredArgs)
	if err != nil {
		c.UI.Error(err.Error())
		return 1
	}
	c.UI.Output(message)
	return 0
}

// Synopsis provides a precis of the hello command.
func (c *CCommand) Synopsis() string {
	ret := `Compresses files using the specified algorithm
`
	return ret
}
<commit_msg>CCommand -> DCommand in d.go<commit_after>package command

import (
	"strings"

	"github.com/mohae/cli"
	"github.com/mohae/contour"
	"github.com/mohae/peu/app"
)

// DCommand is a Command implementation for decompression
type DCommand struct {
	UI cli.Ui
}

// Help prints the help text for the run sub-command.
func (d *DCommand) Help() string {
	helpText := `
Usage: peu d [flags] <filelist string...>

d will take a 1 or more files and decompress them. If the -o flag is not
passed, the files will be decompressed in place. The algorithm that is
used for decompression is determined by matching magic numbers. If a match
is not found, the algorithm is not supported and an error will be returned.

    $ peu d example.txt

    $ peu d -o=out/path example.txt

peu supports 1 flag:

    -o=output/path    save the output of the command to the path specified.
`
	return strings.TrimSpace(helpText)
}

// Run runs the d command; the args are a variadic list of filenames to process.
func (c *DCommand) Run(args []string) int {
	// set up the command flags
	contour.SetUsage(func() { c.UI.Output(c.Help()) })
	// Filter the flags from the args and update the config with them.
	// The args remaining after being filtered are returned.
	filteredArgs, err := contour.FilterArgs(args)
	if err != nil {
		c.UI.Error(err.Error())
		return 1
	}
	// Run the command in the package.
	message, err := app.D(filteredArgs)
	if err != nil {
		c.UI.Error(err.Error())
		return 1
	}
	c.UI.Output(message)
	return 0
}

// Synopsis provides a precis of the hello command.
func (c *DCommand) Synopsis() string {
	ret := `Compresses files using the specified algorithm
`
	return ret
}
<|endoftext|>


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

package rootio

import (
	"bytes"
	"encoding/binary"
	"io"
	"math"
)

type wbuff struct {
	p []byte // buffer of data to write on
	c int    // current position in buffer of data
}

func (w *wbuff) Write(p []byte) (int, error) {
	if w.c >= len(w.p) {
		return 0, io.EOF
	}
	n := copy(w.p[w.c:], p)
	w.c += n
	return n, nil
}

func (w *wbuff) WriteByte(p byte) error {
	if w.c >= len(w.p) {
		return io.EOF
	}
	w.p[w.c] = p
	w.c++
	return nil
}

// WBuffer is a write-only ROOT buffer for streaming.
type WBuffer struct {
	w      *wbuff
	err    error
	offset uint32
	refs   map[interface{}]int64
	sictx  StreamerInfoContext
}

func NewWBuffer(data []byte, refs map[interface{}]int64, offset uint32, ctx StreamerInfoContext) *WBuffer {
	if refs == nil {
		refs = make(map[interface{}]int64)
	}

	return &WBuffer{
		w:      &wbuff{p: data, c: 0},
		refs:   refs,
		offset: offset,
		sictx:  ctx,
	}
}

func (w *WBuffer) Pos() int64 {
	return int64(w.w.c)
}

func (w *WBuffer) SetByteCount(beg int64, class string) (int, error) {
	if w.err != nil {
		return 0, w.err
	}

	cur := w.w.c
	bcnt := int64(cur) - beg - 4
	w.w.c = int(beg)
	w.WriteU32(uint32(bcnt | kByteCountMask))
	w.w.c = cur

	return int(bcnt + 4), w.err
}

func (w *WBuffer) WriteVersion(vers int16) {
	w.WriteU32(0) // byte-count placeholder
	w.WriteU16(uint16(vers))
}

func (w *WBuffer) write(v []byte) {
	if w.err != nil {
		return
	}
	_, w.err = w.w.Write(v)
}

func (w *WBuffer) WriteI8(v int8) {
	if w.err != nil {
		return
	}
	w.err = w.w.WriteByte(byte(v))
}

func (w *WBuffer) WriteI16(v int16) {
	if w.err != nil {
		return
	}
	const sz = 2
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint16(w.w.p[beg:end], uint16(v))
	w.w.c += sz
}

func (w *WBuffer) WriteI32(v int32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], uint32(v))
	w.w.c += sz
}

func (w *WBuffer) WriteI64(v int64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], uint64(v))
	w.w.c += sz
}

func (w *WBuffer) WriteU8(v uint8) {
	if w.err != nil {
		return
	}
	w.err = w.w.WriteByte(byte(v))
}

func (w *WBuffer) WriteU16(v uint16) {
	if w.err != nil {
		return
	}
	const sz = 2
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint16(w.w.p[beg:end], uint16(v))
	w.w.c += sz
}

func (w *WBuffer) WriteU32(v uint32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], v)
	w.w.c += sz
}

func (w *WBuffer) WriteU64(v uint64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], v)
	w.w.c += sz
}

func (w *WBuffer) WriteF32(v float32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], math.Float32bits(v))
	w.w.c += sz
}

func (w *WBuffer) WriteF64(v float64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], math.Float64bits(v))
	w.w.c += sz
}

func (w *WBuffer) WriteBool(v bool) {
	if w.err != nil {
		return
	}
	var o uint8
	if v {
		o = 1
	}
	w.WriteU8(o)
}

func (w *WBuffer) WriteString(v string) {
	if w.err != nil {
		return
	}
	l := len(v)
	if l < 255 {
		w.WriteU8(uint8(l))
		w.write([]byte(v))
		return
	}
	w.WriteU8(255)
	w.WriteU32(uint32(l))
	w.write([]byte(v))
}

func (w *WBuffer) WriteCString(v string) {
	if w.err != nil {
		return
	}
	b := []byte(v)
	i := bytes.Index(b, []byte{0})
	switch {
	case i < 0:
		b = append(b, 0)
		w.write(b)
	default:
		b = b[:i+1]
		w.write(b)
	}
}

func (w *WBuffer) WriteStaticArrayI32(v []int32) {
	if w.err != nil {
		return
	}
	w.WriteI32(int32(len(v)))
	for _, v := range v {
		w.WriteI32(v)
	}
}

func (w *WBuffer) WriteFastArrayBool(v []bool) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteBool(v)
	}
}

func (w *WBuffer) WriteFastArrayI8(v []int8) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI8(v)
	}
}

func (w *WBuffer) WriteFastArrayI16(v []int16) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI16(v)
	}
}

func (w *WBuffer) WriteFastArrayI32(v []int32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI32(v)
	}
}

func (w *WBuffer) WriteFastArrayI64(v []int64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI64(v)
	}
}

func (w *WBuffer) WriteFastArrayU8(v []uint8) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU8(v)
	}
}

func (w *WBuffer) WriteFastArrayU16(v []uint16) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU16(v)
	}
}

func (w *WBuffer) WriteFastArrayU32(v []uint32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU32(v)
	}
}

func (w *WBuffer) WriteFastArrayU64(v []uint64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU64(v)
	}
}

func (w *WBuffer) WriteFastArrayF32(v []float32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteF32(v)
	}
}

func (w *WBuffer) WriteFastArrayF64(v []float64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteF64(v)
	}
}
<commit_msg>rootio: implement WBuffer.WriteObjectAny<commit_after>// Copyright 2018 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rootio

import (
	"bytes"
	"encoding/binary"
	"io"
	"math"
)

type wbuff struct {
	p []byte // buffer of data to write on
	c int    // current position in buffer of data
}

func (w *wbuff) Write(p []byte) (int, error) {
	if w.c >= len(w.p) {
		return 0, io.EOF
	}
	n := copy(w.p[w.c:], p)
	w.c += n
	return n, nil
}

func (w *wbuff) WriteByte(p byte) error {
	if w.c >= len(w.p) {
		return io.EOF
	}
	w.p[w.c] = p
	w.c++
	return nil
}

// WBuffer is a write-only ROOT buffer for streaming.
type WBuffer struct {
	w      *wbuff
	err    error
	offset uint32
	refs   map[interface{}]int64
	sictx  StreamerInfoContext
}

func NewWBuffer(data []byte, refs map[interface{}]int64, offset uint32, ctx StreamerInfoContext) *WBuffer {
	if refs == nil {
		refs = make(map[interface{}]int64)
	}

	return &WBuffer{
		w:      &wbuff{p: data, c: 0},
		refs:   refs,
		offset: offset,
		sictx:  ctx,
	}
}

func (w *WBuffer) Pos() int64 {
	return int64(w.w.c)
}

func (w *WBuffer) SetByteCount(beg int64, class string) (int, error) {
	if w.err != nil {
		return 0, w.err
	}

	cur := w.w.c
	bcnt := int64(cur) - beg - 4
	w.w.c = int(beg)
	w.WriteU32(uint32(bcnt | kByteCountMask))
	w.w.c = cur

	return int(bcnt + 4), w.err
}

func (w *WBuffer) WriteVersion(vers int16) {
	w.WriteU32(0) // byte-count placeholder
	w.WriteU16(uint16(vers))
}

func (w *WBuffer) WriteObjectAny(obj Object) error {
	if w.err != nil {
		return w.err
	}

	if obj == nil {
		w.WriteU32(0) // NULL pointer
		return w.err
	}

	pos := w.Pos()
	w.WriteU32(0) // placeholder for bytecount.

	bcnt, err := w.WriteClass(pos, obj)
	if err != nil {
		w.err = err
		return w.err
	}
	end := w.w.c
	w.w.c = int(pos)
	w.WriteU32(bcnt)
	w.w.c = end

	return w.err
}

func (w *WBuffer) WriteClass(beg int64, obj Object) (uint32, error) {
	if w.err != nil {
		return 0, w.err
	}

	start := w.Pos()
	if ref64, dup := w.refs[obj]; dup {
		// we've already seen this value.
		w.WriteU32(uint32(ref64) | kClassMask)
		bcnt := w.Pos() - start
		return uint32(bcnt | kByteCountMask), w.err
	}

	class := obj.Class()
	ref64, ok := w.refs[class]
	if !ok {
		w.WriteU32(uint32(kNewClassTag))
		// first time we see this type
		w.WriteCString(class)
		w.refs[class] = (start + kMapOffset) | kClassMask

		mobj := obj.(ROOTMarshaler)
		if _, err := mobj.MarshalROOT(w); err != nil {
			w.err = err
			return 0, w.err
		}

		w.refs[obj] = beg + kMapOffset
		bcnt := w.Pos() - start
		return uint32(bcnt | kByteCountMask), w.err
	}

	// first time we see this value
	w.WriteU32(uint32(ref64) | kClassMask)
	if _, err := obj.(ROOTMarshaler).MarshalROOT(w); err != nil {
		w.err = err
		return 0, w.err
	}

	w.refs[obj] = beg + kMapOffset
	bcnt := w.Pos() - start
	return uint32(bcnt | kByteCountMask), w.err
}

func (w *WBuffer) write(v []byte) {
	if w.err != nil {
		return
	}
	_, w.err = w.w.Write(v)
}

func (w *WBuffer) WriteI8(v int8) {
	if w.err != nil {
		return
	}
	w.err = w.w.WriteByte(byte(v))
}

func (w *WBuffer) WriteI16(v int16) {
	if w.err != nil {
		return
	}
	const sz = 2
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint16(w.w.p[beg:end], uint16(v))
	w.w.c += sz
}

func (w *WBuffer) WriteI32(v int32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], uint32(v))
	w.w.c += sz
}

func (w *WBuffer) WriteI64(v int64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], uint64(v))
	w.w.c += sz
}

func (w *WBuffer) WriteU8(v uint8) {
	if w.err != nil {
		return
	}
	w.err = w.w.WriteByte(byte(v))
}

func (w *WBuffer) WriteU16(v uint16) {
	if w.err != nil {
		return
	}
	const sz = 2
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint16(w.w.p[beg:end], uint16(v))
	w.w.c += sz
}

func (w *WBuffer) WriteU32(v uint32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], v)
	w.w.c += sz
}

func (w *WBuffer) WriteU64(v uint64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], v)
	w.w.c += sz
}

func (w *WBuffer) WriteF32(v float32) {
	if w.err != nil {
		return
	}
	const sz = 4
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint32(w.w.p[beg:end], math.Float32bits(v))
	w.w.c += sz
}

func (w *WBuffer) WriteF64(v float64) {
	if w.err != nil {
		return
	}
	const sz = 8
	beg := w.w.c
	end := w.w.c + sz
	binary.BigEndian.PutUint64(w.w.p[beg:end], math.Float64bits(v))
	w.w.c += sz
}

func (w *WBuffer) WriteBool(v bool) {
	if w.err != nil {
		return
	}
	var o uint8
	if v {
		o = 1
	}
	w.WriteU8(o)
}

func (w *WBuffer) WriteString(v string) {
	if w.err != nil {
		return
	}
	l := len(v)
	if l < 255 {
		w.WriteU8(uint8(l))
		w.write([]byte(v))
		return
	}
	w.WriteU8(255)
	w.WriteU32(uint32(l))
	w.write([]byte(v))
}

func (w *WBuffer) WriteCString(v string) {
	if w.err != nil {
		return
	}
	b := []byte(v)
	i := bytes.Index(b, []byte{0})
	switch {
	case i < 0:
		b = append(b, 0)
		w.write(b)
	default:
		b = b[:i+1]
		w.write(b)
	}
}

func (w *WBuffer) WriteStaticArrayI32(v []int32) {
	if w.err != nil {
		return
	}
	w.WriteI32(int32(len(v)))
	for _, v := range v {
		w.WriteI32(v)
	}
}

func (w *WBuffer) WriteFastArrayBool(v []bool) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteBool(v)
	}
}

func (w *WBuffer) WriteFastArrayI8(v []int8) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI8(v)
	}
}

func (w *WBuffer) WriteFastArrayI16(v []int16) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI16(v)
	}
}

func (w *WBuffer) WriteFastArrayI32(v []int32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI32(v)
	}
}

func (w *WBuffer) WriteFastArrayI64(v []int64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteI64(v)
	}
}

func (w *WBuffer) WriteFastArrayU8(v []uint8) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU8(v)
	}
}

func (w *WBuffer) WriteFastArrayU16(v []uint16) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU16(v)
	}
}

func (w *WBuffer) WriteFastArrayU32(v []uint32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU32(v)
	}
}

func (w *WBuffer) WriteFastArrayU64(v []uint64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteU64(v)
	}
}

func (w *WBuffer) WriteFastArrayF32(v []float32) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteF32(v)
	}
}

func (w *WBuffer) WriteFastArrayF64(v []float64) {
	if w.err != nil {
		return
	}
	for _, v := range v {
		w.WriteF64(v)
	}
}
<|endoftext|>


<commit_before>// +build !windows,cgo

package serial

// #include <termios.h>
// #include <unistd.h>
import "C"

// TODO: Maybe change to using syscall package + ioctl instead of cgo

import (
	"errors"
	"fmt"
	"os"
	"syscall"
	"time"
	//"unsafe"
)

func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
	f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
	if err != nil {
		return
	}

	fd := C.int(f.Fd())
	if C.isatty(fd) != 1 {
		f.Close()
		return nil, errors.New("File is not a tty")
	}

	var st C.struct_termios
	_, err = C.tcgetattr(fd, &st)
	if err != nil {
		f.Close()
		return nil, err
	}
	var speed C.speed_t
	switch baud {
	case 115200:
		speed = C.B115200
	case 57600:
		speed = C.B57600
	case 38400:
		speed = C.B38400
	case 19200:
		speed = C.B19200
	case 9600:
		speed = C.B9600
	case 4800:
		speed = C.B4800
	case 2400:
		speed = C.B2400
	default:
		f.Close()
		return nil, fmt.Errorf("Unknown baud rate %v", baud)
	}

	_, err = C.cfsetispeed(&st, speed)
	if err != nil {
		f.Close()
		return nil, err
	}
	_, err = C.cfsetospeed(&st, speed)
	if err != nil {
		f.Close()
		return nil, err
	}

	// Turn off break interrupts, CR->NL, Parity checks, strip, and IXON
	st.c_iflag &= ^C.tcflag_t(C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXOFF | C.IXON | C.PARMRK)

	// Select local mode, turn off parity, set to 8 bits
	st.c_cflag &= ^C.tcflag_t(C.CSIZE | C.PARENB)
	st.c_cflag |= (C.CLOCAL | C.CREAD)
	// databits
	switch databits {
	case 5:
		st.c_cflag |= C.CS5
	case 6:
		st.c_cflag |= C.CS6
	case 7:
		st.c_cflag |= C.CS7
	case 8:
		st.c_cflag |= C.CS8
	default:
		return nil, ErrBadSize
	}
	// Parity settings
	switch parity {
	case ParityNone:
		// default is no parity
	case ParityOdd:
		st.c_cflag |= C.PARENB
		st.c_cflag |= C.PARODD
	case ParityEven:
		st.c_cflag |= C.PARENB
	default:
		return nil, ErrBadParity
	}
	// Stop bits settings
	switch stopbits {
	case Stop1:
		// as is, default is 1 bit
	case Stop2:
		st.c_cflag |= C.CSTOPB
	default:
		return nil, ErrBadStopBits
	}
	// Select raw mode
	st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG)
	st.c_oflag &= ^C.tcflag_t(C.OPOST)

	// set blocking / non-blocking read
	/*
	*	http://man7.org/linux/man-pages/man3/termios.3.html
	* - Supports blocking read and read with timeout operations
	 */
	vmin, vtime := posixTimeoutValues(readTimeout)
	st.c_cc[C.VMIN] = C.cc_t(vmin)
	st.c_cc[C.VTIME] = C.cc_t(vtime)

	_, err = C.tcsetattr(fd, C.TCSANOW, &st)
	if err != nil {
		f.Close()
		return nil, err
	}

	//fmt.Println("Tweaking", name)
	r1, _, e := syscall.Syscall(syscall.SYS_FCNTL,
		uintptr(f.Fd()),
		uintptr(syscall.F_SETFL),
		uintptr(0))
	if e != 0 || r1 != 0 {
		s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1)
		f.Close()
		return nil, errors.New(s)
	}

	/*
				r1, _, e = syscall.Syscall(syscall.SYS_IOCTL,
			                uintptr(f.Fd()),
			                uintptr(0x80045402), // IOSSIOSPEED
			                uintptr(unsafe.Pointer(&baud)));
			        if e != 0 || r1 != 0 {
			                s := fmt.Sprint("Baudrate syscall error:", e, r1)
					f.Close()
		                        return nil, os.NewError(s)
				}
	*/

	return &Port{f: f}, nil
}

type Port struct {
	// We intentionly do not use an "embedded" struct so that we
	// don't export File
	f *os.File
}

func (p *Port) Read(b []byte) (n int, err error) {
	return p.f.Read(b)
}

func (p *Port) Write(b []byte) (n int, err error) {
	return p.f.Write(b)
}

// Discards data written to the port but not transmitted,
// or data received but not read
func (p *Port) Flush() error {
	_, err := C.tcflush(C.int(p.f.Fd()), C.TCIOFLUSH)
	return err
}

func (p *Port) Close() (err error) {
	return p.f.Close()
}
<commit_msg>Add support for missing baudrates between 50 and 1200<commit_after>// +build !windows,cgo

package serial

// #include <termios.h>
// #include <unistd.h>
import "C"

// TODO: Maybe change to using syscall package + ioctl instead of cgo

import (
	"errors"
	"fmt"
	"os"
	"syscall"
	"time"
	//"unsafe"
)

func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
	f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
	if err != nil {
		return
	}

	fd := C.int(f.Fd())
	if C.isatty(fd) != 1 {
		f.Close()
		return nil, errors.New("File is not a tty")
	}

	var st C.struct_termios
	_, err = C.tcgetattr(fd, &st)
	if err != nil {
		f.Close()
		return nil, err
	}
	var speed C.speed_t
	switch baud {
	case 115200:
		speed = C.B115200
	case 57600:
		speed = C.B57600
	case 38400:
		speed = C.B38400
	case 19200:
		speed = C.B19200
	case 9600:
		speed = C.B9600
	case 4800:
		speed = C.B4800
	case 2400:
		speed = C.B2400
	case 1200:
		speed = C.B1200
	case 600:
		speed = C.B600
	case 300:
		speed = C.B300
	case 200:
		speed = C.B200
	case 150:
		speed = C.B150
	case 134:
		speed = C.B134
	case 110:
		speed = C.B110
	case 75:
		speed = C.B75
	case 50:
		speed = C.B50
	default:
		f.Close()
		return nil, fmt.Errorf("Unknown baud rate %v", baud)
	}

	_, err = C.cfsetispeed(&st, speed)
	if err != nil {
		f.Close()
		return nil, err
	}
	_, err = C.cfsetospeed(&st, speed)
	if err != nil {
		f.Close()
		return nil, err
	}

	// Turn off break interrupts, CR->NL, Parity checks, strip, and IXON
	st.c_iflag &= ^C.tcflag_t(C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXOFF | C.IXON | C.PARMRK)

	// Select local mode, turn off parity, set to 8 bits
	st.c_cflag &= ^C.tcflag_t(C.CSIZE | C.PARENB)
	st.c_cflag |= (C.CLOCAL | C.CREAD)
	// databits
	switch databits {
	case 5:
		st.c_cflag |= C.CS5
	case 6:
		st.c_cflag |= C.CS6
	case 7:
		st.c_cflag |= C.CS7
	case 8:
		st.c_cflag |= C.CS8
	default:
		return nil, ErrBadSize
	}
	// Parity settings
	switch parity {
	case ParityNone:
		// default is no parity
	case ParityOdd:
		st.c_cflag |= C.PARENB
		st.c_cflag |= C.PARODD
	case ParityEven:
		st.c_cflag |= C.PARENB
	default:
		return nil, ErrBadParity
	}
	// Stop bits settings
	switch stopbits {
	case Stop1:
		// as is, default is 1 bit
	case Stop2:
		st.c_cflag |= C.CSTOPB
	default:
		return nil, ErrBadStopBits
	}
	// Select raw mode
	st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG)
	st.c_oflag &= ^C.tcflag_t(C.OPOST)

	// set blocking / non-blocking read
	/*
	*	http://man7.org/linux/man-pages/man3/termios.3.html
	* - Supports blocking read and read with timeout operations
	 */
	vmin, vtime := posixTimeoutValues(readTimeout)
	st.c_cc[C.VMIN] = C.cc_t(vmin)
	st.c_cc[C.VTIME] = C.cc_t(vtime)

	_, err = C.tcsetattr(fd, C.TCSANOW, &st)
	if err != nil {
		f.Close()
		return nil, err
	}

	//fmt.Println("Tweaking", name)
	r1, _, e := syscall.Syscall(syscall.SYS_FCNTL,
		uintptr(f.Fd()),
		uintptr(syscall.F_SETFL),
		uintptr(0))
	if e != 0 || r1 != 0 {
		s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1)
		f.Close()
		return nil, errors.New(s)
	}

	/*
				r1, _, e = syscall.Syscall(syscall.SYS_IOCTL,
			                uintptr(f.Fd()),
			                uintptr(0x80045402), // IOSSIOSPEED
			                uintptr(unsafe.Pointer(&baud)));
			        if e != 0 || r1 != 0 {
			                s := fmt.Sprint("Baudrate syscall error:", e, r1)
					f.Close()
		                        return nil, os.NewError(s)
				}
	*/

	return &Port{f: f}, nil
}

type Port struct {
	// We intentionly do not use an "embedded" struct so that we
	// don't export File
	f *os.File
}

func (p *Port) Read(b []byte) (n int, err error) {
	return p.f.Read(b)
}

func (p *Port) Write(b []byte) (n int, err error) {
	return p.f.Write(b)
}

// Discards data written to the port but not transmitted,
// or data received but not read
func (p *Port) Flush() error {
	_, err := C.tcflush(C.int(p.f.Fd()), C.TCIOFLUSH)
	return err
}

func (p *Port) Close() (err error) {
	return p.f.Close()
}
<|endoftext|>


<commit_before>package http

import (
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/vault"
)

type PrepareRequestFunc func(*vault.Core, *logical.Request) error

func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) (*logical.Request, int, error) {
	// Determine the path...
	if !strings.HasPrefix(r.URL.Path, "/v1/") {
		return nil, http.StatusNotFound, nil
	}
	path := r.URL.Path[len("/v1/"):]
	if path == "" {
		return nil, http.StatusNotFound, nil
	}

	// Determine the operation
	var op logical.Operation
	switch r.Method {
	case "DELETE":
		op = logical.DeleteOperation
	case "GET":
		op = logical.ReadOperation
		// Need to call ParseForm to get query params loaded
		queryVals := r.URL.Query()
		listStr := queryVals.Get("list")
		if listStr != "" {
			list, err := strconv.ParseBool(listStr)
			if err != nil {
				return nil, http.StatusBadRequest, nil
			}
			if list {
				op = logical.ListOperation
			}
		}
	case "POST", "PUT":
		op = logical.UpdateOperation
	case "LIST":
		op = logical.ListOperation
	case "OPTIONS":
	default:
		return nil, http.StatusMethodNotAllowed, nil
	}

	if op == logical.ListOperation {
		if !strings.HasSuffix(path, "/") {
			path += "/"
		}
	}

	// Parse the request if we can
	var data map[string]interface{}
	if op == logical.UpdateOperation {
		err := parseRequest(r, w, &data)
		if err == io.EOF {
			data = nil
			err = nil
		}
		if err != nil {
			return nil, http.StatusBadRequest, err
		}
	}

	var err error
	request_id, err := uuid.GenerateUUID()
	if err != nil {
		return nil, http.StatusBadRequest, errwrap.Wrapf("failed to generate identifier for the request: {{err}}", err)
	}

	req := requestAuth(core, r, &logical.Request{
		ID:         request_id,
		Operation:  op,
		Path:       path,
		Data:       data,
		Connection: getConnection(r),
		Headers:    r.Header,
	})

	req, err = requestWrapInfo(r, req)
	if err != nil {
		return nil, http.StatusBadRequest, errwrap.Wrapf("error parsing X-Vault-Wrap-TTL header: {{err}}", err)
	}

	return req, 0, nil
}

func handleLogical(core *vault.Core, injectDataIntoTopLevel bool, prepareRequestCallback PrepareRequestFunc) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		req, statusCode, err := buildLogicalRequest(core, w, r)
		if err != nil || statusCode != 0 {
			respondError(w, statusCode, err)
			return
		}

		// Certain endpoints may require changes to the request object. They
		// will have a callback registered to do the needed operations, so
		// invoke it before proceeding.
		if prepareRequestCallback != nil {
			if err := prepareRequestCallback(core, req); err != nil {
				respondError(w, http.StatusBadRequest, err)
				return
			}
		}

		// Make the internal request. We attach the connection info
		// as well in case this is an authentication request that requires
		// it. Vault core handles stripping this if we need to. This also
		// handles all error cases; if we hit respondLogical, the request is a
		// success.
		resp, ok := request(core, w, r, req)
		if !ok {
			return
		}

		// Build the proper response
		respondLogical(w, r, req, injectDataIntoTopLevel, resp)
	})
}

func respondLogical(w http.ResponseWriter, r *http.Request, req *logical.Request, injectDataIntoTopLevel bool, resp *logical.Response) {
	var httpResp *logical.HTTPResponse
	var ret interface{}

	if resp != nil {
		if resp.Redirect != "" {
			// If we have a redirect, redirect! We use a 307 code
			// because we don't actually know if its permanent.
			http.Redirect(w, r, resp.Redirect, 307)
			return
		}

		// Check if this is a raw response
		if _, ok := resp.Data[logical.HTTPStatusCode]; ok {
			respondRaw(w, r, resp)
			return
		}

		if resp.WrapInfo != nil && resp.WrapInfo.Token != "" {
			httpResp = &logical.HTTPResponse{
				WrapInfo: &logical.HTTPWrapInfo{
					Token:           resp.WrapInfo.Token,
					TTL:             int(resp.WrapInfo.TTL.Seconds()),
					CreationTime:    resp.WrapInfo.CreationTime.Format(time.RFC3339Nano),
					CreationPath:    resp.WrapInfo.CreationPath,
					WrappedAccessor: resp.WrapInfo.WrappedAccessor,
				},
			}
		} else {
			httpResp = logical.LogicalResponseToHTTPResponse(resp)
			httpResp.RequestID = req.ID
		}

		ret = httpResp

		if injectDataIntoTopLevel {
			injector := logical.HTTPSysInjector{
				Response: httpResp,
			}
			ret = injector
		}
	}

	// Respond
	respondOk(w, ret)
	return
}

// respondRaw is used when the response is using HTTPContentType and HTTPRawBody
// to change the default response handling. This is only used for specific things like
// returning the CRL information on the PKI backends.
func respondRaw(w http.ResponseWriter, r *http.Request, resp *logical.Response) {
	retErr := func(w http.ResponseWriter, err string) {
		w.Header().Set("X-Vault-Raw-Error", err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(nil)
	}

	// Ensure this is never a secret or auth response
	if resp.Secret != nil || resp.Auth != nil {
		retErr(w, "raw responses cannot contain secrets or auth")
		return
	}

	// Get the status code
	statusRaw, ok := resp.Data[logical.HTTPStatusCode]
	if !ok {
		retErr(w, "no status code given")
		return
	}
	status, ok := statusRaw.(int)
	if !ok {
		retErr(w, "cannot decode status code")
		return
	}

	nonEmpty := status != http.StatusNoContent

	var contentType string
	var body []byte

	// Get the content type header; don't require it if the body is empty
	contentTypeRaw, ok := resp.Data[logical.HTTPContentType]
	if !ok && !nonEmpty {
		retErr(w, "no content type given")
		return
	}
	if ok {
		contentType, ok = contentTypeRaw.(string)
		if !ok {
			retErr(w, "cannot decode content type")
			return
		}
	}

	if nonEmpty {
		// Get the body
		bodyRaw, ok := resp.Data[logical.HTTPRawBody]
		if !ok {
			retErr(w, "no body given")
			return
		}
		body, ok = bodyRaw.([]byte)
		if !ok {
			retErr(w, "cannot decode body")
			return
		}
	}

	// Write the response
	if contentType != "" {
		w.Header().Set("Content-Type", contentType)
	}

	w.WriteHeader(status)
	w.Write(body)
}

// getConnection is used to format the connection information for
// attaching to a logical request
func getConnection(r *http.Request) (connection *logical.Connection) {
	var remoteAddr string

	remoteAddr, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		remoteAddr = ""
	}

	connection = &logical.Connection{
		RemoteAddr: remoteAddr,
		ConnState:  r.TLS,
	}
	return
}
<commit_msg>Fix a logic bug in the respondRaw function (#3491)<commit_after>package http

import (
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/go-uuid"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/vault"
)

type PrepareRequestFunc func(*vault.Core, *logical.Request) error

func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) (*logical.Request, int, error) {
	// Determine the path...
	if !strings.HasPrefix(r.URL.Path, "/v1/") {
		return nil, http.StatusNotFound, nil
	}
	path := r.URL.Path[len("/v1/"):]
	if path == "" {
		return nil, http.StatusNotFound, nil
	}

	// Determine the operation
	var op logical.Operation
	switch r.Method {
	case "DELETE":
		op = logical.DeleteOperation
	case "GET":
		op = logical.ReadOperation
		// Need to call ParseForm to get query params loaded
		queryVals := r.URL.Query()
		listStr := queryVals.Get("list")
		if listStr != "" {
			list, err := strconv.ParseBool(listStr)
			if err != nil {
				return nil, http.StatusBadRequest, nil
			}
			if list {
				op = logical.ListOperation
			}
		}
	case "POST", "PUT":
		op = logical.UpdateOperation
	case "LIST":
		op = logical.ListOperation
	case "OPTIONS":
	default:
		return nil, http.StatusMethodNotAllowed, nil
	}

	if op == logical.ListOperation {
		if !strings.HasSuffix(path, "/") {
			path += "/"
		}
	}

	// Parse the request if we can
	var data map[string]interface{}
	if op == logical.UpdateOperation {
		err := parseRequest(r, w, &data)
		if err == io.EOF {
			data = nil
			err = nil
		}
		if err != nil {
			return nil, http.StatusBadRequest, err
		}
	}

	var err error
	request_id, err := uuid.GenerateUUID()
	if err != nil {
		return nil, http.StatusBadRequest, errwrap.Wrapf("failed to generate identifier for the request: {{err}}", err)
	}

	req := requestAuth(core, r, &logical.Request{
		ID:         request_id,
		Operation:  op,
		Path:       path,
		Data:       data,
		Connection: getConnection(r),
		Headers:    r.Header,
	})

	req, err = requestWrapInfo(r, req)
	if err != nil {
		return nil, http.StatusBadRequest, errwrap.Wrapf("error parsing X-Vault-Wrap-TTL header: {{err}}", err)
	}

	return req, 0, nil
}

func handleLogical(core *vault.Core, injectDataIntoTopLevel bool, prepareRequestCallback PrepareRequestFunc) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		req, statusCode, err := buildLogicalRequest(core, w, r)
		if err != nil || statusCode != 0 {
			respondError(w, statusCode, err)
			return
		}

		// Certain endpoints may require changes to the request object. They
		// will have a callback registered to do the needed operations, so
		// invoke it before proceeding.
		if prepareRequestCallback != nil {
			if err := prepareRequestCallback(core, req); err != nil {
				respondError(w, http.StatusBadRequest, err)
				return
			}
		}

		// Make the internal request. We attach the connection info
		// as well in case this is an authentication request that requires
		// it. Vault core handles stripping this if we need to. This also
		// handles all error cases; if we hit respondLogical, the request is a
		// success.
		resp, ok := request(core, w, r, req)
		if !ok {
			return
		}

		// Build the proper response
		respondLogical(w, r, req, injectDataIntoTopLevel, resp)
	})
}

func respondLogical(w http.ResponseWriter, r *http.Request, req *logical.Request, injectDataIntoTopLevel bool, resp *logical.Response) {
	var httpResp *logical.HTTPResponse
	var ret interface{}

	if resp != nil {
		if resp.Redirect != "" {
			// If we have a redirect, redirect! We use a 307 code
			// because we don't actually know if its permanent.
			http.Redirect(w, r, resp.Redirect, 307)
			return
		}

		// Check if this is a raw response
		if _, ok := resp.Data[logical.HTTPStatusCode]; ok {
			respondRaw(w, r, resp)
			return
		}

		if resp.WrapInfo != nil && resp.WrapInfo.Token != "" {
			httpResp = &logical.HTTPResponse{
				WrapInfo: &logical.HTTPWrapInfo{
					Token:           resp.WrapInfo.Token,
					TTL:             int(resp.WrapInfo.TTL.Seconds()),
					CreationTime:    resp.WrapInfo.CreationTime.Format(time.RFC3339Nano),
					CreationPath:    resp.WrapInfo.CreationPath,
					WrappedAccessor: resp.WrapInfo.WrappedAccessor,
				},
			}
		} else {
			httpResp = logical.LogicalResponseToHTTPResponse(resp)
			httpResp.RequestID = req.ID
		}

		ret = httpResp

		if injectDataIntoTopLevel {
			injector := logical.HTTPSysInjector{
				Response: httpResp,
			}
			ret = injector
		}
	}

	// Respond
	respondOk(w, ret)
	return
}

// respondRaw is used when the response is using HTTPContentType and HTTPRawBody
// to change the default response handling. This is only used for specific things like
// returning the CRL information on the PKI backends.
func respondRaw(w http.ResponseWriter, r *http.Request, resp *logical.Response) {
	retErr := func(w http.ResponseWriter, err string) {
		w.Header().Set("X-Vault-Raw-Error", err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(nil)
	}

	// Ensure this is never a secret or auth response
	if resp.Secret != nil || resp.Auth != nil {
		retErr(w, "raw responses cannot contain secrets or auth")
		return
	}

	// Get the status code
	statusRaw, ok := resp.Data[logical.HTTPStatusCode]
	if !ok {
		retErr(w, "no status code given")
		return
	}
	status, ok := statusRaw.(int)
	if !ok {
		retErr(w, "cannot decode status code")
		return
	}

	nonEmpty := status != http.StatusNoContent

	var contentType string
	var body []byte

	// Get the content type header; don't require it if the body is empty
	contentTypeRaw, ok := resp.Data[logical.HTTPContentType]
	if !ok && nonEmpty {
		retErr(w, "no content type given")
		return
	}
	if ok {
		contentType, ok = contentTypeRaw.(string)
		if !ok {
			retErr(w, "cannot decode content type")
			return
		}
	}

	if nonEmpty {
		// Get the body
		bodyRaw, ok := resp.Data[logical.HTTPRawBody]
		if !ok {
			retErr(w, "no body given")
			return
		}
		body, ok = bodyRaw.([]byte)
		if !ok {
			retErr(w, "cannot decode body")
			return
		}
	}

	// Write the response
	if contentType != "" {
		w.Header().Set("Content-Type", contentType)
	}

	w.WriteHeader(status)
	w.Write(body)
}

// getConnection is used to format the connection information for
// attaching to a logical request
func getConnection(r *http.Request) (connection *logical.Connection) {
	var remoteAddr string

	remoteAddr, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		remoteAddr = ""
	}

	connection = &logical.Connection{
		RemoteAddr: remoteAddr,
		ConnState:  r.TLS,
	}
	return
}
<|endoftext|>