<commit_before>package core

import (
	"bytes"
	"encoding/json"
	"strings"
	"time"
	"github.com/s3git/s3git-go/internal/kv"
)

const COMMIT = "commit"

// Type to create a commit object
// - total size of json object is always a multiple of 64, so we are padding the object
// - structured as a json object
//   - json keys are in fix order
//     - in case a key contains an array, the values are sorted alphabetically

type commitObject struct {
	coreObject
	S3gitMessage     string   `json:"s3gitMessage"`     // Message describing the commit (optional)
	S3gitCommitter   string   `json:"s3gitCommitter"`   // Person doing the commit
	S3gitBranch      string   `json:"s3gitBranch"`      // Name of the branch
	S3gitTree        string   `json:"s3gitTree"`        // Tree object for the commit
	S3gitWarmParents []string `json:"s3gitWarmParents"` // List of parent commits up the (possibly split) chain
	S3gitColdParents []string `json:"s3gitColdParents"` // Parent commits that are no longer part of the chain
	S3gitTimeStamp   string   `json:"s3gitTimeStamp"`
	S3gitPadding     string   `json:"s3gitPadding"`
}

func makeCommitObject(message, branch, tree string, warmParents, coldParents []string) *commitObject {

	co := commitObject{coreObject: coreObject{S3gitVersion: 1, S3gitType: COMMIT}, S3gitMessage: message, S3gitBranch: branch,
		S3gitTree: tree, S3gitWarmParents: warmParents, S3gitColdParents: coldParents}

	// TODO: Read from git config
	// TODO: brackets are translated to \u003c respectively \u003e
	co.S3gitCommitter = "frankw <fwessels@xs4all.nl>"
	// TODO: Want to report as UTC or not (git includes a timezone)
	co.S3gitTimeStamp = time.Now(). /*.UTC()*/ Format(time.RFC3339Nano)
	return &co
}

func (co *commitObject) ParseTime() (time.Time, error) {
	return time.Parse(time.RFC3339Nano, co.S3gitTimeStamp)
}

func (co *commitObject) MarkWarmAndColdParents() error {

	// Mark warm and cold parents as parents in KV
	for _, parentCommit := range co.S3gitWarmParents {
		err := kv.MarkCommitAsParent(parentCommit)
		if err != nil {
			return err
		}
	}
	for _, parentCommit := range co.S3gitColdParents {
		err := kv.MarkCommitAsParent(parentCommit)
		if err != nil {
			return err
		}
	}

	return nil
}

func isCommit(hash string) bool {

	// TODO: Verify that this hash is a commit object
	// 1. in case size of object is not a multiple of KeySize --> not a commit object
	// otherwise:
	// 2. try to load as json object --> ok: true
	return true
}

// Return commit object based on hash
func GetCommitObject(hash string) (*commitObject, error) {

	s, err := readBlob(hash)
	if err != nil {
		return nil, err
	}

	return GetCommitObjectFromString(s)
}

// Get commit object from string contents
func GetCommitObjectFromString(s string) (*commitObject, error) {

	dec := json.NewDecoder(strings.NewReader(s))
	var co commitObject
	if err := dec.Decode(&co); err != nil {
		return nil, err
	}

	return &co, nil
}

func StoreCommitObject(message, branch string, warmParents, coldParents []string, added <-chan []byte, removed []string) (hash string, empty bool, err error) {

	// Create a tree object for this commit
	treeObject := makeTreeObject(added, removed)
	if treeObject.empty() {
		return "", true, nil
	}
	// Store tree object on disk
	treeHash, err := treeObject.writeToDisk()
	if err != nil {
		return "", false, err
	}

	// Create commit object
	commitObject := makeCommitObject(message, branch, treeHash, warmParents, coldParents)

	buf := new(bytes.Buffer)

	encoder := json.NewEncoder(buf)
	if err := encoder.Encode(commitObject); err != nil {
		return "", false, err
	}

	// Write to disk
	h, e := commitObject.write(buf, COMMIT)

	err = commitObject.MarkWarmAndColdParents()
	if err != nil {
		return "", false, err
	}

	return h, false, e
}
<commit_msg>Read user name and email from git config (by calling git executable)<commit_after>package core

import (
	"bytes"
	"encoding/json"
	"github.com/s3git/s3git-go/internal/kv"
	"os/exec"
	"strings"
	"time"
	"errors"
)

const COMMIT = "commit"

// Type to create a commit object
// - total size of json object is always a multiple of 64, so we are padding the object
// - structured as a json object
//   - json keys are in fix order
//     - in case a key contains an array, the values are sorted alphabetically

type commitObject struct {
	coreObject
	S3gitMessage        string   `json:"s3gitMessage"`       // Message describing the commit (optional)
	S3gitCommitterName  string   `json:"s3gitCommitterName"` // Name of person doing the commit (from git)
	S3gitCommitterEmail string   `json:"s3gitCommitterName"` // Email of person doing the commit (from git)
	S3gitBranch         string   `json:"s3gitBranch"`        // Name of the branch
	S3gitTree           string   `json:"s3gitTree"`          // Tree object for the commit
	S3gitWarmParents    []string `json:"s3gitWarmParents"`   // List of parent commits up the (possibly split) chain
	S3gitColdParents    []string `json:"s3gitColdParents"`   // Parent commits that are no longer part of the chain
	S3gitTimeStamp      string   `json:"s3gitTimeStamp"`
	S3gitPadding        string   `json:"s3gitPadding"`
}

func makeCommitObject(message, branch, tree string, warmParents, coldParents []string, name, email string) *commitObject {

	co := commitObject{coreObject: coreObject{S3gitVersion: 1, S3gitType: COMMIT}, S3gitMessage: message, S3gitBranch: branch,
		S3gitTree: tree, S3gitWarmParents: warmParents, S3gitColdParents: coldParents}

	co.S3gitCommitterName = name
	co.S3gitCommitterEmail = email
	// TODO: Want to report as UTC or not (git includes a timezone)
	co.S3gitTimeStamp = time.Now(). /*.UTC()*/ Format(time.RFC3339Nano)
	return &co
}

func (co *commitObject) ParseTime() (time.Time, error) {
	return time.Parse(time.RFC3339Nano, co.S3gitTimeStamp)
}

func (co *commitObject) MarkWarmAndColdParents() error {

	// Mark warm and cold parents as parents in KV
	for _, parentCommit := range co.S3gitWarmParents {
		err := kv.MarkCommitAsParent(parentCommit)
		if err != nil {
			return err
		}
	}
	for _, parentCommit := range co.S3gitColdParents {
		err := kv.MarkCommitAsParent(parentCommit)
		if err != nil {
			return err
		}
	}

	return nil
}

func isCommit(hash string) bool {

	// TODO: Verify that this hash is a commit object
	// 1. in case size of object is not a multiple of KeySize --> not a commit object
	// otherwise:
	// 2. try to load as json object --> ok: true
	return true
}

// Return commit object based on hash
func GetCommitObject(hash string) (*commitObject, error) {

	s, err := readBlob(hash)
	if err != nil {
		return nil, err
	}

	return GetCommitObjectFromString(s)
}

// Get commit object from string contents
func GetCommitObjectFromString(s string) (*commitObject, error) {

	dec := json.NewDecoder(strings.NewReader(s))
	var co commitObject
	if err := dec.Decode(&co); err != nil {
		return nil, err
	}

	return &co, nil
}

func StoreCommitObject(message, branch string, warmParents, coldParents []string, added <-chan []byte, removed []string) (hash string, empty bool, err error) {

	// Create a tree object for this commit
	treeObject := makeTreeObject(added, removed)
	if treeObject.empty() {
		return "", true, nil
	}
	// Store tree object on disk
	treeHash, err := treeObject.writeToDisk()
	if err != nil {
		return "", false, err
	}

	name, email, err := getGitUserNameAndEmail()
	if err != nil {
		return "", false, err
	}

	// Create commit object
	commitObject := makeCommitObject(message, branch, treeHash, warmParents, coldParents, name, email)

	buf := new(bytes.Buffer)

	encoder := json.NewEncoder(buf)
	if err := encoder.Encode(commitObject); err != nil {
		return "", false, err
	}

	// Write to disk
	h, e := commitObject.write(buf, COMMIT)

	err = commitObject.MarkWarmAndColdParents()
	if err != nil {
		return "", false, err
	}

	return h, false, e
}

func getGitUserNameAndEmail() (name, email string, err error) {

	_, err = exec.Command("got", "help").Output()
	if err != nil {
		return "", "", errors.New("git executable not found, is git installed? Needed for name and email configuration")
	}

	n, err := exec.Command("git", "config", "user.name").Output()
	if err != nil {
		return "", "", err
	}

	e, err := exec.Command("git", "config", "user.email").Output()
	if err != nil {
		return "", "", err
	}

	return strings.TrimSpace(string(n)), strings.TrimSpace(string(e)), nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gpu

//------------------------------------------------------------------------------

/*
#include "glad.h"
*/
import "C"
import "github.com/drakmaniso/carol/internal"

//------------------------------------------------------------------------------

//export logGLError
func logGLError(
	source C.GLenum,
	typ C.GLenum,
	id C.GLuint,
	severity C.GLenum,
	length C.GLsizei,
	m *C.char,
) {
	var sev string
	switch severity {
	case C.GL_DEBUG_SEVERITY_HIGH:
		sev = "ERROR"
	case C.GL_DEBUG_SEVERITY_MEDIUM:
		sev = "WARNING"
	case C.GL_DEBUG_SEVERITY_LOW:
		sev = "warning"
	case C.GL_DEBUG_SEVERITY_NOTIFICATION:
		sev = "info"
		return //TODO
	}
	var sou string
	switch source {
	case C.GL_DEBUG_SOURCE_API:
		sou = "OpenGL"
	case C.GL_DEBUG_SOURCE_WINDOW_SYSTEM:
		sou = "Window-system API"
	case C.GL_DEBUG_SOURCE_SHADER_COMPILER:
		sou = "Shader compiler"
	case C.GL_DEBUG_SOURCE_THIRD_PARTY:
		sou = "Third party"
	case C.GL_DEBUG_SOURCE_APPLICATION:
		sou = "Application"
	case C.GL_DEBUG_SOURCE_OTHER:
		sou = "Other source"
	}
	var ty string
	switch typ {
	case C.GL_DEBUG_TYPE_ERROR:
		ty = " (error)"
	case C.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
		ty = " (deprecated behavior)"
	case C.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
		ty = " (undefined behavior)"
	case C.GL_DEBUG_TYPE_PORTABILITY:
		ty = " (portability)"
	case C.GL_DEBUG_TYPE_PERFORMANCE:
		ty = " (performance)"
	case C.GL_DEBUG_TYPE_MARKER:
		ty = " (marker)"
	case C.GL_DEBUG_TYPE_PUSH_GROUP:
		ty = " (push group)"
	case C.GL_DEBUG_TYPE_POP_GROUP:
		ty = " (pop group)"
	case C.GL_DEBUG_TYPE_OTHER:
		ty = ""
	}

	internal.DebugLog("%s %s%s: %s\n", sou, sev, ty, C.GoString(m))
}

//------------------------------------------------------------------------------
<commit_msg>Remove dependency between gpu and internal<commit_after>// Copyright (c) 2013-2016 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package gpu

//------------------------------------------------------------------------------

/*
#include "glad.h"
*/
import "C"
import (
	"log"
	"os"
)

//------------------------------------------------------------------------------

//export logGLError
func logGLError(
	source C.GLenum,
	typ C.GLenum,
	id C.GLuint,
	severity C.GLenum,
	length C.GLsizei,
	m *C.char,
) {
	var sev string
	switch severity {
	case C.GL_DEBUG_SEVERITY_HIGH:
		sev = "ERROR"
	case C.GL_DEBUG_SEVERITY_MEDIUM:
		sev = "WARNING"
	case C.GL_DEBUG_SEVERITY_LOW:
		sev = "warning"
	case C.GL_DEBUG_SEVERITY_NOTIFICATION:
		sev = "info"
		return //TODO
	}
	var sou string
	switch source {
	case C.GL_DEBUG_SOURCE_API:
		sou = "OpenGL"
	case C.GL_DEBUG_SOURCE_WINDOW_SYSTEM:
		sou = "Window-system API"
	case C.GL_DEBUG_SOURCE_SHADER_COMPILER:
		sou = "Shader compiler"
	case C.GL_DEBUG_SOURCE_THIRD_PARTY:
		sou = "Third party"
	case C.GL_DEBUG_SOURCE_APPLICATION:
		sou = "Application"
	case C.GL_DEBUG_SOURCE_OTHER:
		sou = "Other source"
	}
	var ty string
	switch typ {
	case C.GL_DEBUG_TYPE_ERROR:
		ty = " (error)"
	case C.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
		ty = " (deprecated behavior)"
	case C.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
		ty = " (undefined behavior)"
	case C.GL_DEBUG_TYPE_PORTABILITY:
		ty = " (portability)"
	case C.GL_DEBUG_TYPE_PERFORMANCE:
		ty = " (performance)"
	case C.GL_DEBUG_TYPE_MARKER:
		ty = " (marker)"
	case C.GL_DEBUG_TYPE_PUSH_GROUP:
		ty = " (push group)"
	case C.GL_DEBUG_TYPE_POP_GROUP:
		ty = " (pop group)"
	case C.GL_DEBUG_TYPE_OTHER:
		ty = ""
	}

	logger.Printf("%s %s%s: %s\n", sou, sev, ty, C.GoString(m))
}

var logger = log.New(os.Stderr, "*** ", log.Ltime)

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>// (c) 2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package process

import (
	"fmt"
	"path/filepath"
	"sync"

	"github.com/ava-labs/avalanchego/app"
	"github.com/ava-labs/avalanchego/database/leveldb"
	"github.com/ava-labs/avalanchego/database/manager"
	"github.com/ava-labs/avalanchego/database/memdb"
	"github.com/ava-labs/avalanchego/database/rocksdb"
	"github.com/ava-labs/avalanchego/nat"
	"github.com/ava-labs/avalanchego/node"
	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/utils/dynamicip"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/utils/perms"
	"github.com/ava-labs/avalanchego/version"
)

const (
	Header = `     _____               .__                       .__
    /  _  \___  _______  |  | _____    ____   ____ |  |__   ____    ,_ o
   /  /_\  \  \/ /\__  \ |  | \__  \  /    \_/ ___\|  |  \_/ __ \   / //\,
  /    |    \   /  / __ \|  |__/ __ \|   |  \  \___|   Y  \  ___/    \>> |
  \____|__  /\_/  (____  /____(____  /___|  /\___  >___|  /\___  >    \\
          \/           \/          \/     \/     \/     \/     \/`
)

var (
	stakingPortName = fmt.Sprintf("%s-staking", constants.AppName)
	httpPortName    = fmt.Sprintf("%s-http", constants.AppName)

	_ app.App = &process{}
)

// process is a wrapper around a node that runs in this process
type process struct {
	config node.Config
	node   *node.Node
	exitWG sync.WaitGroup
}

func NewApp(config node.Config) app.App {
	return &process{
		config: config,
		node:   &node.Node{},
	}
}

// Start the business logic of the node (as opposed to config reading, etc).
// Does not block until the node is done.
func (p *process) Start() error {
	// Set the data directory permissions to be read write.
	if err := perms.ChmodR(p.config.DatabaseConfig.Path, true, perms.ReadWriteExecute); err != nil {
		return fmt.Errorf("failed to restrict the permissions of the database directory with: %s", err)
	}
	if err := perms.ChmodR(p.config.LoggingConfig.Directory, true, perms.ReadWriteExecute); err != nil {
		return fmt.Errorf("failed to restrict the permissions of the log directory with: %s", err)
	}

	// we want to create the logger after the plugin has started the app
	logFactory := logging.NewFactory(p.config.LoggingConfig)
	log, err := logFactory.Make("main")
	if err != nil {
		logFactory.Close()
		return err
	}

	// start the db manager
	var dbManager manager.Manager
	switch p.config.DatabaseConfig.Name {
	case rocksdb.Name:
		path := filepath.Join(p.config.DatabaseConfig.Path, rocksdb.Name)
		dbManager, err = manager.NewRocksDB(path, log, version.CurrentDatabase)
	case leveldb.Name:
		dbManager, err = manager.NewLevelDB(p.config.DatabaseConfig.Path, log, version.CurrentDatabase)
	case memdb.Name:
		dbManager = manager.NewMemDB(version.CurrentDatabase)
	default:
		err = fmt.Errorf(
			"db-type was %q but should have been one of {%s, %s, %s}",
			p.config.DatabaseConfig.Name,
			leveldb.Name,
			rocksdb.Name,
			memdb.Name,
		)
	}
	if err != nil {
		log.Fatal("couldn't create %q db manager at %s: %s", p.config.DatabaseConfig.Name, p.config.DatabaseConfig.Path, err)
		logFactory.Close()
		return err
	}

	// Track if sybil control is enforced
	if !p.config.EnableStaking {
		log.Warn("Staking is disabled. Sybil control is not enforced.")
	}

	// Check if transaction signatures should be checked
	if !p.config.EnableCrypto {
		// TODO: actually disable crypto verification
		log.Warn("transaction signatures are not being checked")
	}

	// Track if assertions should be executed
	if p.config.LoggingConfig.Assertions {
		log.Debug("assertions are enabled. This may slow down execution")
	}

	// TODO move this to config
	// SupportsNAT() for NoRouter is false.
	// Which means we tried to perform a NAT activity but we were not successful.
	if p.config.AttemptedNATTraversal && !p.config.Nat.SupportsNAT() {
		log.Warn("UPnP or NAT-PMP router attach failed, you may not be listening publicly. " +
			"Please confirm the settings in your router")
	}

	mapper := nat.NewPortMapper(log, p.config.Nat)

	// Open staking port we want for NAT Traversal to have the external port
	// (config.IP.Port) to connect to our internal listening port
	// (config.InternalStakingPort) which should be the same in most cases.
	if p.config.IP.IP().Port != 0 {
		mapper.Map(
			"TCP",
			p.config.IP.IP().Port,
			p.config.IP.IP().Port,
			stakingPortName,
			&p.config.IP,
			p.config.DynamicUpdateDuration,
		)
	}

	// Open the HTTP port iff the HTTP server is not listening on localhost
	if p.config.HTTPHost != "127.0.0.1" && p.config.HTTPHost != "localhost" && p.config.HTTPPort != 0 {
		// For NAT Traversal we want to route from the external port
		// (config.ExternalHTTPPort) to our internal port (config.HTTPPort)
		mapper.Map(
			"TCP",
			p.config.HTTPPort,
			p.config.HTTPPort,
			httpPortName,
			nil,
			p.config.DynamicUpdateDuration,
		)
	}

	// Regularly updates our public IP (or does nothing, if configured that way)
	externalIPUpdater := dynamicip.NewDynamicIPManager(
		p.config.DynamicPublicIPResolver,
		p.config.DynamicUpdateDuration,
		log,
		&p.config.IP,
	)

	if err := p.node.Initialize(&p.config, dbManager, log, logFactory); err != nil {
		log.Fatal("error initializing node: %s", err)
		mapper.UnmapAllPorts()
		externalIPUpdater.Stop()
		if err := dbManager.Close(); err != nil {
			log.Warn("failed to close the node's DB: %s", err)
		}
		log.Stop()
		logFactory.Close()
		return err
	}

	// [p.ExitCode] will block until [p.exitWG.Done] is called
	p.exitWG.Add(1)
	go func() {
		defer func() {
			if r := recover(); r != nil {
				fmt.Println("caught panic", r)
			}
			log.Stop()
			logFactory.Close()
			p.exitWG.Done()
		}()
		defer func() {
			mapper.UnmapAllPorts()
			externalIPUpdater.Stop()
			if err := dbManager.Close(); err != nil {
				log.Warn("failed to close the node's DB: %s", err)
			}
			log.StopOnPanic()
		}()

		err := p.node.Dispatch()
		log.Debug("dispatch returned with: %s", err)
	}()
	return nil
}

// Stop attempts to shutdown the currently running node. This function will
// return immediately.
func (p *process) Stop() error {
	p.node.Shutdown(0)
	return nil
}

// ExitCode returns the exit code that the node is reporting. This function
// blocks until the node has been shut down.
func (p *process) ExitCode() (int, error) {
	p.exitWG.Wait()
	return p.node.ExitCode(), nil
}
<commit_msg>added comment on panic handling<commit_after>// (c) 2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package process

import (
	"fmt"
	"path/filepath"
	"sync"

	"github.com/ava-labs/avalanchego/app"
	"github.com/ava-labs/avalanchego/database/leveldb"
	"github.com/ava-labs/avalanchego/database/manager"
	"github.com/ava-labs/avalanchego/database/memdb"
	"github.com/ava-labs/avalanchego/database/rocksdb"
	"github.com/ava-labs/avalanchego/nat"
	"github.com/ava-labs/avalanchego/node"
	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/utils/dynamicip"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/utils/perms"
	"github.com/ava-labs/avalanchego/version"
)

const (
	Header = `     _____               .__                       .__
    /  _  \___  _______  |  | _____    ____   ____ |  |__   ____    ,_ o
   /  /_\  \  \/ /\__  \ |  | \__  \  /    \_/ ___\|  |  \_/ __ \   / //\,
  /    |    \   /  / __ \|  |__/ __ \|   |  \  \___|   Y  \  ___/    \>> |
  \____|__  /\_/  (____  /____(____  /___|  /\___  >___|  /\___  >    \\
          \/           \/          \/     \/     \/     \/     \/`
)

var (
	stakingPortName = fmt.Sprintf("%s-staking", constants.AppName)
	httpPortName    = fmt.Sprintf("%s-http", constants.AppName)

	_ app.App = &process{}
)

// process is a wrapper around a node that runs in this process
type process struct {
	config node.Config
	node   *node.Node
	exitWG sync.WaitGroup
}

func NewApp(config node.Config) app.App {
	return &process{
		config: config,
		node:   &node.Node{},
	}
}

// Start the business logic of the node (as opposed to config reading, etc).
// Does not block until the node is done.
func (p *process) Start() error {
	// Set the data directory permissions to be read write.
	if err := perms.ChmodR(p.config.DatabaseConfig.Path, true, perms.ReadWriteExecute); err != nil {
		return fmt.Errorf("failed to restrict the permissions of the database directory with: %s", err)
	}
	if err := perms.ChmodR(p.config.LoggingConfig.Directory, true, perms.ReadWriteExecute); err != nil {
		return fmt.Errorf("failed to restrict the permissions of the log directory with: %s", err)
	}

	// we want to create the logger after the plugin has started the app
	logFactory := logging.NewFactory(p.config.LoggingConfig)
	log, err := logFactory.Make("main")
	if err != nil {
		logFactory.Close()
		return err
	}

	// start the db manager
	var dbManager manager.Manager
	switch p.config.DatabaseConfig.Name {
	case rocksdb.Name:
		path := filepath.Join(p.config.DatabaseConfig.Path, rocksdb.Name)
		dbManager, err = manager.NewRocksDB(path, log, version.CurrentDatabase)
	case leveldb.Name:
		dbManager, err = manager.NewLevelDB(p.config.DatabaseConfig.Path, log, version.CurrentDatabase)
	case memdb.Name:
		dbManager = manager.NewMemDB(version.CurrentDatabase)
	default:
		err = fmt.Errorf(
			"db-type was %q but should have been one of {%s, %s, %s}",
			p.config.DatabaseConfig.Name,
			leveldb.Name,
			rocksdb.Name,
			memdb.Name,
		)
	}
	if err != nil {
		log.Fatal("couldn't create %q db manager at %s: %s", p.config.DatabaseConfig.Name, p.config.DatabaseConfig.Path, err)
		logFactory.Close()
		return err
	}

	// Track if sybil control is enforced
	if !p.config.EnableStaking {
		log.Warn("Staking is disabled. Sybil control is not enforced.")
	}

	// Check if transaction signatures should be checked
	if !p.config.EnableCrypto {
		// TODO: actually disable crypto verification
		log.Warn("transaction signatures are not being checked")
	}

	// Track if assertions should be executed
	if p.config.LoggingConfig.Assertions {
		log.Debug("assertions are enabled. This may slow down execution")
	}

	// TODO move this to config
	// SupportsNAT() for NoRouter is false.
	// Which means we tried to perform a NAT activity but we were not successful.
	if p.config.AttemptedNATTraversal && !p.config.Nat.SupportsNAT() {
		log.Warn("UPnP or NAT-PMP router attach failed, you may not be listening publicly. " +
			"Please confirm the settings in your router")
	}

	mapper := nat.NewPortMapper(log, p.config.Nat)

	// Open staking port we want for NAT Traversal to have the external port
	// (config.IP.Port) to connect to our internal listening port
	// (config.InternalStakingPort) which should be the same in most cases.
	if p.config.IP.IP().Port != 0 {
		mapper.Map(
			"TCP",
			p.config.IP.IP().Port,
			p.config.IP.IP().Port,
			stakingPortName,
			&p.config.IP,
			p.config.DynamicUpdateDuration,
		)
	}

	// Open the HTTP port iff the HTTP server is not listening on localhost
	if p.config.HTTPHost != "127.0.0.1" && p.config.HTTPHost != "localhost" && p.config.HTTPPort != 0 {
		// For NAT Traversal we want to route from the external port
		// (config.ExternalHTTPPort) to our internal port (config.HTTPPort)
		mapper.Map(
			"TCP",
			p.config.HTTPPort,
			p.config.HTTPPort,
			httpPortName,
			nil,
			p.config.DynamicUpdateDuration,
		)
	}

	// Regularly updates our public IP (or does nothing, if configured that way)
	externalIPUpdater := dynamicip.NewDynamicIPManager(
		p.config.DynamicPublicIPResolver,
		p.config.DynamicUpdateDuration,
		log,
		&p.config.IP,
	)

	if err := p.node.Initialize(&p.config, dbManager, log, logFactory); err != nil {
		log.Fatal("error initializing node: %s", err)
		mapper.UnmapAllPorts()
		externalIPUpdater.Stop()
		if err := dbManager.Close(); err != nil {
			log.Warn("failed to close the node's DB: %s", err)
		}
		log.Stop()
		logFactory.Close()
		return err
	}

	// [p.ExitCode] will block until [p.exitWG.Done] is called
	p.exitWG.Add(1)
	go func() {
		defer func() {
			if r := recover(); r != nil {
				fmt.Println("caught panic", r)
			}
			log.Stop()
			logFactory.Close()
			p.exitWG.Done()
		}()
		defer func() {
			mapper.UnmapAllPorts()
			externalIPUpdater.Stop()
			if err := dbManager.Close(); err != nil {
				log.Warn("failed to close the node's DB: %s", err)
			}

			// If [p.node.Dispatch()] panics, then we should log the panic and
			// then re-raise the panic. This is why the above defer is broken
			// into two parts.
			log.StopOnPanic()
		}()

		err := p.node.Dispatch()
		log.Debug("dispatch returned with: %s", err)
	}()
	return nil
}

// Stop attempts to shutdown the currently running node. This function will
// return immediately.
func (p *process) Stop() error {
	p.node.Shutdown(0)
	return nil
}

// ExitCode returns the exit code that the node is reporting. This function
// blocks until the node has been shut down.
func (p *process) ExitCode() (int, error) {
	p.exitWG.Wait()
	return p.node.ExitCode(), nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package upgrades

// stepsFor118 returns upgrade steps to upgrade to a Juju 1.18 deployment.
func stepsFor118(context Context) []UpgradeStep {
	return []UpgradeStep{
	// Nothing yet.
	}
}
<commit_msg>A non-functioning upgrade script.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package upgrades

import (
	"fmt"
	"launchpad.net/juju-core/agent"
	"launchpad.net/juju-core/utils/exec"
)

// stepsFor118 returns upgrade steps to upgrade to a Juju 1.18 deployment.
func stepsFor118(context Context) []UpgradeStep {
	return []UpgradeStep{
	// Nothing yet.
	}
}

// Ensure that the lock dir exists and change the ownership of the lock dir
// itself to ubuntu:ubuntu from root:root so the juju-run command run as the
// ubuntu user is able to get access to the hook execution lock (like the
// uniter itself does.)
func ensureLockDirExistsAndUbuntuWritable() {
	// Pretty sure we want the agent Config in the context...
	var agentConfig agent.Config // TODO: get from context

	lockDir := path.Join(agentConfig.DataDir(), "locks")
	// We only try to change ownership if there is an ubuntu user
	// defined, and we determine this by the existance of the home dir.
	command := fmt.Sprintf(""+
		"mkdir -p %s\n"+
		"[ -e /home/ubuntu ] && chown ubuntu:ubuntu %s",
		lockDir, lockDir)
	result, err := exec.RunCommands(exec.RunParams{
		Commands:   command,
		WorkingDir: ProxyDirectory,
	})
	if err != nil {
		return err
	}
	if result.Code != 0 {
		logger.Errorf("failed writing new proxy values: \n%s\n%s", result.Stdout, result.Stderr)
	}
}
<|endoftext|>


<commit_before>package usecases

import (
	"github.com/Tinker-Ware/digital-ocean-service/domain"
	"github.com/digitalocean/godo"
	"github.com/jinzhu/copier"
)

// Instance represens a created instance in any provider
type Instance struct {
	Provider string `json:"provider,omitempty"`
	domain.Droplet
}

// CreateDroplet creates a doplet in Digital Ocean
func (interactor DOInteractor) CreateDroplet(droplet domain.DropletRequest, token string) (*Instance, error) {
	client := getClient(token)

	dropletRequest := &godo.DropletCreateRequest{
		Name:              droplet.Name,
		Region:            droplet.Region,
		Size:              droplet.Size,
		Backups:           droplet.Backups,
		IPv6:              droplet.IPv6,
		PrivateNetworking: droplet.PrivateNetworking,
		UserData:          droplet.UserData,
		Image: godo.DropletCreateImage{
			Slug: droplet.Image,
		},
	}

	sshkeys := []godo.DropletCreateSSHKey{}
	for _, key := range droplet.SSHKeys {
		k := godo.DropletCreateSSHKey{
			ID:          key.ID,
			Fingerprint: key.Fingerprint,
		}
		sshkeys = append(sshkeys, k)
	}
	dropletRequest.SSHKeys = sshkeys

	drop, _, err := client.Droplets.Create(dropletRequest)

	if err != nil {
		return nil, err
	}

	inst := &Instance{
		Provider: "digital_ocean",
		Droplet: domain.Droplet{
			ID:                drop.ID,
			Name:              droplet.Name,
			Region:            droplet.Region,
			OperatingSystem:   drop.Image.Slug,
			PrivateNetworking: false,
			InstanceName:      drop.Size.Slug,
		},
	}

	networksV4 := []domain.NetworkV4{}
	for _, net := range drop.Networks.V4 {
		n := domain.NetworkV4{}
		copier.Copy(n, net)
		networksV4 = append(networksV4, n)
	}

	networksV6 := []domain.NetworkV6{}
	for _, net := range drop.Networks.V6 {
		n := domain.NetworkV6{}
		copier.Copy(n, net)
		networksV6 = append(networksV6, n)
	}
	networks := domain.Networks{
		V4: networksV4,
		V6: networksV6,
	}

	inst.Networks = networks
	inst.SSHKeys = droplet.SSHKeys
	return inst, nil

}

// ListDroplets lists all the droplets a user has in Digital Ocean
func (interactor DOInteractor) ListDroplets(token string) ([]domain.Droplet, error) {

	client := getClient(token)

	doDrops, _, err := client.Droplets.List(nil)
	if err != nil {
		return nil, err
	}
	droplets := []domain.Droplet{}

	for _, drops := range doDrops {
		drp := domain.Droplet{
			Name:         drops.Name,
			Region:       drops.Region.String(),
			InstanceName: drops.Size.String(),
		}

		networksV4 := []domain.NetworkV4{}
		for _, net := range drops.Networks.V4 {
			n := domain.NetworkV4{}
			copier.Copy(n, net)
			networksV4 = append(networksV4, n)
		}

		networksV6 := []domain.NetworkV6{}
		for _, net := range drops.Networks.V6 {
			n := domain.NetworkV6{}
			copier.Copy(n, net)
			networksV6 = append(networksV6, n)
		}

		droplets = append(droplets, drp)

	}

	return droplets, nil
}

// GetDroplet gets a single droplet
func (interactor DOInteractor) GetDroplet(id int, token string) (*Instance, error) {
	client := getClient(token)

	droplet, _, err := client.Droplets.Get(id)
	if err != nil {
		return nil, err
	}

	instance := Instance{
		Provider: "digital_ocean",
		Droplet: domain.Droplet{
			ID:                droplet.ID,
			Name:              droplet.Name,
			Region:            droplet.Region.Slug,
			OperatingSystem:   droplet.Image.Slug,
			PrivateNetworking: false,
			InstanceName:      droplet.Size.Slug,
		},
	}

	networksV4 := []domain.NetworkV4{}
	for _, net := range droplet.Networks.V4 {
		n := domain.NetworkV4{
			IPAddress: net.IPAddress,
			Netmask:   net.Netmask,
			Gateway:   net.Gateway,
			Type:      net.Type,
		}

		networksV4 = append(networksV4, n)
	}

	networksV6 := []domain.NetworkV6{}
	for _, net := range droplet.Networks.V6 {
		n := domain.NetworkV6{
			IPAddress: net.IPAddress,
			Netmask:   net.Netmask,
			Gateway:   net.Gateway,
			Type:      net.Type,
		}

		networksV6 = append(networksV6, n)

	}
	networks := domain.Networks{
		V4: networksV4,
		V6: networksV6,
	}

	instance.Networks = networks

	return &instance, nil
}
<commit_msg>Remove ID from the DO keys<commit_after>package usecases

import (
	"github.com/Tinker-Ware/digital-ocean-service/domain"
	"github.com/digitalocean/godo"
	"github.com/jinzhu/copier"
)

// Instance represens a created instance in any provider
type Instance struct {
	Provider string `json:"provider,omitempty"`
	domain.Droplet
}

// CreateDroplet creates a doplet in Digital Ocean
func (interactor DOInteractor) CreateDroplet(droplet domain.DropletRequest, token string) (*Instance, error) {
	client := getClient(token)

	dropletRequest := &godo.DropletCreateRequest{
		Name:              droplet.Name,
		Region:            droplet.Region,
		Size:              droplet.Size,
		Backups:           droplet.Backups,
		IPv6:              droplet.IPv6,
		PrivateNetworking: droplet.PrivateNetworking,
		UserData:          droplet.UserData,
		Image: godo.DropletCreateImage{
			Slug: droplet.Image,
		},
	}

	sshkeys := []godo.DropletCreateSSHKey{}
	for _, key := range droplet.SSHKeys {
		k := godo.DropletCreateSSHKey{
			Fingerprint: key.Fingerprint,
		}
		sshkeys = append(sshkeys, k)
	}
	dropletRequest.SSHKeys = sshkeys

	drop, _, err := client.Droplets.Create(dropletRequest)

	if err != nil {
		return nil, err
	}

	inst := &Instance{
		Provider: "digital_ocean",
		Droplet: domain.Droplet{
			ID:                drop.ID,
			Name:              droplet.Name,
			Region:            droplet.Region,
			OperatingSystem:   drop.Image.Slug,
			PrivateNetworking: false,
			InstanceName:      drop.Size.Slug,
		},
	}

	networksV4 := []domain.NetworkV4{}
	for _, net := range drop.Networks.V4 {
		n := domain.NetworkV4{}
		copier.Copy(n, net)
		networksV4 = append(networksV4, n)
	}

	networksV6 := []domain.NetworkV6{}
	for _, net := range drop.Networks.V6 {
		n := domain.NetworkV6{}
		copier.Copy(n, net)
		networksV6 = append(networksV6, n)
	}
	networks := domain.Networks{
		V4: networksV4,
		V6: networksV6,
	}

	inst.Networks = networks
	inst.SSHKeys = droplet.SSHKeys
	return inst, nil

}

// ListDroplets lists all the droplets a user has in Digital Ocean
func (interactor DOInteractor) ListDroplets(token string) ([]domain.Droplet, error) {

	client := getClient(token)

	doDrops, _, err := client.Droplets.List(nil)
	if err != nil {
		return nil, err
	}
	droplets := []domain.Droplet{}

	for _, drops := range doDrops {
		drp := domain.Droplet{
			Name:         drops.Name,
			Region:       drops.Region.String(),
			InstanceName: drops.Size.String(),
		}

		networksV4 := []domain.NetworkV4{}
		for _, net := range drops.Networks.V4 {
			n := domain.NetworkV4{}
			copier.Copy(n, net)
			networksV4 = append(networksV4, n)
		}

		networksV6 := []domain.NetworkV6{}
		for _, net := range drops.Networks.V6 {
			n := domain.NetworkV6{}
			copier.Copy(n, net)
			networksV6 = append(networksV6, n)
		}

		droplets = append(droplets, drp)

	}

	return droplets, nil
}

// GetDroplet gets a single droplet
func (interactor DOInteractor) GetDroplet(id int, token string) (*Instance, error) {
	client := getClient(token)

	droplet, _, err := client.Droplets.Get(id)
	if err != nil {
		return nil, err
	}

	instance := Instance{
		Provider: "digital_ocean",
		Droplet: domain.Droplet{
			ID:                droplet.ID,
			Name:              droplet.Name,
			Region:            droplet.Region.Slug,
			OperatingSystem:   droplet.Image.Slug,
			PrivateNetworking: false,
			InstanceName:      droplet.Size.Slug,
		},
	}

	networksV4 := []domain.NetworkV4{}
	for _, net := range droplet.Networks.V4 {
		n := domain.NetworkV4{
			IPAddress: net.IPAddress,
			Netmask:   net.Netmask,
			Gateway:   net.Gateway,
			Type:      net.Type,
		}

		networksV4 = append(networksV4, n)
	}

	networksV6 := []domain.NetworkV6{}
	for _, net := range droplet.Networks.V6 {
		n := domain.NetworkV6{
			IPAddress: net.IPAddress,
			Netmask:   net.Netmask,
			Gateway:   net.Gateway,
			Type:      net.Type,
		}

		networksV6 = append(networksV6, n)

	}
	networks := domain.Networks{
		V4: networksV4,
		V6: networksV6,
	}

	instance.Networks = networks

	return &instance, nil
}
<|endoftext|>


<commit_before>package json

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"sync"
)

var (
	// ErrNotImplemented a function is in development
	ErrNotImplemented = errors.New("Not Implemented")
	// ErrInvalidPath returned by Open if the path is not a directory
	ErrInvalidPath = errors.New("Provided path not a directory")
	// ErrTableExists returned when attempting to register a table that already
	// exists.
	ErrTableExists = errors.New("Table Already Exists")
)

// Table implementation for marshaling and unmarshaling records
type Table interface {
	Scan() chan json.RawMessage
	Put(interface{}) error
	Load(chan json.RawMessage) error
}

// Connection simple json database
type Connection struct {
	path         string
	tables       map[string]Table
	fileProvider func(string) (io.Reader, error)
	fileCreator  func(string) (io.Writer, error)
	sync.Mutex
}

// Open creates a new json db connection from the passed file
func Open(path string) (*Connection, error) {
	if stat, err := os.Stat(path); err != nil {
		return nil, err
	} else if !stat.IsDir() {
		return nil, ErrInvalidPath
	}

	connection := new(Connection)
	connection.path = path
	connection.tables = make(map[string]Table)
	connection.fileCreator = func(f string) (io.Writer, error) {
		file, err := os.Create(f)
		stat, _ := file.Stat()
		log.Println("Debug: ", stat.Name())
		return file, err
	}
	connection.fileProvider = func(f string) (io.Reader, error) {
		return os.Open(f)
	}

	return connection, nil
}

// SetFileProvider gives some customizability in how we load data
func (c *Connection) SetFileProvider(fileCreator func(f string) (io.Reader, error)) {
	c.fileProvider = fileCreator
}

// SetFileCreator gives some customizability in how we save data
func (c *Connection) SetFileCreator(fileCreator func(f string) (io.Writer, error)) {
	c.fileCreator = fileCreator
}

// RegisterTable adds a table implementation the the database.
func (c *Connection) RegisterTable(name string, table Table) error {
	c.Lock()
	defer c.Unlock()
	if _, ok := c.tables[name]; ok {
		return ErrTableExists
	}

	records, errCh := make(chan json.RawMessage), make(chan error, 1)
	go func() {
		defer close(records)
		defer close(errCh)

		var (
			file     io.Reader
			line     []byte
			isPrefix bool
			err      error
		)

		if file, err = c.fileProvider(path.Join(c.path, name+".json")); err != nil {
			if _, ok := err.(*os.PathError); ok {
				return
			}
			errCh <- err
			return
		}

		if closer, ok := file.(io.Closer); ok {
			defer closer.Close()
		}

		buffer := bufio.NewReader(file)
		for err == nil {
			fullLine := make([]byte, 0, cap(line))
			line, isPrefix = line[0:0], true
			for ; isPrefix; line, isPrefix, err = buffer.ReadLine() {
				if err != nil {
					break
				}
				fullLine = append(fullLine, line...)
			}

			if err != nil && err != io.EOF {
				log.Println("Error Reading json table file: ", err)
				errCh <- err
				return
			}

			if len(fullLine) < 1 {
				continue
			}

			records <- json.RawMessage(fullLine)
		}
	}()

	if err := table.Load(records); err != nil {
		return err
	}

	if err := <-errCh; err != nil {
		return err
	}

	c.tables[name] = table
	return nil
}

// Close flushes write buffer to disk and closes the file.
func (c *Connection) Close() error {
	c.Lock()
	defer c.Unlock()
	var (
		file io.Writer
		data []byte
		err  error
	)
	for name, table := range c.tables {
		if file, err = c.fileCreator(path.Join(c.path, name+".json")); err != nil {
			return nil
		}

		for record := range table.Scan() {
			if data, err = record.MarshalJSON(); err != nil {
				if closer, ok := file.(io.Closer); ok {
					closer.Close()
				}
				return err
			}

			if _, err = fmt.Fprintln(file, string(data)); err != nil {
				if closer, ok := file.(io.Closer); ok {
					closer.Close()
				}
				return err
			}
		}

		if closer, ok := file.(io.Closer); ok {
			if err = closer.Close(); err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>fussed with the isPrefix read logic in the json db<commit_after>package json

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"sync"
)

var (
	// ErrNotImplemented a function is in development
	ErrNotImplemented = errors.New("Not Implemented")
	// ErrInvalidPath returned by Open if the path is not a directory
	ErrInvalidPath = errors.New("Provided path not a directory")
	// ErrTableExists returned when attempting to register a table that already
	// exists.
	ErrTableExists = errors.New("Table Already Exists")
)

// Table implementation for marshaling and unmarshaling records
type Table interface {
	Scan() chan json.RawMessage
	Put(interface{}) error
	Load(chan json.RawMessage) error
}

// Connection simple json database
type Connection struct {
	path         string
	tables       map[string]Table
	fileProvider func(string) (io.Reader, error)
	fileCreator  func(string) (io.Writer, error)
	sync.Mutex
}

// Open creates a new json db connection from the passed file
func Open(path string) (*Connection, error) {
	if stat, err := os.Stat(path); err != nil {
		return nil, err
	} else if !stat.IsDir() {
		return nil, ErrInvalidPath
	}

	connection := new(Connection)
	connection.path = path
	connection.tables = make(map[string]Table)
	connection.fileCreator = func(f string) (io.Writer, error) {
		file, err := os.Create(f)
		stat, _ := file.Stat()
		log.Println("Debug: ", stat.Name())
		return file, err
	}
	connection.fileProvider = func(f string) (io.Reader, error) {
		return os.Open(f)
	}

	return connection, nil
}

// SetFileProvider gives some customizability in how we load data
func (c *Connection) SetFileProvider(fileCreator func(f string) (io.Reader, error)) {
	c.fileProvider = fileCreator
}

// SetFileCreator gives some customizability in how we save data
func (c *Connection) SetFileCreator(fileCreator func(f string) (io.Writer, error)) {
	c.fileCreator = fileCreator
}

// RegisterTable adds a table implementation the the database.
func (c *Connection) RegisterTable(name string, table Table) error {
	c.Lock()
	defer c.Unlock()
	if _, ok := c.tables[name]; ok {
		return ErrTableExists
	}

	records, errCh := make(chan json.RawMessage), make(chan error, 1)
	go func() {
		defer close(records)
		defer close(errCh)

		var (
			file     io.Reader
			line     []byte
			isPrefix bool
			err      error
		)

		if file, err = c.fileProvider(path.Join(c.path, name+".json")); err != nil {
			if _, ok := err.(*os.PathError); ok {
				return
			}
			errCh <- err
			return
		}

		if closer, ok := file.(io.Closer); ok {
			defer closer.Close()
		}

		buffer := bufio.NewReader(file)
		for err == nil {

			fullLine := make([]byte, 0)
			line, isPrefix, err = buffer.ReadLine()
			for ; isPrefix; line, isPrefix, err = buffer.ReadLine() {
				if err != nil {
					break
				}
				fullLine = append(fullLine, line...)
			}

			if err != nil && err != io.EOF {
				log.Println("Error Reading json table file: ", err)
				errCh <- err
				return
			}

			fullLine = append(fullLine, line...)

			if len(fullLine) < 1 {
				continue
			}

			records <- json.RawMessage(fullLine)
		}
	}()

	if err := table.Load(records); err != nil {
		return err
	}

	if err := <-errCh; err != nil {
		return err
	}

	c.tables[name] = table
	return nil
}

// Close flushes write buffer to disk and closes the file.
func (c *Connection) Close() error {
	c.Lock()
	defer c.Unlock()
	var (
		file io.Writer
		data []byte
		err  error
	)
	for name, table := range c.tables {
		if file, err = c.fileCreator(path.Join(c.path, name+".json")); err != nil {
			return nil
		}

		for record := range table.Scan() {
			if data, err = record.MarshalJSON(); err != nil {
				if closer, ok := file.(io.Closer); ok {
					closer.Close()
				}
				return err
			}

			if _, err = fmt.Fprintln(file, string(data)); err != nil {
				if closer, ok := file.(io.Closer); ok {
					closer.Close()
				}
				return err
			}
		}

		if closer, ok := file.(io.Closer); ok {
			if err = closer.Close(); err != nil {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Write a function that takes a string as input and reverse only the vowels of a string.

Example 1:

Input: "hello"
Output: "holle"
Example 2:

Input: "leetcode"
Output: "leotcede"
Note:
The vowels does not include the letter "y".

*/

package main

import (
  "log"
)

func main() {
  tests := []string{"hello", "leetcode"}
  for _, test := range tests {
    log.Printf("reverseVowels(%s) = %s\n", test, reverseVowels(test))
  }
}

func reverseVowels(s string) string {
  // transform input string into unicode char list for easier manipulation
  sRunes := []rune(s)

  // make lists of vowels and their indices from start
  vowelsList  := []rune{}
  vowelIndexList := []int{}

  for i := 0; i < len(sRunes); i++ {
    if isVowel(sRunes[i]) {
      vowelsList = append(vowelsList, sRunes[i])
      vowelIndexList = append(vowelIndexList, i)
    }
  }

  // log.Printf("%v\n", vowelsList)
  // log.Printf("%v\n", vowelIndexList)

  j := 0
  for i := len(vowelIndexList)-1; i >= 0; i-- {
    sRunes[vowelIndexList[i]] = vowelsList[j]
    j++
  }

  return string(sRunes)
}

func isVowel(ch rune) bool {
  if ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' {
    return true
  }

  return false
}
<commit_msg>Implement linear space version<commit_after>/*
Write a function that takes a string as input and reverse only the vowels of a string.

Example 1:

Input: "hello"
Output: "holle"
Example 2:

Input: "leetcode"
Output: "leotcede"
Note:
The vowels does not include the letter "y".

*/

package main

import (
  "log"
)

func main() {
  tests := []string{"hello", "leetcode"}
  for _, test := range tests {
    // log.Printf("reverseVowels(%s) = %s\n", test, reverseVowels(test))
    log.Printf("reverseVowels(%s) = %s\n", test, reverseVowels2(test))
  }
}

func reverseVowels2(s string) string {
  sRunes := []rune(s)
  vowelIndexList := []int{}

  for i := 0; i < len(sRunes); i++ {
    if isVowel(sRunes[i]) {
      vowelIndexList = append(vowelIndexList, i)
    }
  }

  for i := 0; i < len(vowelIndexList)/2; i++ {
    sRunes[vowelIndexList[i]], sRunes[vowelIndexList[len(vowelIndexList)- i - 1]] = sRunes[vowelIndexList[len(vowelIndexList)- i - 1]], sRunes[vowelIndexList[i]]
  }

  return string(sRunes)
}

func reverseVowels(s string) string {
  // transform input string into unicode char list for easier manipulation
  sRunes := []rune(s)

  // make lists of vowels and their indices from start
  vowelsList  := []rune{}
  vowelIndexList := []int{}

  for i := 0; i < len(sRunes); i++ {
    if isVowel(sRunes[i]) {
      vowelsList = append(vowelsList, sRunes[i])
      vowelIndexList = append(vowelIndexList, i)
    }
  }

  // log.Printf("%v\n", vowelsList)
  // log.Printf("%v\n", vowelIndexList)

  j := 0
  for i := len(vowelIndexList)-1; i >= 0; i-- {
    sRunes[vowelIndexList[i]] = vowelsList[j]
    j++
  }

  return string(sRunes)
}

func isVowel(ch rune) bool {
  if ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' {
    return true
  }

  return false
}
<|endoftext|>


<commit_before>package defaults

import (
	"net/http"
	"strings"

	"github.com/volatiletech/authboss/v3"
)

// Responder helps respond to http requests
type Responder struct {
	Renderer authboss.Renderer
}

// NewResponder constructor
func NewResponder(renderer authboss.Renderer) *Responder {
	return &Responder{Renderer: renderer}
}

// Respond to an HTTP request. It's main job is to merge data that comes in from
// various middlewares via the context with the data sent by the controller and
// render that.
func (r *Responder) Respond(w http.ResponseWriter, req *http.Request, code int, page string, data authboss.HTMLData) error {
	ctxData := req.Context().Value(authboss.CTXKeyData)
	if ctxData != nil {
		if data == nil {
			data = authboss.HTMLData{}
		}
		data.Merge(ctxData.(authboss.HTMLData))
	}

	rendered, mime, err := r.Renderer.Render(req.Context(), page, data)
	if err != nil {
		return err
	}

	w.Header().Set("Content-Type", mime)
	w.WriteHeader(code)

	_, err = w.Write(rendered)
	return err
}

func isAPIRequest(r *http.Request) bool {
	return strings.HasPrefix(r.Header.Get("Content-Type"), "application/json")
}

// Redirector for http requests
type Redirector struct {
	Renderer authboss.Renderer

	// FormValueName for the redirection
	FormValueName string

	// CoerceRedirectTo200 forces http.StatusTemporaryRedirect and
	// and http.StatusPermanentRedirect to http.StatusOK
	CorceRedirectTo200 bool
}

// NewRedirector constructor
func NewRedirector(renderer authboss.Renderer, formValueName string) *Redirector {
	return &Redirector{FormValueName: formValueName, Renderer: renderer}
}

// Redirect the client elsewhere. If it's an API request it will simply render
// a JSON response with information that should help a client to decide what
// to do.
func (r *Redirector) Redirect(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	var redirectFunction = r.redirectNonAPI
	if isAPIRequest(req) {
		redirectFunction = r.redirectAPI
	}

	return redirectFunction(w, req, ro)
}

func (r Redirector) redirectAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	path := ro.RedirectPath
	redir := req.FormValue(r.FormValueName)
	if len(redir) != 0 && ro.FollowRedirParam {
		path = redir
	}

	var status = "success"
	var message string
	if len(ro.Success) != 0 {
		message = ro.Success
	}
	if len(ro.Failure) != 0 {
		status = "failure"
		message = ro.Failure
	}

	data := authboss.HTMLData{
		"location": path,
	}

	data["status"] = status
	if len(message) != 0 {
		data["message"] = message
	}

	body, mime, err := r.Renderer.Render(req.Context(), "redirect", data)
	if err != nil {
		return err
	}

	if len(body) != 0 {
		w.Header().Set("Content-Type", mime)
	}

	if ro.Code != 0 {
		if r.CorceRedirectTo200 && (ro.Code == http.StatusTemporaryRedirect || ro.Code == http.StatusPermanentRedirect) {
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteHeader(ro.Code)
		}
	}
	_, err = w.Write(body)
	return err
}

func (r Redirector) redirectNonAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	path := ro.RedirectPath
	redir := req.FormValue(r.FormValueName)
	if len(redir) != 0 && ro.FollowRedirParam {
		path = redir
	}

	if len(ro.Success) != 0 {
		authboss.PutSession(w, authboss.FlashSuccessKey, ro.Success)
	}
	if len(ro.Failure) != 0 {
		authboss.PutSession(w, authboss.FlashErrorKey, ro.Failure)
	}

	http.Redirect(w, req, path, http.StatusFound)
	return nil
}
<commit_msg>Update responder.go<commit_after>package defaults

import (
	"net/http"
	"strings"

	"github.com/volatiletech/authboss/v3"
)

// Responder helps respond to http requests
type Responder struct {
	Renderer authboss.Renderer
}

// NewResponder constructor
func NewResponder(renderer authboss.Renderer) *Responder {
	return &Responder{Renderer: renderer}
}

// Respond to an HTTP request. It's main job is to merge data that comes in from
// various middlewares via the context with the data sent by the controller and
// render that.
func (r *Responder) Respond(w http.ResponseWriter, req *http.Request, code int, page string, data authboss.HTMLData) error {
	ctxData := req.Context().Value(authboss.CTXKeyData)
	if ctxData != nil {
		if data == nil {
			data = authboss.HTMLData{}
		}
		data.Merge(ctxData.(authboss.HTMLData))
	}

	rendered, mime, err := r.Renderer.Render(req.Context(), page, data)
	if err != nil {
		return err
	}

	w.Header().Set("Content-Type", mime)
	w.WriteHeader(code)

	_, err = w.Write(rendered)
	return err
}

func isAPIRequest(r *http.Request) bool {
	return strings.HasPrefix(r.Header.Get("Content-Type"), "application/json")
}

// Redirector for http requests
type Redirector struct {
	Renderer authboss.Renderer

	// FormValueName for the redirection
	FormValueName string

	// CoerceRedirectTo200 forces http.StatusTemporaryRedirect and
	// and http.StatusPermanentRedirect to http.StatusOK
	CorceRedirectTo200 bool
}

// NewRedirector constructor
func NewRedirector(renderer authboss.Renderer, formValueName string) *Redirector {
	return &Redirector{FormValueName: formValueName, Renderer: renderer}
}

// Redirect the client elsewhere. If it's an API request it will simply render
// a JSON response with information that should help a client to decide what
// to do.
func (r *Redirector) Redirect(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	var redirectFunction = r.redirectNonAPI
	if isAPIRequest(req) {
		redirectFunction = r.redirectAPI
	}

	return redirectFunction(w, req, ro)
}

func (r Redirector) redirectAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	path := ro.RedirectPath
	redir := req.FormValue(r.FormValueName)
	if strings.Contains(redir, "://") {
		// Guard against Open Redirect: https://cwe.mitre.org/data/definitions/601.html
		redir = ""
	}
	if len(redir) != 0 && ro.FollowRedirParam {
		path = redir
	}

	var status = "success"
	var message string
	if len(ro.Success) != 0 {
		message = ro.Success
	}
	if len(ro.Failure) != 0 {
		status = "failure"
		message = ro.Failure
	}

	data := authboss.HTMLData{
		"location": path,
	}

	data["status"] = status
	if len(message) != 0 {
		data["message"] = message
	}

	body, mime, err := r.Renderer.Render(req.Context(), "redirect", data)
	if err != nil {
		return err
	}

	if len(body) != 0 {
		w.Header().Set("Content-Type", mime)
	}

	if ro.Code != 0 {
		if r.CorceRedirectTo200 && (ro.Code == http.StatusTemporaryRedirect || ro.Code == http.StatusPermanentRedirect) {
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteHeader(ro.Code)
		}
	}
	_, err = w.Write(body)
	return err
}

func (r Redirector) redirectNonAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
	path := ro.RedirectPath
	redir := req.FormValue(r.FormValueName)
	if len(redir) != 0 && ro.FollowRedirParam {
		path = redir
	}

	if len(ro.Success) != 0 {
		authboss.PutSession(w, authboss.FlashSuccessKey, ro.Success)
	}
	if len(ro.Failure) != 0 {
		authboss.PutSession(w, authboss.FlashErrorKey, ro.Failure)
	}

	http.Redirect(w, req, path, http.StatusFound)
	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"io"
	"reflect"
	"strings"
	"testing"
	"time"
)

func TestFS_FrameReader(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)

	// Create some frames and send them
	f1 := &StreamFrame{
		File:   "foo",
		Offset: 5,
		Data:   []byte("hello"),
	}
	f2 := &StreamFrame{
		File:   "foo",
		Offset: 10,
		Data:   []byte(", wor"),
	}
	f3 := &StreamFrame{
		File:   "foo",
		Offset: 12,
		Data:   []byte("ld"),
	}
	framesCh <- f1
	framesCh <- f2
	framesCh <- f3
	close(framesCh)

	expected := []byte("hello, world")

	// Read a little
	p := make([]byte, 12)

	n, err := r.Read(p[:5])
	if err != nil {
		t.Fatalf("Read failed: %v", err)
	}
	if off := r.Offset(); off != n {
		t.Fatalf("unexpected read bytes: got %v; wanted %v", n, off)
	}

	off := n
	for {
		n, err = r.Read(p[off:])
		if err != nil {
			if err == io.EOF {
				break
			}
			t.Fatalf("Read failed: %v", err)
		}
		off += n
	}

	if !reflect.DeepEqual(p, expected) {
		t.Fatalf("read %q, wanted %q", string(p), string(expected))
	}

	if err := r.Close(); err != nil {
		t.Fatalf("Close() failed: %v", err)
	}
	if _, ok := <-cancelCh; ok {
		t.Fatalf("Close() didn't close cancel channel")
	}
	if len(expected) != r.Offset() {
		t.Fatalf("offset %d, wanted %d", r.Offset(), len(expected))
	}
}

func TestFS_FrameReader_Unblock(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)
	r.SetUnblockTime(10 * time.Millisecond)

	// Read a little
	p := make([]byte, 12)

	n, err := r.Read(p)
	if err != nil {
		t.Fatalf("Read failed: %v", err)
	}

	if n != 0 {
		t.Fatalf("should have unblocked")
	}

	// Unset the unblock
	r.SetUnblockTime(0)

	resultCh := make(chan struct{})
	go func() {
		r.Read(p)
		close(resultCh)
	}()

	select {
	case <-resultCh:
		t.Fatalf("shouldn't have unblocked")
	case <-time.After(300 * time.Millisecond):
	}
}

func TestFS_FrameReader_Error(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error, 1)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)
	r.SetUnblockTime(10 * time.Millisecond)

	// Send an error
	expected := fmt.Errorf("test error")
	errCh <- expected

	// Read a little
	p := make([]byte, 12)

	_, err := r.Read(p)
	if err == nil || !strings.Contains(err.Error(), expected.Error()) {
		t.Fatalf("bad error: %v", err)
	}
}
<commit_msg>tests: test logs from client<->api package<commit_after>package api

import (
	"bytes"
	"fmt"
	"io"
	"reflect"
	"strings"
	"testing"
	"time"

	units "github.com/docker/go-units"
	"github.com/hashicorp/nomad/helper"
	"github.com/hashicorp/nomad/testutil"
	"github.com/kr/pretty"
	"github.com/stretchr/testify/require"
)

func TestFS_Logs(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	rpcPort := 0
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		rpcPort = c.Ports.RPC
		c.Client = &testutil.ClientConfig{
			Enabled: true,
		}
	})
	defer s.Stop()

	//TODO There should be a way to connect the client to the servers in
	//makeClient above
	require.NoError(c.Agent().SetServers([]string{fmt.Sprintf("127.0.0.1:%d", rpcPort)}))

	index := uint64(0)
	testutil.WaitForResult(func() (bool, error) {
		nodes, qm, err := c.Nodes().List(&QueryOptions{WaitIndex: index})
		if err != nil {
			return false, err
		}
		index = qm.LastIndex
		if len(nodes) != 1 {
			return false, fmt.Errorf("expected 1 node but found: %s", pretty.Sprint(nodes))
		}
		if nodes[0].Status != "ready" {
			return false, fmt.Errorf("node not ready: %s", nodes[0].Status)
		}
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %v", err)
	})

	var input strings.Builder
	input.Grow(units.MB)
	lines := 80 * units.KB
	for i := 0; i < lines; i++ {
		fmt.Fprintf(&input, "%d\n", i)
	}

	job := &Job{
		ID:          helper.StringToPtr("TestFS_Logs"),
		Region:      helper.StringToPtr("global"),
		Datacenters: []string{"dc1"},
		Type:        helper.StringToPtr("batch"),
		TaskGroups: []*TaskGroup{
			{
				Name: helper.StringToPtr("TestFS_LogsGroup"),
				Tasks: []*Task{
					{
						Name:   "logger",
						Driver: "mock_driver",
						Config: map[string]interface{}{
							"stdout_string": input.String(),
						},
					},
				},
			},
		},
	}

	jobs := c.Jobs()
	jobResp, _, err := jobs.Register(job, nil)
	require.NoError(err)

	index = jobResp.EvalCreateIndex
	evals := c.Evaluations()
	testutil.WaitForResult(func() (bool, error) {
		evalResp, qm, err := evals.Info(jobResp.EvalID, &QueryOptions{WaitIndex: index})
		if err != nil {
			return false, err
		}
		if evalResp.BlockedEval != "" {
			t.Fatalf("Eval blocked: %s", pretty.Sprint(evalResp))
		}
		index = qm.LastIndex
		if evalResp.Status != "complete" {
			return false, fmt.Errorf("eval status: %v", evalResp.Status)
		}
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %v", err)
	})

	allocID := ""
	testutil.WaitForResult(func() (bool, error) {
		allocs, _, err := jobs.Allocations(*job.ID, true, &QueryOptions{WaitIndex: index})
		if err != nil {
			return false, err
		}
		if len(allocs) != 1 {
			return false, fmt.Errorf("unexpected number of allocs: %d", len(allocs))
		}
		if allocs[0].ClientStatus != "complete" {
			return false, fmt.Errorf("alloc not complete: %s", allocs[0].ClientStatus)
		}
		allocID = allocs[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %v", err)
	})

	alloc, _, err := c.Allocations().Info(allocID, nil)
	require.NoError(err)

	for i := 0; i < 3; i++ {
		stopCh := make(chan struct{})
		defer close(stopCh)

		frames, errors := c.AllocFS().Logs(alloc, false, "logger", "stdout", "start", 0, stopCh, nil)

		var result bytes.Buffer
	READ_FRAMES:
		for {
			select {
			case f := <-frames:
				if f == nil {
					break READ_FRAMES
				}
				result.Write(f.Data)
			case err := <-errors:
				// Don't Fatal here as the other assertions may
				// contain helpeful information.
				t.Errorf("Error: %v", err)
			}
		}

		// Check length
		require.Equal(input.Len(), result.Len())

		// Check complete ordering
		for i := 0; i < lines; i++ {
			line, err := result.ReadBytes('\n')
			require.NoErrorf(err, "unexpected error on line %d: %v", i, err)
			require.Equal(fmt.Sprintf("%d\n", i), string(line))
		}
	}
}

func TestFS_FrameReader(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)

	// Create some frames and send them
	f1 := &StreamFrame{
		File:   "foo",
		Offset: 5,
		Data:   []byte("hello"),
	}
	f2 := &StreamFrame{
		File:   "foo",
		Offset: 10,
		Data:   []byte(", wor"),
	}
	f3 := &StreamFrame{
		File:   "foo",
		Offset: 12,
		Data:   []byte("ld"),
	}
	framesCh <- f1
	framesCh <- f2
	framesCh <- f3
	close(framesCh)

	expected := []byte("hello, world")

	// Read a little
	p := make([]byte, 12)

	n, err := r.Read(p[:5])
	if err != nil {
		t.Fatalf("Read failed: %v", err)
	}
	if off := r.Offset(); off != n {
		t.Fatalf("unexpected read bytes: got %v; wanted %v", n, off)
	}

	off := n
	for {
		n, err = r.Read(p[off:])
		if err != nil {
			if err == io.EOF {
				break
			}
			t.Fatalf("Read failed: %v", err)
		}
		off += n
	}

	if !reflect.DeepEqual(p, expected) {
		t.Fatalf("read %q, wanted %q", string(p), string(expected))
	}

	if err := r.Close(); err != nil {
		t.Fatalf("Close() failed: %v", err)
	}
	if _, ok := <-cancelCh; ok {
		t.Fatalf("Close() didn't close cancel channel")
	}
	if len(expected) != r.Offset() {
		t.Fatalf("offset %d, wanted %d", r.Offset(), len(expected))
	}
}

func TestFS_FrameReader_Unblock(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)
	r.SetUnblockTime(10 * time.Millisecond)

	// Read a little
	p := make([]byte, 12)

	n, err := r.Read(p)
	if err != nil {
		t.Fatalf("Read failed: %v", err)
	}

	if n != 0 {
		t.Fatalf("should have unblocked")
	}

	// Unset the unblock
	r.SetUnblockTime(0)

	resultCh := make(chan struct{})
	go func() {
		r.Read(p)
		close(resultCh)
	}()

	select {
	case <-resultCh:
		t.Fatalf("shouldn't have unblocked")
	case <-time.After(300 * time.Millisecond):
	}
}

func TestFS_FrameReader_Error(t *testing.T) {
	t.Parallel()
	// Create a channel of the frames and a cancel channel
	framesCh := make(chan *StreamFrame, 3)
	errCh := make(chan error, 1)
	cancelCh := make(chan struct{})

	r := NewFrameReader(framesCh, errCh, cancelCh)
	r.SetUnblockTime(10 * time.Millisecond)

	// Send an error
	expected := fmt.Errorf("test error")
	errCh <- expected

	// Read a little
	p := make([]byte, 12)

	_, err := r.Read(p)
	if err == nil || !strings.Contains(err.Error(), expected.Error()) {
		t.Fatalf("bad error: %v", err)
	}
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/globocom/gandalf/db"
	"github.com/globocom/gandalf/repository"
	"github.com/globocom/gandalf/user"
	"io"
	"io/ioutil"
	"labix.org/v2/mgo/bson"
	"net/http"
	"reflect"
)

func GrantAccess(w http.ResponseWriter, r *http.Request) {
	repo := repository.Repository{Name: r.URL.Query().Get(":name")}
	c := db.Session.Repository()
	c.Find(bson.M{"_id": repo.Name}).One(&repo)
	req := map[string][]string{}
	err := parseBody(r.Body, &req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for _, u := range req["users"] {
		_, err = getUserOr404(u)
		if err != nil {
			if len(req["users"]) == 1 {
				http.Error(w, err.Error(), http.StatusNotFound)
				return
			} else {
				// #TODO (flaviamissi): log a warning saying the user "u" was not found and skip it
				continue
			}
		}
		repo.Users = append(repo.Users, u)
	}
	err = c.Update(bson.M{"_id": repo.Name}, &repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func AddKey(w http.ResponseWriter, r *http.Request) {
	u := user.User{Name: r.URL.Query().Get(":name")}
	c := db.Session.User()
	err := c.Find(bson.M{"_id": u.Name}).One(&u)
	if err != nil {
		http.Error(w, "User not found", http.StatusNotFound)
		return
	}
	params := map[string]string{}
	err = parseBody(r.Body, &params)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if params["key"] == "" {
		http.Error(w, "A key is needed", http.StatusBadRequest)
		return
	}
	u.Keys = append(u.Keys, params["key"])
	err = c.Update(bson.M{"_id": u.Name}, u)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Key \"%s\" successfuly created", params["key"])
}

func NewUser(w http.ResponseWriter, r *http.Request) {
	var usr user.User
	err := parseBody(r.Body, &usr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	u, err := user.New(usr.Name, usr.Keys)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "User %s successfuly created", u.Name)
}

func RemoveUser(w http.ResponseWriter, r *http.Request) {
	u := &user.User{Name: r.URL.Query().Get(":name")}
	err := user.Remove(u)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "User %s successfuly removed", u)
}

func NewRepository(w http.ResponseWriter, r *http.Request) {
	var repo repository.Repository
	err := parseBody(r.Body, &repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	rep, err := repository.New(repo.Name, repo.Users, repo.IsPublic)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "Repository %s successfuly created", rep.Name)
}

func RemoveRepository(w http.ResponseWriter, r *http.Request) {
	repo := &repository.Repository{Name: r.URL.Query().Get(":name")}
	err := repository.Remove(repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}
	fmt.Fprintf(w, "Repository %s successfuly removed", repo.Name)
}

func parseBody(body io.ReadCloser, result interface{}) error {
	if reflect.ValueOf(result).Kind() == reflect.Struct {
		return errors.New("parseBody function cannot deal with struct. Use pointer")
	}
	b, err := ioutil.ReadAll(body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, &result)
	if err != nil {
		e := fmt.Sprintf("Could not parse json: %s", err.Error())
		return errors.New(e)
	}
	return nil
}
<commit_msg>api: added some todo commends on GrantAccces handler<commit_after>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/globocom/gandalf/db"
	"github.com/globocom/gandalf/repository"
	"github.com/globocom/gandalf/user"
	"io"
	"io/ioutil"
	"labix.org/v2/mgo/bson"
	"net/http"
	"reflect"
)

func GrantAccess(w http.ResponseWriter, r *http.Request) {
	// it's need a intermediary method to grant access to a user into a repository
	// something equivalent to what we have in NewUser handler
	repo := repository.Repository{Name: r.URL.Query().Get(":name")}
	c := db.Session.Repository()
	c.Find(bson.M{"_id": repo.Name}).One(&repo)
	req := map[string][]string{}
	err := parseBody(r.Body, &req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	for _, u := range req["users"] {
		// TODO (flaviamissi): query all only once, then iterate over them?
		_, err = getUserOr404(u)
		if err != nil {
			if len(req["users"]) == 1 {
				http.Error(w, err.Error(), http.StatusNotFound)
				return
			} else {
				// #TODO (flaviamissi): log a warning saying the user "u" was not found and skip it
				continue
			}
		}
		repo.Users = append(repo.Users, u)
	}
	err = c.Update(bson.M{"_id": repo.Name}, &repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func AddKey(w http.ResponseWriter, r *http.Request) {
	u := user.User{Name: r.URL.Query().Get(":name")}
	c := db.Session.User()
	err := c.Find(bson.M{"_id": u.Name}).One(&u)
	if err != nil {
		http.Error(w, "User not found", http.StatusNotFound)
		return
	}
	params := map[string]string{}
	err = parseBody(r.Body, &params)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if params["key"] == "" {
		http.Error(w, "A key is needed", http.StatusBadRequest)
		return
	}
	u.Keys = append(u.Keys, params["key"])
	err = c.Update(bson.M{"_id": u.Name}, u)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Key \"%s\" successfuly created", params["key"])
}

func NewUser(w http.ResponseWriter, r *http.Request) {
	var usr user.User
	err := parseBody(r.Body, &usr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	u, err := user.New(usr.Name, usr.Keys)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "User %s successfuly created", u.Name)
}

func RemoveUser(w http.ResponseWriter, r *http.Request) {
	u := &user.User{Name: r.URL.Query().Get(":name")}
	err := user.Remove(u)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "User %s successfuly removed", u)
}

func NewRepository(w http.ResponseWriter, r *http.Request) {
	var repo repository.Repository
	err := parseBody(r.Body, &repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	rep, err := repository.New(repo.Name, repo.Users, repo.IsPublic)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "Repository %s successfuly created", rep.Name)
}

func RemoveRepository(w http.ResponseWriter, r *http.Request) {
	repo := &repository.Repository{Name: r.URL.Query().Get(":name")}
	err := repository.Remove(repo)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}
	fmt.Fprintf(w, "Repository %s successfuly removed", repo.Name)
}

func parseBody(body io.ReadCloser, result interface{}) error {
	if reflect.ValueOf(result).Kind() == reflect.Struct {
		return errors.New("parseBody function cannot deal with struct. Use pointer")
	}
	b, err := ioutil.ReadAll(body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, &result)
	if err != nil {
		e := fmt.Sprintf("Could not parse json: %s", err.Error())
		return errors.New(e)
	}
	return nil
}
<|endoftext|>


<commit_before>package utils

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"

	"github.com/docker/docker/pkg/term"
	"github.com/docker/docker/pkg/units"
)

type JSONError struct {
	Code    int    `json:"code,omitempty"`
	Message string `json:"message,omitempty"`
}

func (e *JSONError) Error() string {
	return e.Message
}

type JSONProgress struct {
	terminalFd uintptr
	Current    int   `json:"current,omitempty"`
	Total      int   `json:"total,omitempty"`
	Start      int64 `json:"start,omitempty"`
}

func (p *JSONProgress) String() string {
	var (
		width       = 200
		pbBox       string
		numbersBox  string
		timeLeftBox string
	)

	ws, err := term.GetWinsize(p.terminalFd)
	if err == nil {
		width = int(ws.Width)
	}

	if p.Current <= 0 && p.Total <= 0 {
		return ""
	}
	current := units.HumanSize(int64(p.Current))
	if p.Total <= 0 {
		return fmt.Sprintf("%8v", current)
	}
	total := units.HumanSize(int64(p.Total))
	percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
	if width > 110 {
		pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", 50-percentage))
	}
	numbersBox = fmt.Sprintf("%8v/%v", current, total)

	if p.Current > 0 && p.Start > 0 && percentage < 50 {
		fromStart := time.Now().UTC().Sub(time.Unix(int64(p.Start), 0))
		perEntry := fromStart / time.Duration(p.Current)
		left := time.Duration(p.Total-p.Current) * perEntry
		left = (left / time.Second) * time.Second

		if width > 50 {
			timeLeftBox = " " + left.String()
		}
	}
	return pbBox + numbersBox + timeLeftBox
}

type JSONMessage struct {
	Stream          string        `json:"stream,omitempty"`
	Status          string        `json:"status,omitempty"`
	Progress        *JSONProgress `json:"progressDetail,omitempty"`
	ProgressMessage string        `json:"progress,omitempty"` //deprecated
	ID              string        `json:"id,omitempty"`
	From            string        `json:"from,omitempty"`
	Time            int64         `json:"time,omitempty"`
	Error           *JSONError    `json:"errorDetail,omitempty"`
	ErrorMessage    string        `json:"error,omitempty"` //deprecated
}

func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
	if jm.Error != nil {
		if jm.Error.Code == 401 {
			return fmt.Errorf("Authentication is required.")
		}
		return jm.Error
	}
	var endl string
	if isTerminal && jm.Stream == "" && jm.Progress != nil {
		// <ESC>[2K = erase entire current line
		fmt.Fprintf(out, "%c[2K\r", 27)
		endl = "\r"
	} else if jm.Progress != nil { //disable progressbar in non-terminal
		return nil
	}
	if jm.Time != 0 {
		fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(time.RFC3339Nano))
	}
	if jm.ID != "" {
		fmt.Fprintf(out, "%s: ", jm.ID)
	}
	if jm.From != "" {
		fmt.Fprintf(out, "(from %s) ", jm.From)
	}
	if jm.Progress != nil {
		fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
	} else if jm.ProgressMessage != "" { //deprecated
		fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl)
	} else if jm.Stream != "" {
		fmt.Fprintf(out, "%s%s", jm.Stream, endl)
	} else {
		fmt.Fprintf(out, "%s%s\n", jm.Status, endl)
	}
	return nil
}

func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool) error {
	var (
		dec  = json.NewDecoder(in)
		ids  = make(map[string]int)
		diff = 0
	)
	for {
		var jm JSONMessage
		if err := dec.Decode(&jm); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		if jm.Progress != nil {
			jm.Progress.terminalFd = terminalFd
		}
		if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") {
			line, ok := ids[jm.ID]
			if !ok {
				line = len(ids)
				ids[jm.ID] = line
				fmt.Fprintf(out, "\n")
				diff = 0
			} else {
				diff = len(ids) - line
			}
			if jm.ID != "" && isTerminal {
				// <ESC>[{diff}A = move cursor up diff rows
				fmt.Fprintf(out, "%c[%dA", 27, diff)
			}
		}
		err := jm.Display(out, isTerminal)
		if jm.ID != "" && isTerminal {
			// <ESC>[{diff}B = move cursor down diff rows
			fmt.Fprintf(out, "%c[%dB", 27, diff)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>progress bar: don't strings.Repeat a negative number<commit_after>package utils

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"

	"github.com/docker/docker/pkg/term"
	"github.com/docker/docker/pkg/units"
)

type JSONError struct {
	Code    int    `json:"code,omitempty"`
	Message string `json:"message,omitempty"`
}

func (e *JSONError) Error() string {
	return e.Message
}

type JSONProgress struct {
	terminalFd uintptr
	Current    int   `json:"current,omitempty"`
	Total      int   `json:"total,omitempty"`
	Start      int64 `json:"start,omitempty"`
}

func (p *JSONProgress) String() string {
	var (
		width       = 200
		pbBox       string
		numbersBox  string
		timeLeftBox string
	)

	ws, err := term.GetWinsize(p.terminalFd)
	if err == nil {
		width = int(ws.Width)
	}

	if p.Current <= 0 && p.Total <= 0 {
		return ""
	}
	current := units.HumanSize(int64(p.Current))
	if p.Total <= 0 {
		return fmt.Sprintf("%8v", current)
	}
	total := units.HumanSize(int64(p.Total))
	percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
	if width > 110 {
		// this number can't be negetive gh#7136
		numSpaces := 0
		if 50-percentage > 0 {
			numSpaces = 50 - percentage
		}
		pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces))
	}
	numbersBox = fmt.Sprintf("%8v/%v", current, total)

	if p.Current > 0 && p.Start > 0 && percentage < 50 {
		fromStart := time.Now().UTC().Sub(time.Unix(int64(p.Start), 0))
		perEntry := fromStart / time.Duration(p.Current)
		left := time.Duration(p.Total-p.Current) * perEntry
		left = (left / time.Second) * time.Second

		if width > 50 {
			timeLeftBox = " " + left.String()
		}
	}
	return pbBox + numbersBox + timeLeftBox
}

type JSONMessage struct {
	Stream          string        `json:"stream,omitempty"`
	Status          string        `json:"status,omitempty"`
	Progress        *JSONProgress `json:"progressDetail,omitempty"`
	ProgressMessage string        `json:"progress,omitempty"` //deprecated
	ID              string        `json:"id,omitempty"`
	From            string        `json:"from,omitempty"`
	Time            int64         `json:"time,omitempty"`
	Error           *JSONError    `json:"errorDetail,omitempty"`
	ErrorMessage    string        `json:"error,omitempty"` //deprecated
}

func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
	if jm.Error != nil {
		if jm.Error.Code == 401 {
			return fmt.Errorf("Authentication is required.")
		}
		return jm.Error
	}
	var endl string
	if isTerminal && jm.Stream == "" && jm.Progress != nil {
		// <ESC>[2K = erase entire current line
		fmt.Fprintf(out, "%c[2K\r", 27)
		endl = "\r"
	} else if jm.Progress != nil { //disable progressbar in non-terminal
		return nil
	}
	if jm.Time != 0 {
		fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(time.RFC3339Nano))
	}
	if jm.ID != "" {
		fmt.Fprintf(out, "%s: ", jm.ID)
	}
	if jm.From != "" {
		fmt.Fprintf(out, "(from %s) ", jm.From)
	}
	if jm.Progress != nil {
		fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
	} else if jm.ProgressMessage != "" { //deprecated
		fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl)
	} else if jm.Stream != "" {
		fmt.Fprintf(out, "%s%s", jm.Stream, endl)
	} else {
		fmt.Fprintf(out, "%s%s\n", jm.Status, endl)
	}
	return nil
}

func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool) error {
	var (
		dec  = json.NewDecoder(in)
		ids  = make(map[string]int)
		diff = 0
	)
	for {
		var jm JSONMessage
		if err := dec.Decode(&jm); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		if jm.Progress != nil {
			jm.Progress.terminalFd = terminalFd
		}
		if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") {
			line, ok := ids[jm.ID]
			if !ok {
				line = len(ids)
				ids[jm.ID] = line
				fmt.Fprintf(out, "\n")
				diff = 0
			} else {
				diff = len(ids) - line
			}
			if jm.ID != "" && isTerminal {
				// <ESC>[{diff}A = move cursor up diff rows
				fmt.Fprintf(out, "%c[%dA", 27, diff)
			}
		}
		err := jm.Display(out, isTerminal)
		if jm.ID != "" && isTerminal {
			// <ESC>[{diff}B = move cursor down diff rows
			fmt.Fprintf(out, "%c[%dB", 27, diff)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Salsita Software
// Use of this source code is governed by the MIT License.
// The license can be found in the LICENSE file.

package pivotal

import (
	"fmt"
	"net/http"
)

// ErrAPI ----------------------------------------------------------------------

type Error struct {
	Code             string `json:"code"`
	Error            string `json:"error"`
	Requirement      string `json:"requirement"`
	GeneralProblem   string `json:"general_problem"`
	PossibleFix      string `json:"possible_fix"`
	ValidationErrors []struct {
		Field   string `json:"field"`
		Problem string `json:"problem"`
	} `json:"validation_errors"`
}

type ErrAPI struct {
	Response *http.Response
	Err      *Error
}

func (err *ErrAPI) Error() string {
	req := err.Response.Request
	return fmt.Sprintf(
		"%v %v -> %v (error = %+v)",
		req.Method,
		req.URL,
		err.Response.Status,
		err.Err)
}

// ErrFieldNotSet --------------------------------------------------------------

type ErrFieldNotSet struct {
	fieldName string
}

func (err *ErrFieldNotSet) Error() string {
	return fmt.Sprintf("Required field '%s' is not set")
}
<commit_msg>Fixes missing format value<commit_after>// Copyright (c) 2014 Salsita Software
// Use of this source code is governed by the MIT License.
// The license can be found in the LICENSE file.

package pivotal

import (
	"fmt"
	"net/http"
)

// ErrAPI ----------------------------------------------------------------------

type Error struct {
	Code             string `json:"code"`
	Error            string `json:"error"`
	Requirement      string `json:"requirement"`
	GeneralProblem   string `json:"general_problem"`
	PossibleFix      string `json:"possible_fix"`
	ValidationErrors []struct {
		Field   string `json:"field"`
		Problem string `json:"problem"`
	} `json:"validation_errors"`
}

type ErrAPI struct {
	Response *http.Response
	Err      *Error
}

func (err *ErrAPI) Error() string {
	req := err.Response.Request
	return fmt.Sprintf(
		"%v %v -> %v (error = %+v)",
		req.Method,
		req.URL,
		err.Response.Status,
		err.Err)
}

// ErrFieldNotSet --------------------------------------------------------------

type ErrFieldNotSet struct {
	fieldName string
}

func (err *ErrFieldNotSet) Error() string {
	return fmt.Sprintf("Required field '%s' is not set", err.fieldName)
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"

	"github.com/hashicorp/vault/api"
)

type Vault interface {
	LookupWithAppRole(roleID, secretID, path string) (*Config, error)
	LookupWithToken(token, path string) (*Config, error)
}

type vault struct {
	client    *api.Client
	vaultAddr string
}

func NewVault(vaultAddr, caCertFile string) (Vault, error) {
	cfg := api.DefaultConfig()
	if err := cfg.ReadEnvironment(); err != nil {
		return nil, err
	}
	if vaultAddr != "" {
		cfg.Address = vaultAddr
	}
	if caCertFile != "" {
		t := &api.TLSConfig{CACert: caCertFile}
		if err := cfg.ConfigureTLS(t); err != nil {
			return nil, err
		}
	}
	client, err := api.NewClient(cfg)
	if err != nil {
		return nil, err
	}
	return &vault{
		client:    client,
		vaultAddr: vaultAddr,
	}, nil
}

func (v *vault) LookupWithAppRole(roleID, secretID, path string) (*Config, error) {
	body := map[string]interface{}{
		"role_id":   roleID,
		"secret_id": secretID,
	}
	secret, err := v.client.Logical().Write("auth/approle/login", body)
	if err != nil {
		return nil, err
	}
	return v.LookupWithToken(secret.Auth.ClientToken, path)
}

func (v *vault) LookupWithToken(token, path string) (*Config, error) {
	if token != "" {
		v.client.SetToken(token)
	}
	secret, err := v.client.Logical().Read(path)
	if err != nil {
		return nil, err
	}
	return &Config{
		CipherKey:   get(secret.Data, "cipher_key"),
		S3AccessKey: get(secret.Data, "s3_access_key"),
		S3SecretKey: get(secret.Data, "s3_secret_key"),
		S3Token:     get(secret.Data, "s3_token"),
		S3Region:    get(secret.Data, "s3_region"),
		S3Endpoint:  get(secret.Data, "s3_endpoint"),
	}, nil
}

func get(m map[string]interface{}, key string) string {
	val, ok := m[key]
	if !ok {
		return ""
	}
	return fmt.Sprint(val)
}
<commit_msg>vaultAddr is not required<commit_after>package config

import (
	"fmt"

	"github.com/hashicorp/vault/api"
)

type Vault interface {
	LookupWithAppRole(roleID, secretID, path string) (*Config, error)
	LookupWithToken(token, path string) (*Config, error)
}

type vault struct {
	client *api.Client
}

func NewVault(vaultAddr, caCertFile string) (Vault, error) {
	cfg := api.DefaultConfig()
	if err := cfg.ReadEnvironment(); err != nil {
		return nil, err
	}
	if vaultAddr != "" {
		cfg.Address = vaultAddr
	}
	if caCertFile != "" {
		t := &api.TLSConfig{CACert: caCertFile}
		if err := cfg.ConfigureTLS(t); err != nil {
			return nil, err
		}
	}
	client, err := api.NewClient(cfg)
	if err != nil {
		return nil, err
	}
	return &vault{client}, nil
}

func (v *vault) LookupWithAppRole(roleID, secretID, path string) (*Config, error) {
	body := map[string]interface{}{
		"role_id":   roleID,
		"secret_id": secretID,
	}
	secret, err := v.client.Logical().Write("auth/approle/login", body)
	if err != nil {
		return nil, err
	}
	return v.LookupWithToken(secret.Auth.ClientToken, path)
}

func (v *vault) LookupWithToken(token, path string) (*Config, error) {
	if token != "" {
		v.client.SetToken(token)
	}
	secret, err := v.client.Logical().Read(path)
	if err != nil {
		return nil, err
	}
	return &Config{
		CipherKey:   get(secret.Data, "cipher_key"),
		S3AccessKey: get(secret.Data, "s3_access_key"),
		S3SecretKey: get(secret.Data, "s3_secret_key"),
		S3Token:     get(secret.Data, "s3_token"),
		S3Region:    get(secret.Data, "s3_region"),
		S3Endpoint:  get(secret.Data, "s3_endpoint"),
	}, nil
}

func get(m map[string]interface{}, key string) string {
	val, ok := m[key]
	if !ok {
		return ""
	}
	return fmt.Sprint(val)
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Mainflux
 *
 * Mainflux server is licensed under an Apache license, version 2.0.
 * All rights not explicitly granted in the Apache license, version 2.0 are reserved.
 * See the included LICENSE file for more details.
 */

package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/cisco/senml"
	"github.com/go-zoo/bone"
)

const (
	senMl string = "application/senml+json"
	blob  string = "application/octet-stream"
)

// sendMessage function
func sendMessage(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	if len(data) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		str := `{"response": "no data provided"}`
		io.WriteString(w, str)
		return
	}
	// Validate Content-Type
	ctype, err := validateContentType(r.Header.Get("Content-Type"))
	if err != nil {
		// Return content type error
		w.WriteHeader(http.StatusUnsupportedMediaType)
		str := `{"response": "` + err.Error() + `"}`
		io.WriteString(w, str)
		return
	}
	//If is senML validate it
	if ctype == senMl {
		var err error
		if _, err = senml.Decode(data, senml.JSON); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			str := `{"response": "senML validation faild"}`
			io.WriteString(w, str)
			return
		}
	}

	cid := bone.GetValue(r, "channel_id")

	// Publisher ID header
	hdr := r.Header.Get("Client-ID")

	// Publish message on MQTT via NATS
	m := NatsMsg{}
	m.Channel = cid
	m.Publisher = hdr
	m.Protocol = "http"
	m.Payload = data
	// Add ContentType to NatsMsg
	m.ContentType = cleanContentType(ctype)

	fmt.Printf(m.ContentType)

	b, err := json.Marshal(m)
	if err != nil {
		log.Print(err)
	}
	NatsConn.Publish("msg.http", b)

	// Send back response to HTTP client
	// We have accepted the request and published it over MQTT,
	// but we do not know if it will be executed or not (MQTT is not req-reply protocol)
	w.WriteHeader(http.StatusAccepted)
	str := `{"response": "message sent"}`
	io.WriteString(w, str)
}

func cleanContentType(ct string) string {
	return strings.Split(ct, "/")[1]
}

func validateContentType(content string) (result string, err error) {

	switch content {
	case blob, senMl:
		return content, nil
	}
	return content, errors.New("Unsuproted Content-Type")

}
<commit_msg>Refactored content type validation, remove logs<commit_after>/**
 * Copyright (c) Mainflux
 *
 * Mainflux server is licensed under an Apache license, version 2.0.
 * All rights not explicitly granted in the Apache license, version 2.0 are reserved.
 * See the included LICENSE file for more details.
 */

package api

import (
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/cisco/senml"
	"github.com/go-zoo/bone"
)

const (
	senMl string = "application/senml+json"
	blob  string = "application/octet-stream"
)

// sendMessage function
func sendMessage(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	if len(data) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		str := `{"response": "no data provided"}`
		io.WriteString(w, str)
		return
	}
	// Validate Content-Type
	ctype, err := validateContentType(r.Header.Get("Content-Type"))
	if err != nil {
		// Return content type error
		w.WriteHeader(http.StatusUnsupportedMediaType)
		str := `{"response": "` + err.Error() + `"}`
		io.WriteString(w, str)
		return
	}
	//If is senML validate it
	if ctype == senMl {
		var err error
		if _, err = senml.Decode(data, senml.JSON); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			str := `{"response": "senML validation faild"}`
			io.WriteString(w, str)
			return
		}
	}

	cid := bone.GetValue(r, "channel_id")

	// Publisher ID header
	hdr := r.Header.Get("Client-ID")

	// Publish message on MQTT via NATS
	m := NatsMsg{}
	m.Channel = cid
	m.Publisher = hdr
	m.Protocol = "http"
	m.Payload = data
	// Add ContentType to NatsMsg
	m.ContentType = cleanContentType(ctype)

	b, err := json.Marshal(m)
	if err != nil {
		log.Print(err)
	}
	NatsConn.Publish("msg.http", b)

	// Send back response to HTTP client
	// We have accepted the request and published it over MQTT,
	// but we do not know if it will be executed or not (MQTT is not req-reply protocol)
	w.WriteHeader(http.StatusAccepted)
	str := `{"response": "message sent"}`
	io.WriteString(w, str)
}

func cleanContentType(ct string) string {
	return strings.Split(ct, "/")[1]
}

func validateContentType(content string) (result string, err error) {

	switch content {
	case blob, senMl:
		return content, nil
	}
	return content, errors.New("Unsuproted Content-Type")

}
<|endoftext|>