<commit_before>package termbox

import (
	"syscall"
)

// public API

// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Close' function.
//
// Example usage:
//      err := termbox.Init()
//      if err != nil {
//              panic(err)
//      }
//      defer termbox.Close()
func Init() error {
	var err error

	in, err = syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
	if err != nil {
		return err
	}
	out, err = syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
	if err != nil {
		return err
	}

	err = get_console_mode(in, &orig_mode)
	if err != nil {
		return err
	}

	err = set_console_mode(in, enable_window_input)
	consolewin = err == nil

	orig_screen = out
	out, err = create_console_screen_buffer()
	if err != nil {
		return err
	}
	w, h := get_win_size(out)

	err = set_console_screen_buffer_size(out, coord{short(w), short(h)})
	if err != nil {
		return err
	}

	err = set_console_active_screen_buffer(out)
	if err != nil {
		return err
	}

	show_cursor(false)
	termw, termh = get_term_size(out)
	back_buffer.init(termw, termh)
	front_buffer.init(termw, termh)
	back_buffer.clear()
	front_buffer.clear()
	clear()

	attrsbuf = make([]word, 0, termw*termh)
	charsbuf = make([]wchar, 0, termw*termh)
	diffbuf = make([]diff_msg, 0, 32)

	go input_event_producer()

	return nil
}

// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Close() {
	// we ignore errors here, because we can't really do anything about them
	set_console_mode(in, orig_mode)
	set_console_active_screen_buffer(orig_screen)
	syscall.Close(out)
}

// Synchronizes the internal back buffer with the terminal.
func Flush() error {
	update_size_maybe()
	prepare_diff_messages()
	for _, msg := range diffbuf {
		write_console_output_attribute(out, msg.attrs, msg.pos)
		write_console_output_character(out, msg.chars, msg.pos)
	}
	if !is_cursor_hidden(cursor_x, cursor_y) {
		move_cursor(cursor_x, cursor_y)
	}
	return nil
}

// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
	if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
		show_cursor(true)
	}

	if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
		show_cursor(false)
	}

	cursor_x, cursor_y = x, y
	if !is_cursor_hidden(cursor_x, cursor_y) {
		move_cursor(cursor_x, cursor_y)
	}
}

// The shortcut for SetCursor(-1, -1).
func HideCursor() {
	SetCursor(cursor_hidden, cursor_hidden)
}

// Changes cell's parameters in the internal back buffer at the specified
// position.
func SetCell(x, y int, ch rune, fg, bg Attribute) {
	if x < 0 || x >= back_buffer.width {
		return
	}
	if y < 0 || y >= back_buffer.height {
		return
	}

	back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
}

// Returns a slice into the termbox's back buffer. You can get its dimensions
// using 'Size' function. The slice remains valid as long as no 'Clear' or
// 'Flush' function calls were made after call to this function.
func CellBuffer() []Cell {
	return back_buffer.cells
}

// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
	return <-input_comm
}

// Returns the size of the internal back buffer (which is mostly the same as
// console's window size in characters). But it doesn't always match the size
// of the console window, after the console size has changed, the internal back
// buffer will get in sync only after Clear or Flush function calls.
func Size() (int, int) {
	return termw, termh
}

// Clears the internal back buffer.
func Clear(fg, bg Attribute) error {
	foreground, background = fg, bg
	update_size_maybe()
	back_buffer.clear()
	return nil
}

// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc. This is the default input mode.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
// enable mouse button click events.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
	if mode == InputCurrent {
		return input_mode
	}
	if consolewin {
		if mode&InputMouse != 0 {
			err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags)
			if err != nil {
				panic(err)
			}
		} else {
			err := set_console_mode(in, enable_window_input)
			if err != nil {
				panic(err)
			}
		}
	}

	input_mode = mode
	return input_mode
}

// Sets the termbox output mode.
//
// Windows console does not support extra colour modes,
// so this will always set and return OutputNormal.
func SetOutputMode(mode OutputMode) OutputMode {
	output_mode = OutputNormal
	return output_mode
}

// Sync comes handy when something causes desync between termbox's understanding
// of a terminal buffer and the reality. Such as a third party process. Sync
// forces a complete resync between the termbox and a terminal, it may not be
// visually pretty though. At the moment on Windows it does nothing.
func Sync() error {
	return nil
}
<commit_msg>Remove 'output_mode' use from windows part, fixes compilation.<commit_after>package termbox

import (
	"syscall"
)

// public API

// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Close' function.
//
// Example usage:
//      err := termbox.Init()
//      if err != nil {
//              panic(err)
//      }
//      defer termbox.Close()
func Init() error {
	var err error

	in, err = syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
	if err != nil {
		return err
	}
	out, err = syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
	if err != nil {
		return err
	}

	err = get_console_mode(in, &orig_mode)
	if err != nil {
		return err
	}

	err = set_console_mode(in, enable_window_input)
	consolewin = err == nil

	orig_screen = out
	out, err = create_console_screen_buffer()
	if err != nil {
		return err
	}
	w, h := get_win_size(out)

	err = set_console_screen_buffer_size(out, coord{short(w), short(h)})
	if err != nil {
		return err
	}

	err = set_console_active_screen_buffer(out)
	if err != nil {
		return err
	}

	show_cursor(false)
	termw, termh = get_term_size(out)
	back_buffer.init(termw, termh)
	front_buffer.init(termw, termh)
	back_buffer.clear()
	front_buffer.clear()
	clear()

	attrsbuf = make([]word, 0, termw*termh)
	charsbuf = make([]wchar, 0, termw*termh)
	diffbuf = make([]diff_msg, 0, 32)

	go input_event_producer()

	return nil
}

// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Close() {
	// we ignore errors here, because we can't really do anything about them
	set_console_mode(in, orig_mode)
	set_console_active_screen_buffer(orig_screen)
	syscall.Close(out)
}

// Synchronizes the internal back buffer with the terminal.
func Flush() error {
	update_size_maybe()
	prepare_diff_messages()
	for _, msg := range diffbuf {
		write_console_output_attribute(out, msg.attrs, msg.pos)
		write_console_output_character(out, msg.chars, msg.pos)
	}
	if !is_cursor_hidden(cursor_x, cursor_y) {
		move_cursor(cursor_x, cursor_y)
	}
	return nil
}

// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
	if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
		show_cursor(true)
	}

	if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
		show_cursor(false)
	}

	cursor_x, cursor_y = x, y
	if !is_cursor_hidden(cursor_x, cursor_y) {
		move_cursor(cursor_x, cursor_y)
	}
}

// The shortcut for SetCursor(-1, -1).
func HideCursor() {
	SetCursor(cursor_hidden, cursor_hidden)
}

// Changes cell's parameters in the internal back buffer at the specified
// position.
func SetCell(x, y int, ch rune, fg, bg Attribute) {
	if x < 0 || x >= back_buffer.width {
		return
	}
	if y < 0 || y >= back_buffer.height {
		return
	}

	back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg}
}

// Returns a slice into the termbox's back buffer. You can get its dimensions
// using 'Size' function. The slice remains valid as long as no 'Clear' or
// 'Flush' function calls were made after call to this function.
func CellBuffer() []Cell {
	return back_buffer.cells
}

// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
	return <-input_comm
}

// Returns the size of the internal back buffer (which is mostly the same as
// console's window size in characters). But it doesn't always match the size
// of the console window, after the console size has changed, the internal back
// buffer will get in sync only after Clear or Flush function calls.
func Size() (int, int) {
	return termw, termh
}

// Clears the internal back buffer.
func Clear(fg, bg Attribute) error {
	foreground, background = fg, bg
	update_size_maybe()
	back_buffer.clear()
	return nil
}

// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc. This is the default input mode.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will
// enable mouse button click events.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
	if mode == InputCurrent {
		return input_mode
	}
	if consolewin {
		if mode&InputMouse != 0 {
			err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags)
			if err != nil {
				panic(err)
			}
		} else {
			err := set_console_mode(in, enable_window_input)
			if err != nil {
				panic(err)
			}
		}
	}

	input_mode = mode
	return input_mode
}

// Sets the termbox output mode.
//
// Windows console does not support extra colour modes,
// so this will always set and return OutputNormal.
func SetOutputMode(mode OutputMode) OutputMode {
	return OutputNormal
}

// Sync comes handy when something causes desync between termbox's understanding
// of a terminal buffer and the reality. Such as a third party process. Sync
// forces a complete resync between the termbox and a terminal, it may not be
// visually pretty though. At the moment on Windows it does nothing.
func Sync() error {
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2019 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package base

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/starlark/interpreter"

	"go.chromium.org/luci/lucicfg"
)

// GenerateConfigs executes the Starlark script and assembles final values for
// meta config.
//
// It is a common part of subcommands that generate configs.
//
// 'meta' is initial Meta config with default parameters, it will be mutated
// in-place to contain the final parameters (based on lucicfg.config(...) calls
// in Starlark and the config populated via CLI flags, passed as 'flags').
// 'flags' are also mutated in-place to rebase ConfigDir onto cwd.
//
// 'vars' are a collection of k=v pairs passed via CLI flags as `-var k=v`. They
// are used to pre-set lucicfg.var(..., exposed_as=<k>) variables.
func GenerateConfigs(ctx context.Context, inputFile string, meta, flags *lucicfg.Meta, vars map[string]string) (*lucicfg.State, error) {
	abs, err := filepath.Abs(inputFile)
	if err != nil {
		return nil, err
	}

	// Make sure the input file exists, to make the error message in this case be
	// more humane. lucicfg.Generate will formulate this error as "no such module"
	// which looks confusing.
	//
	// Also check that the script starts with "#!..." line, indicating it is
	// executable. This gives a hint in case lucicfg is mistakenly invoked with
	// some library script. Executing such scripts directly usually causes very
	// confusing errors.
	switch f, err := os.Open(abs); {
	case os.IsNotExist(err):
		return nil, fmt.Errorf("no such file: %s", inputFile)
	case err != nil:
		return nil, err
	default:
		yes, err := startsWithShebang(f)
		f.Close()
		switch {
		case err != nil:
			return nil, err
		case !yes:
			fmt.Fprintf(os.Stderr,
				`================================= WARNING =================================
Body of the script %s doesn't start with "#!".

It is likely not a correct entry point script and lucicfg execution will fail
with cryptic errors or unexpected results. Many configs consist of more than
one *.star file, but there's usually only one entry point script that should
be passed to lucicfg.

If it is the correct script, make sure it starts with the following line to
indicate it is executable (and remove this warning):

    #!/usr/bin/env lucicfg

You may also optionally set +x flag on it, but this is not required.
===========================================================================

`, filepath.Base(abs))
		}
	}

	// The directory with the input file becomes the root of the main package.
	root, main := filepath.Split(abs)

	// Generate everything, storing the result in memory.
	logging.Infof(ctx, "Generating configs...")
	state, err := lucicfg.Generate(ctx, lucicfg.Inputs{
		Code:  interpreter.FileSystemLoader(root),
		Path:  root,
		Entry: main,
		Meta:  meta,
		Vars:  vars,
	})
	if err != nil {
		return nil, err
	}

	// Config dir in the default meta, and if set from Starlark, is relative to
	// the main package root. It is relative to cwd ONLY when explicitly provided
	// via -config-dir CLI flag. Note that ".." is allowed.
	cwd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	meta.RebaseConfigDir(root)
	state.Meta.RebaseConfigDir(root)
	flags.RebaseConfigDir(cwd)

	// Figure out the final meta config: values set via starlark override
	// defaults, and values passed explicitly via CLI flags override what is
	// in starlark.
	meta.PopulateFromTouchedIn(&state.Meta)
	meta.PopulateFromTouchedIn(flags)
	meta.Log(ctx)

	// Discard changes to the non-tracked files by loading their original bodies
	// (if any) from disk. We replace them to make sure the output is still
	// validated as a whole, it is just only partially generated in this case.
	if len(meta.TrackedFiles) != 0 {
		if err := state.Output.DiscardChangesToUntracked(ctx, meta.TrackedFiles, meta.ConfigDir); err != nil {
			return nil, err
		}
	}

	return state, nil
}

func startsWithShebang(r io.Reader) (bool, error) {
	buf := make([]byte, 2)
	switch _, err := io.ReadFull(r, buf); {
	case err == io.EOF || err == io.ErrUnexpectedEOF:
		return false, nil // the file is smaller than 2 bytes
	case err != nil:
		return false, err
	default:
		return bytes.Equal(buf, []byte("#!")), nil
	}
}
<commit_msg>[lucicfg] Log version of lucicfg when generating configs.<commit_after>// Copyright 2019 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package base

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/starlark/interpreter"

	"go.chromium.org/luci/lucicfg"
)

// GenerateConfigs executes the Starlark script and assembles final values for
// meta config.
//
// It is a common part of subcommands that generate configs.
//
// 'meta' is initial Meta config with default parameters, it will be mutated
// in-place to contain the final parameters (based on lucicfg.config(...) calls
// in Starlark and the config populated via CLI flags, passed as 'flags').
// 'flags' are also mutated in-place to rebase ConfigDir onto cwd.
//
// 'vars' are a collection of k=v pairs passed via CLI flags as `-var k=v`. They
// are used to pre-set lucicfg.var(..., exposed_as=<k>) variables.
func GenerateConfigs(ctx context.Context, inputFile string, meta, flags *lucicfg.Meta, vars map[string]string) (*lucicfg.State, error) {
	abs, err := filepath.Abs(inputFile)
	if err != nil {
		return nil, err
	}

	// Make sure the input file exists, to make the error message in this case be
	// more humane. lucicfg.Generate will formulate this error as "no such module"
	// which looks confusing.
	//
	// Also check that the script starts with "#!..." line, indicating it is
	// executable. This gives a hint in case lucicfg is mistakenly invoked with
	// some library script. Executing such scripts directly usually causes very
	// confusing errors.
	switch f, err := os.Open(abs); {
	case os.IsNotExist(err):
		return nil, fmt.Errorf("no such file: %s", inputFile)
	case err != nil:
		return nil, err
	default:
		yes, err := startsWithShebang(f)
		f.Close()
		switch {
		case err != nil:
			return nil, err
		case !yes:
			fmt.Fprintf(os.Stderr,
				`================================= WARNING =================================
Body of the script %s doesn't start with "#!".

It is likely not a correct entry point script and lucicfg execution will fail
with cryptic errors or unexpected results. Many configs consist of more than
one *.star file, but there's usually only one entry point script that should
be passed to lucicfg.

If it is the correct script, make sure it starts with the following line to
indicate it is executable (and remove this warning):

    #!/usr/bin/env lucicfg

You may also optionally set +x flag on it, but this is not required.
===========================================================================

`, filepath.Base(abs))
		}
	}

	// The directory with the input file becomes the root of the main package.
	root, main := filepath.Split(abs)

	// Generate everything, storing the result in memory.
	logging.Infof(ctx, "Generating configs using %s...", lucicfg.UserAgent)
	state, err := lucicfg.Generate(ctx, lucicfg.Inputs{
		Code:  interpreter.FileSystemLoader(root),
		Path:  root,
		Entry: main,
		Meta:  meta,
		Vars:  vars,
	})
	if err != nil {
		return nil, err
	}

	// Config dir in the default meta, and if set from Starlark, is relative to
	// the main package root. It is relative to cwd ONLY when explicitly provided
	// via -config-dir CLI flag. Note that ".." is allowed.
	cwd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	meta.RebaseConfigDir(root)
	state.Meta.RebaseConfigDir(root)
	flags.RebaseConfigDir(cwd)

	// Figure out the final meta config: values set via starlark override
	// defaults, and values passed explicitly via CLI flags override what is
	// in starlark.
	meta.PopulateFromTouchedIn(&state.Meta)
	meta.PopulateFromTouchedIn(flags)
	meta.Log(ctx)

	// Discard changes to the non-tracked files by loading their original bodies
	// (if any) from disk. We replace them to make sure the output is still
	// validated as a whole, it is just only partially generated in this case.
	if len(meta.TrackedFiles) != 0 {
		if err := state.Output.DiscardChangesToUntracked(ctx, meta.TrackedFiles, meta.ConfigDir); err != nil {
			return nil, err
		}
	}

	return state, nil
}

func startsWithShebang(r io.Reader) (bool, error) {
	buf := make([]byte, 2)
	switch _, err := io.ReadFull(r, buf); {
	case err == io.EOF || err == io.ErrUnexpectedEOF:
		return false, nil // the file is smaller than 2 bytes
	case err != nil:
		return false, err
	default:
		return bytes.Equal(buf, []byte("#!")), nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/version"
)

const (
	storagePoolVolumeTypeContainer = iota
	storagePoolVolumeTypeImage
	storagePoolVolumeTypeCustom
)

// Leave the string type in here! This guarantees that go treats this is as a
// typed string constant. Removing it causes go to treat these as untyped string
// constants which is not what we want.
const (
	storagePoolVolumeTypeNameContainer string = "container"
	storagePoolVolumeTypeNameImage     string = "image"
	storagePoolVolumeTypeNameCustom    string = "custom"
)

// Leave the string type in here! This guarantees that go treats this is as a
// typed string constant. Removing it causes go to treat these as untyped string
// constants which is not what we want.
const (
	storagePoolVolumeAPIEndpointContainers string = "containers"
	storagePoolVolumeAPIEndpointImages     string = "images"
	storagePoolVolumeAPIEndpointCustom     string = "custom"
)

var supportedVolumeTypes = []int{storagePoolVolumeTypeContainer, storagePoolVolumeTypeImage, storagePoolVolumeTypeCustom}

func storagePoolVolumeTypeNameToType(volumeTypeName string) (int, error) {
	switch volumeTypeName {
	case storagePoolVolumeTypeNameContainer:
		return storagePoolVolumeTypeContainer, nil
	case storagePoolVolumeTypeNameImage:
		return storagePoolVolumeTypeImage, nil
	case storagePoolVolumeTypeNameCustom:
		return storagePoolVolumeTypeCustom, nil
	}

	return -1, fmt.Errorf("invalid storage volume type name")
}

func storagePoolVolumeTypeNameToAPIEndpoint(volumeTypeName string) (string, error) {
	switch volumeTypeName {
	case storagePoolVolumeTypeNameContainer:
		return storagePoolVolumeAPIEndpointContainers, nil
	case storagePoolVolumeTypeNameImage:
		return storagePoolVolumeAPIEndpointImages, nil
	case storagePoolVolumeTypeNameCustom:
		return storagePoolVolumeAPIEndpointCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type name")
}

func storagePoolVolumeTypeToName(volumeType int) (string, error) {
	switch volumeType {
	case storagePoolVolumeTypeContainer:
		return storagePoolVolumeTypeNameContainer, nil
	case storagePoolVolumeTypeImage:
		return storagePoolVolumeTypeNameImage, nil
	case storagePoolVolumeTypeCustom:
		return storagePoolVolumeTypeNameCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type")
}

func storagePoolVolumeTypeToAPIEndpoint(volumeType int) (string, error) {
	switch volumeType {
	case storagePoolVolumeTypeContainer:
		return storagePoolVolumeAPIEndpointContainers, nil
	case storagePoolVolumeTypeImage:
		return storagePoolVolumeAPIEndpointImages, nil
	case storagePoolVolumeTypeCustom:
		return storagePoolVolumeAPIEndpointCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type")
}

func storagePoolVolumeUpdate(d *Daemon, poolName string, volumeName string, volumeType int, newDescription string, newConfig map[string]string) error {
	s, err := storagePoolVolumeInit(d, poolName, volumeName, volumeType)
	if err != nil {
		return err
	}

	oldWritable := s.GetStoragePoolVolumeWritable()
	newWritable := oldWritable

	// Backup the current state
	oldDescription := oldWritable.Description
	oldConfig := map[string]string{}
	err = shared.DeepCopy(&oldWritable.Config, &oldConfig)
	if err != nil {
		return err
	}

	// Define a function which reverts everything.  Defer this function
	// so that it doesn't need to be explicitly called in every failing
	// return path. Track whether or not we want to undo the changes
	// using a closure.
	undoChanges := true
	defer func() {
		if undoChanges {
			s.SetStoragePoolVolumeWritable(&oldWritable)
		}
	}()

	// Diff the configurations
	changedConfig := []string{}
	userOnly := true
	for key := range oldConfig {
		if oldConfig[key] != newConfig[key] {
			if !strings.HasPrefix(key, "user.") {
				userOnly = false
			}

			if !shared.StringInSlice(key, changedConfig) {
				changedConfig = append(changedConfig, key)
			}
		}
	}

	for key := range newConfig {
		if oldConfig[key] != newConfig[key] {
			if !strings.HasPrefix(key, "user.") {
				userOnly = false
			}

			if !shared.StringInSlice(key, changedConfig) {
				changedConfig = append(changedConfig, key)
			}
		}
	}

	// Apply config changes if there are any
	if len(changedConfig) != 0 {

		// Update the storage pool
		if !userOnly {
			err = s.StoragePoolVolumeUpdate(changedConfig)
			if err != nil {
				return err
			}
		}

		newWritable.Config = newConfig

		// Apply the new configuration
		s.SetStoragePoolVolumeWritable(&newWritable)
	}

	poolID, err := dbStoragePoolGetID(d.db, poolName)
	if err != nil {
		return err
	}

	// Update the database if something changed
	if len(changedConfig) != 0 || newDescription != oldDescription {
		err = dbStoragePoolVolumeUpdate(d.db, volumeName, volumeType, poolID, newDescription, newConfig)
		if err != nil {
			return err
		}
	}

	// Success, update the closure to mark that the changes should be kept.
	undoChanges = false

	return nil
}

func storagePoolVolumeUsedByGet(d *Daemon, volumeName string, volumeTypeName string) ([]string, error) {
	// Look for containers using the interface
	cts, err := dbContainersList(d.db, cTypeRegular)
	if err != nil {
		return []string{}, err
	}

	volumeUsedBy := []string{}
	volumeNameWithType := fmt.Sprintf("%s/%s", volumeTypeName, volumeName)
	for _, ct := range cts {
		c, err := containerLoadByName(d, ct)
		if err != nil {
			continue
		}

		for _, d := range c.LocalDevices() {
			if d["type"] != "disk" {
				continue
			}

			// Make sure that we don't compare against stuff like
			// "container////bla" but only against "container/bla".
			cleanSource := filepath.Clean(d["source"])
			if cleanSource == volumeName || cleanSource == volumeNameWithType {
				volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/containers/%s", version.APIVersion, ct))
			}
		}
	}

	profiles, err := profilesUsingPoolVolumeGetNames(d.db, volumeName, volumeTypeName)
	if err != nil {
		return []string{}, err
	}

	if len(volumeUsedBy) == 0 && len(profiles) == 0 {
		return []string{}, err
	}

	for _, pName := range profiles {
		volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/profiles/%s", version.APIVersion, pName))
	}

	return volumeUsedBy, nil
}

func profilesUsingPoolVolumeGetNames(db *sql.DB, volumeName string, volumeType string) ([]string, error) {
	usedBy := []string{}

	profiles, err := dbProfiles(db)
	if err != nil {
		return usedBy, err
	}

	for _, pName := range profiles {
		_, profile, err := dbProfileGet(db, pName)
		if err != nil {
			return usedBy, err
		}

		volumeNameWithType := fmt.Sprintf("%s/%s", volumeType, volumeName)
		for _, v := range profile.Devices {
			if v["type"] != "disk" {
				continue
			}

			// Can't be a storage volume.
			if filepath.IsAbs(v["source"]) {
				continue
			}

			// Make sure that we don't compare against stuff
			// like "container////bla" but only against
			// "container/bla".
			cleanSource := filepath.Clean(v["source"])
			if cleanSource == volumeName || cleanSource == volumeNameWithType {
				usedBy = append(usedBy, pName)
			}
		}
	}

	return usedBy, nil
}

func storagePoolVolumeDBCreate(d *Daemon, poolName string, volumeName, volumeDescription string, volumeTypeName string, volumeConfig map[string]string) error {
	// Check that the name of the new storage volume is valid. (For example.
	// zfs pools cannot contain "/" in their names.)
	err := storageValidName(volumeName)
	if err != nil {
		return err
	}

	// Convert the volume type name to our internal integer representation.
	volumeType, err := storagePoolVolumeTypeNameToType(volumeTypeName)
	if err != nil {
		return err
	}

	// We currently only allow to create storage volumes of type
	// storagePoolVolumeTypeCustom. So check, that nothing else was
	// requested.
	if volumeType != storagePoolVolumeTypeCustom {
		return fmt.Errorf("currently not allowed to create storage volumes of type %s", volumeTypeName)
	}

	// Load storage pool the volume will be attached to.
	poolID, poolStruct, err := dbStoragePoolGet(d.db, poolName)
	if err != nil {
		return err
	}

	// Check that a storage volume of the same storage volume type does not
	// already exist.
	volumeID, _ := dbStoragePoolVolumeGetTypeID(d.db, volumeName, volumeType, poolID)
	if volumeID > 0 {
		return fmt.Errorf("a storage volume of type %s does already exist", volumeTypeName)
	}

	// Make sure that we don't pass a nil to the next function.
	if volumeConfig == nil {
		volumeConfig = map[string]string{}
	}

	// Validate the requested storage volume configuration.
	err = storageVolumeValidateConfig(poolName, volumeConfig, poolStruct)
	if err != nil {
		return err
	}

	err = storageVolumeFillDefault(poolName, volumeConfig, poolStruct)
	if err != nil {
		return err
	}

	// Create the database entry for the storage volume.
	_, err = dbStoragePoolVolumeCreate(d.db, volumeName, volumeDescription, volumeType, poolID, volumeConfig)
	if err != nil {
		return fmt.Errorf("Error inserting %s of type %s into database: %s", poolName, volumeTypeName, err)
	}

	return nil
}

func storagePoolVolumeCreateInternal(d *Daemon, poolName string, volumeName, volumeDescription string, volumeTypeName string, volumeConfig map[string]string) error {
	err := storagePoolVolumeDBCreate(d, poolName, volumeName, volumeDescription, volumeTypeName, volumeConfig)
	if err != nil {
		return err
	}

	// Convert the volume type name to our internal integer representation.
	volumeType, err := storagePoolVolumeTypeNameToType(volumeTypeName)
	if err != nil {
		return err
	}

	s, err := storagePoolVolumeInit(d, poolName, volumeName, volumeType)
	if err != nil {
		return err
	}

	poolID, _ := s.GetContainerPoolInfo()

	// Create storage volume.
	err = s.StoragePoolVolumeCreate()
	if err != nil {
		dbStoragePoolVolumeDelete(d.db, volumeName, volumeType, poolID)
		return err
	}

	return nil
}
<commit_msg>storage: Fix UsedBy for containers and images<commit_after>package main

import (
	"database/sql"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/version"
)

const (
	storagePoolVolumeTypeContainer = iota
	storagePoolVolumeTypeImage
	storagePoolVolumeTypeCustom
)

// Leave the string type in here! This guarantees that go treats this is as a
// typed string constant. Removing it causes go to treat these as untyped string
// constants which is not what we want.
const (
	storagePoolVolumeTypeNameContainer string = "container"
	storagePoolVolumeTypeNameImage     string = "image"
	storagePoolVolumeTypeNameCustom    string = "custom"
)

// Leave the string type in here! This guarantees that go treats this is as a
// typed string constant. Removing it causes go to treat these as untyped string
// constants which is not what we want.
const (
	storagePoolVolumeAPIEndpointContainers string = "containers"
	storagePoolVolumeAPIEndpointImages     string = "images"
	storagePoolVolumeAPIEndpointCustom     string = "custom"
)

var supportedVolumeTypes = []int{storagePoolVolumeTypeContainer, storagePoolVolumeTypeImage, storagePoolVolumeTypeCustom}

func storagePoolVolumeTypeNameToType(volumeTypeName string) (int, error) {
	switch volumeTypeName {
	case storagePoolVolumeTypeNameContainer:
		return storagePoolVolumeTypeContainer, nil
	case storagePoolVolumeTypeNameImage:
		return storagePoolVolumeTypeImage, nil
	case storagePoolVolumeTypeNameCustom:
		return storagePoolVolumeTypeCustom, nil
	}

	return -1, fmt.Errorf("invalid storage volume type name")
}

func storagePoolVolumeTypeNameToAPIEndpoint(volumeTypeName string) (string, error) {
	switch volumeTypeName {
	case storagePoolVolumeTypeNameContainer:
		return storagePoolVolumeAPIEndpointContainers, nil
	case storagePoolVolumeTypeNameImage:
		return storagePoolVolumeAPIEndpointImages, nil
	case storagePoolVolumeTypeNameCustom:
		return storagePoolVolumeAPIEndpointCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type name")
}

func storagePoolVolumeTypeToName(volumeType int) (string, error) {
	switch volumeType {
	case storagePoolVolumeTypeContainer:
		return storagePoolVolumeTypeNameContainer, nil
	case storagePoolVolumeTypeImage:
		return storagePoolVolumeTypeNameImage, nil
	case storagePoolVolumeTypeCustom:
		return storagePoolVolumeTypeNameCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type")
}

func storagePoolVolumeTypeToAPIEndpoint(volumeType int) (string, error) {
	switch volumeType {
	case storagePoolVolumeTypeContainer:
		return storagePoolVolumeAPIEndpointContainers, nil
	case storagePoolVolumeTypeImage:
		return storagePoolVolumeAPIEndpointImages, nil
	case storagePoolVolumeTypeCustom:
		return storagePoolVolumeAPIEndpointCustom, nil
	}

	return "", fmt.Errorf("invalid storage volume type")
}

func storagePoolVolumeUpdate(d *Daemon, poolName string, volumeName string, volumeType int, newDescription string, newConfig map[string]string) error {
	s, err := storagePoolVolumeInit(d, poolName, volumeName, volumeType)
	if err != nil {
		return err
	}

	oldWritable := s.GetStoragePoolVolumeWritable()
	newWritable := oldWritable

	// Backup the current state
	oldDescription := oldWritable.Description
	oldConfig := map[string]string{}
	err = shared.DeepCopy(&oldWritable.Config, &oldConfig)
	if err != nil {
		return err
	}

	// Define a function which reverts everything.  Defer this function
	// so that it doesn't need to be explicitly called in every failing
	// return path. Track whether or not we want to undo the changes
	// using a closure.
	undoChanges := true
	defer func() {
		if undoChanges {
			s.SetStoragePoolVolumeWritable(&oldWritable)
		}
	}()

	// Diff the configurations
	changedConfig := []string{}
	userOnly := true
	for key := range oldConfig {
		if oldConfig[key] != newConfig[key] {
			if !strings.HasPrefix(key, "user.") {
				userOnly = false
			}

			if !shared.StringInSlice(key, changedConfig) {
				changedConfig = append(changedConfig, key)
			}
		}
	}

	for key := range newConfig {
		if oldConfig[key] != newConfig[key] {
			if !strings.HasPrefix(key, "user.") {
				userOnly = false
			}

			if !shared.StringInSlice(key, changedConfig) {
				changedConfig = append(changedConfig, key)
			}
		}
	}

	// Apply config changes if there are any
	if len(changedConfig) != 0 {

		// Update the storage pool
		if !userOnly {
			err = s.StoragePoolVolumeUpdate(changedConfig)
			if err != nil {
				return err
			}
		}

		newWritable.Config = newConfig

		// Apply the new configuration
		s.SetStoragePoolVolumeWritable(&newWritable)
	}

	poolID, err := dbStoragePoolGetID(d.db, poolName)
	if err != nil {
		return err
	}

	// Update the database if something changed
	if len(changedConfig) != 0 || newDescription != oldDescription {
		err = dbStoragePoolVolumeUpdate(d.db, volumeName, volumeType, poolID, newDescription, newConfig)
		if err != nil {
			return err
		}
	}

	// Success, update the closure to mark that the changes should be kept.
	undoChanges = false

	return nil
}

func storagePoolVolumeUsedByGet(d *Daemon, volumeName string, volumeTypeName string) ([]string, error) {
	// Handle container volumes
	if volumeTypeName == "container" {
		cName, sName, snap := containerGetParentAndSnapshotName(volumeName)

		if snap {
			return []string{fmt.Sprintf("/%s/containers/%s/snapshots/%s", version.APIVersion, cName, sName)}, nil
		}

		return []string{fmt.Sprintf("/%s/containers/%s", version.APIVersion, cName)}, nil
	}

	// Handle image volumes
	if volumeTypeName == "image" {
		return []string{fmt.Sprintf("/%s/images/%s", version.APIVersion, volumeName)}, nil
	}

	// Look for containers using the interface
	cts, err := dbContainersList(d.db, cTypeRegular)
	if err != nil {
		return []string{}, err
	}

	volumeUsedBy := []string{}
	volumeNameWithType := fmt.Sprintf("%s/%s", volumeTypeName, volumeName)
	for _, ct := range cts {
		c, err := containerLoadByName(d, ct)
		if err != nil {
			continue
		}

		for _, d := range c.LocalDevices() {
			if d["type"] != "disk" {
				continue
			}

			// Make sure that we don't compare against stuff like
			// "container////bla" but only against "container/bla".
			cleanSource := filepath.Clean(d["source"])
			if cleanSource == volumeName || cleanSource == volumeNameWithType {
				volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/containers/%s", version.APIVersion, ct))
			}
		}
	}

	profiles, err := profilesUsingPoolVolumeGetNames(d.db, volumeName, volumeTypeName)
	if err != nil {
		return []string{}, err
	}

	if len(volumeUsedBy) == 0 && len(profiles) == 0 {
		return []string{}, err
	}

	for _, pName := range profiles {
		volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/profiles/%s", version.APIVersion, pName))
	}

	return volumeUsedBy, nil
}

func profilesUsingPoolVolumeGetNames(db *sql.DB, volumeName string, volumeType string) ([]string, error) {
	usedBy := []string{}

	profiles, err := dbProfiles(db)
	if err != nil {
		return usedBy, err
	}

	for _, pName := range profiles {
		_, profile, err := dbProfileGet(db, pName)
		if err != nil {
			return usedBy, err
		}

		volumeNameWithType := fmt.Sprintf("%s/%s", volumeType, volumeName)
		for _, v := range profile.Devices {
			if v["type"] != "disk" {
				continue
			}

			// Can't be a storage volume.
			if filepath.IsAbs(v["source"]) {
				continue
			}

			// Make sure that we don't compare against stuff
			// like "container////bla" but only against
			// "container/bla".
			cleanSource := filepath.Clean(v["source"])
			if cleanSource == volumeName || cleanSource == volumeNameWithType {
				usedBy = append(usedBy, pName)
			}
		}
	}

	return usedBy, nil
}

func storagePoolVolumeDBCreate(d *Daemon, poolName string, volumeName, volumeDescription string, volumeTypeName string, volumeConfig map[string]string) error {
	// Check that the name of the new storage volume is valid. (For example.
	// zfs pools cannot contain "/" in their names.)
	err := storageValidName(volumeName)
	if err != nil {
		return err
	}

	// Convert the volume type name to our internal integer representation.
	volumeType, err := storagePoolVolumeTypeNameToType(volumeTypeName)
	if err != nil {
		return err
	}

	// We currently only allow to create storage volumes of type
	// storagePoolVolumeTypeCustom. So check, that nothing else was
	// requested.
	if volumeType != storagePoolVolumeTypeCustom {
		return fmt.Errorf("currently not allowed to create storage volumes of type %s", volumeTypeName)
	}

	// Load storage pool the volume will be attached to.
	poolID, poolStruct, err := dbStoragePoolGet(d.db, poolName)
	if err != nil {
		return err
	}

	// Check that a storage volume of the same storage volume type does not
	// already exist.
	volumeID, _ := dbStoragePoolVolumeGetTypeID(d.db, volumeName, volumeType, poolID)
	if volumeID > 0 {
		return fmt.Errorf("a storage volume of type %s does already exist", volumeTypeName)
	}

	// Make sure that we don't pass a nil to the next function.
	if volumeConfig == nil {
		volumeConfig = map[string]string{}
	}

	// Validate the requested storage volume configuration.
	err = storageVolumeValidateConfig(poolName, volumeConfig, poolStruct)
	if err != nil {
		return err
	}

	err = storageVolumeFillDefault(poolName, volumeConfig, poolStruct)
	if err != nil {
		return err
	}

	// Create the database entry for the storage volume.
	_, err = dbStoragePoolVolumeCreate(d.db, volumeName, volumeDescription, volumeType, poolID, volumeConfig)
	if err != nil {
		return fmt.Errorf("Error inserting %s of type %s into database: %s", poolName, volumeTypeName, err)
	}

	return nil
}

func storagePoolVolumeCreateInternal(d *Daemon, poolName string, volumeName, volumeDescription string, volumeTypeName string, volumeConfig map[string]string) error {
	err := storagePoolVolumeDBCreate(d, poolName, volumeName, volumeDescription, volumeTypeName, volumeConfig)
	if err != nil {
		return err
	}

	// Convert the volume type name to our internal integer representation.
	volumeType, err := storagePoolVolumeTypeNameToType(volumeTypeName)
	if err != nil {
		return err
	}

	s, err := storagePoolVolumeInit(d, poolName, volumeName, volumeType)
	if err != nil {
		return err
	}

	poolID, _ := s.GetContainerPoolInfo()

	// Create storage volume.
	err = s.StoragePoolVolumeCreate()
	if err != nil {
		dbStoragePoolVolumeDelete(d.db, volumeName, volumeType, poolID)
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package crypto

import (
	"bytes"
	"compress/gzip"
	"crypto/rand"
	"testing"
)

// CONTRIBUTE: Additional tests could be used, such as testing that decryption
// fails if the wrong iv's are used, and overall trying to probe the library
// for something that doesn't work quite right.

// TestEncryption makes sure that things can be encrypted and decrypted.
func TestEncryption(t *testing.T) {
	// Get a key for encryption.
	key, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}

	// Encrypt the zero plaintext.
	plaintext := make([]byte, 128)
	_, err = rand.Read(plaintext)
	if err != nil {
		t.Fatal(err)
	}
	ciphertext, iv, padding, err := EncryptBytes(key, plaintext)
	if err != nil {
		t.Fatal(err)
	}

	// Get the decrypted plaintext.
	decryptedPlaintext, err := DecryptBytes(key, ciphertext, iv, padding)
	if err != nil {
		t.Fatal(err)
	}

	// Compare the original to the decrypted.
	if bytes.Compare(plaintext, decryptedPlaintext) != 0 {
		t.Fatal("Encrypted and decrypted zero plaintext do not match")
	}

	// Try to decrypt using a different key
	key2, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}
	badtext, err := DecryptBytes(key2, ciphertext, iv, padding)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(plaintext, badtext) == 0 {
		t.Fatal("When using the wrong key, plaintext was still decrypted!")
	}
}

// TestPadding encrypts and decrypts a byte slice that invokes every possible
// padding length.
func TestPadding(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}

	// Encrypt and decrypt for all of the potential padded values and see that
	// padding is handled correctly.
	for i := 256; i < 256+BlockSize; i++ {
		key, err := GenerateEncryptionKey()
		if err != nil {
			t.Fatal(err)
		}
		plaintext := make([]byte, i)
		rand.Read(plaintext)
		ciphertext, iv, padding, err := EncryptBytes(key, plaintext)
		if err != nil {
			t.Fatal(err)
		}
		decryptedPlaintext, err := DecryptBytes(key, ciphertext, iv, padding)
		if err != nil {
			t.Fatal(err)
		}
		if bytes.Compare(plaintext, decryptedPlaintext) != 0 {
			t.Fatal("Encrypted and decrypted zero plaintext do not match for i = ", i)
		}
	}
}

// TestEntropy encrypts and then decrypts a zero plaintext, checking that the
// ciphertext is high entropy. This is simply to check for obvious mistakes and
// not to guarantee security of the ciphertext.
func TestEntropy(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}

	// Encrypt a larger zero plaintext and make sure that the outcome is high
	// entropy. We measure entropy by seeing how much gzip can compress the
	// ciphertext. 10 * 1000 bytes was chosen because gzip overhead will exceed
	// compression rate for smaller files, even low entropy files.
	cipherSize := 10 * 1000
	key, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}
	plaintext := make([]byte, cipherSize)
	ciphertext, _, _, err := EncryptBytes(key, plaintext)
	if err != nil {
		t.Fatal(err)
	}

	// Gzip the ciphertext
	var b bytes.Buffer
	zip := gzip.NewWriter(&b)
	zip.Write(ciphertext)
	zip.Close()
	if b.Len() < cipherSize {
		t.Error("supposedly high entropy ciphertext has been compressed!")
	}
}
<commit_msg>slight expansion to crypto testing<commit_after>package crypto

import (
	"bytes"
	"compress/gzip"
	"crypto/rand"
	"testing"
)

// TestEncryption makes sure that things can be encrypted and decrypted.
func TestEncryption(t *testing.T) {
	// Get a key for encryption.
	key, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}

	// Encrypt the zero plaintext.
	plaintext := make([]byte, 128)
	_, err = rand.Read(plaintext)
	if err != nil {
		t.Fatal(err)
	}
	ciphertext, iv, padding, err := EncryptBytes(key, plaintext)
	if err != nil {
		t.Fatal(err)
	}

	// Get the decrypted plaintext.
	decryptedPlaintext, err := DecryptBytes(key, ciphertext, iv, padding)
	if err != nil {
		t.Fatal(err)
	}

	// Compare the original to the decrypted.
	if bytes.Compare(plaintext, decryptedPlaintext) != 0 {
		t.Fatal("Encrypted and decrypted zero plaintext do not match")
	}

	// Try to decrypt using a different key
	key2, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}
	badtext, err := DecryptBytes(key2, ciphertext, iv, padding)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(plaintext, badtext) == 0 {
		t.Fatal("When using the wrong key, plaintext was still decrypted!")
	}

	// Try to decrypt using a different iv.
	badIV := iv
	badIV[0]++
	badtext, err = DecryptBytes(key, ciphertext, badIV, padding)
	if err != nil {
		t.Fatal(err)
	}
	if bytes.Compare(plaintext, badtext) == 0 {
		t.Fatal("When using the wrong key, plaintext was still decrypted!")
	}

	// Try to decrypt using incorrectly sized ivs, ciphertext, and padding.
	_, err = DecryptBytes(key, ciphertext, iv[1:], padding)
	if err == nil {
		t.Fatal("Was able to decrypt with a bad iv.")
	}
	_, err = DecryptBytes(key, ciphertext[1:], iv, padding)
	if err == nil {
		t.Fatal("Was able to decrypt with a bad ciphertext")
	}
	_, err = DecryptBytes(key, ciphertext, iv, 1+len(ciphertext))
	if err == nil {
		t.Fatal("Was able to decrypt using bad padding")
	}
	_, err = DecryptBytes(key, ciphertext, iv, -1)
	if err == nil {
		t.Fatal("Was able to decrypt using bad padding")
	}
}

// TestPadding encrypts and decrypts a byte slice that invokes every possible
// padding length.
func TestPadding(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}

	// Encrypt and decrypt for all of the potential padded values and see that
	// padding is handled correctly.
	for i := 256; i < 256+BlockSize; i++ {
		key, err := GenerateEncryptionKey()
		if err != nil {
			t.Fatal(err)
		}
		plaintext := make([]byte, i)
		rand.Read(plaintext)
		ciphertext, iv, padding, err := EncryptBytes(key, plaintext)
		if err != nil {
			t.Fatal(err)
		}
		decryptedPlaintext, err := DecryptBytes(key, ciphertext, iv, padding)
		if err != nil {
			t.Fatal(err)
		}
		if bytes.Compare(plaintext, decryptedPlaintext) != 0 {
			t.Fatal("Encrypted and decrypted zero plaintext do not match for i = ", i)
		}
	}
}

// TestEntropy encrypts and then decrypts a zero plaintext, checking that the
// ciphertext is high entropy. This is simply to check for obvious mistakes and
// not to guarantee security of the ciphertext.
func TestEntropy(t *testing.T) {
	if testing.Short() {
		t.Skip()
	}

	// Encrypt a larger zero plaintext and make sure that the outcome is high
	// entropy. We measure entropy by seeing how much gzip can compress the
	// ciphertext. 10 * 1000 bytes was chosen because gzip overhead will exceed
	// compression rate for smaller files, even low entropy files.
	cipherSize := 10 * 1000
	key, err := GenerateEncryptionKey()
	if err != nil {
		t.Fatal(err)
	}
	plaintext := make([]byte, cipherSize)
	ciphertext, _, _, err := EncryptBytes(key, plaintext)
	if err != nil {
		t.Fatal(err)
	}

	// Gzip the ciphertext
	var b bytes.Buffer
	zip := gzip.NewWriter(&b)
	zip.Write(ciphertext)
	zip.Close()
	if b.Len() < cipherSize {
		t.Error("supposedly high entropy ciphertext has been compressed!")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

const ucdFileName = "UnicodeData.txt"
const ucdBaseUrl = "http://www.unicode.org/Public/UCD/latest/ucd/"

func progressDisplay(running *bool) {
	for *running {
		fmt.Print(".")
		time.Sleep(150 * time.Millisecond)
	}
	fmt.Println()
}

func getUcdFile(fileName string) {
	url := ucdBaseUrl + ucdFileName
	fmt.Printf("%s not found\nretrieving from %s\n", ucdFileName, url)
	running := true
	go progressDisplay(&running)
	defer func() {
		running = false
	}()
	response, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	file, err := os.Create(fileName)
	if err != nil {
		panic(err)
	}
	_, err = io.Copy(file, response.Body)
	if err != nil {
		panic(err)
	}
	file.Close()
}

func buildIndex(fileName string) (map[string][]rune, map[rune]string) {
	if _, err := os.Stat(fileName); os.IsNotExist(err) {
		getUcdFile(fileName)
	}
	content, err := ioutil.ReadFile(fileName)
	if err != nil {
		panic(err)
	}

	lines := strings.Split(string(content), "\n")

	index := make(map[string][]rune)
	names := make(map[rune]string)

	for _, line := range lines {
		var uchar rune
		fields := strings.Split(line, ";")
		if len(fields) >= 2 {
			code64, _ := strconv.ParseInt(fields[0], 16, 0)
			uchar = rune(code64)
			names[uchar] = fields[1]
			for _, word := range strings.Split(fields[1], " ") {
				var entries []rune
				if len(index[word]) < 1 {
					entries = make([]rune, 0)
				} else {
					entries = index[word]
				}
				index[word] = append(entries, uchar)
			}
		}

	}
	return index, names
}

func main() {
	dir, _ := os.Getwd()
	path := path.Join(dir, ucdFileName)
	index, names := buildIndex(path)
	if len(os.Args) != 2 {
		fmt.Println("Usage:  runefinder <word>\texample: runefinder cat")
		os.Exit(1)
	}

	word := strings.ToUpper(os.Args[1])
	for _, uchar := range index[word] {
		fmt.Printf("U+%-5X %c \t%s\n", uchar, uchar, names[uchar])
	}

}
<commit_msg>improved output formatting. no HTTP fetch if no argument given<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

const ucdFileName = "UnicodeData.txt"
const ucdBaseUrl = "http://www.unicode.org/Public/UCD/latest/ucd/"

func progressDisplay(running *bool) {
	for *running {
		fmt.Print(".")
		time.Sleep(150 * time.Millisecond)
	}
	fmt.Println()
}

func getUcdFile(fileName string) {
	url := ucdBaseUrl + ucdFileName
	fmt.Printf("%s not found\nretrieving from %s\n", ucdFileName, url)
	running := true
	go progressDisplay(&running)
	defer func() {
		running = false
	}()
	response, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	file, err := os.Create(fileName)
	if err != nil {
		panic(err)
	}
	_, err = io.Copy(file, response.Body)
	if err != nil {
		panic(err)
	}
	file.Close()
}

func buildIndex(fileName string) (map[string][]rune, map[rune]string) {
	if _, err := os.Stat(fileName); os.IsNotExist(err) {
		getUcdFile(fileName)
	}
	content, err := ioutil.ReadFile(fileName)
	if err != nil {
		panic(err)
	}

	lines := strings.Split(string(content), "\n")

	index := make(map[string][]rune)
	names := make(map[rune]string)

	for _, line := range lines {
		var uchar rune
		fields := strings.Split(line, ";")
		if len(fields) >= 2 {
			code64, _ := strconv.ParseInt(fields[0], 16, 0)
			uchar = rune(code64)
			names[uchar] = fields[1]
			for _, word := range strings.Split(fields[1], " ") {
				var entries []rune
				if len(index[word]) < 1 {
					entries = make([]rune, 0)
				} else {
					entries = index[word]
				}
				index[word] = append(entries, uchar)
			}
		}

	}
	return index, names
}

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage:  runefinder <word>\texample: runefinder cat")
		os.Exit(1)
	}
	word := strings.ToUpper(os.Args[1])

	dir, _ := os.Getwd()
	path := path.Join(dir, ucdFileName)
	index, names := buildIndex(path)

	count := 0
	format := "U+%04X  %c \t%s\n"
	for _, uchar := range index[word] {
		if uchar > 0xFFFF {
			format = "U+%5X %c \t%s\n"
		}
		fmt.Printf(format, uchar, uchar, names[uchar])
		count++
	}
	fmt.Printf("%d characters found\n", count)

}
<|endoftext|>


<commit_before>package ring

import (
	"encoding/binary"
	"fmt"
	"log"
	"math"
	"net"
	"sync"
	"sync/atomic"
	"time"
)

const (
	_STATE_UNKNOWN = iota
	_STATE_CONNECTING
	_STATE_CONNECTED
	_STATE_DISCONNECTING
)

type ringConn struct {
	state      int32
	addr       string
	conn       net.Conn
	reader     *timeoutReader
	writerLock sync.Mutex
	writer     *timeoutWriter
}

type TCPMsgRing struct {
	lock sync.RWMutex
	// addressIndex is the index given to a Node's Address method to determine
	// the network address to connect to (see Node's Address method for more
	// information).
	addressIndex        int
	chunkSize           int
	connectionTimeout   time.Duration
	intraMessageTimeout time.Duration
	interMessageTimeout time.Duration
	ring                Ring
	msgHandlers         map[uint64]MsgUnmarshaller
	conns               map[string]*ringConn
}

func NewTCPMsgRing(r Ring) *TCPMsgRing {
	return &TCPMsgRing{
		ring:                r,
		msgHandlers:         make(map[uint64]MsgUnmarshaller),
		conns:               make(map[string]*ringConn),
		chunkSize:           16 * 1024,
		connectionTimeout:   60 * time.Second,
		intraMessageTimeout: 2 * time.Second,
		interMessageTimeout: 2 * time.Hour,
	}
}

func (m *TCPMsgRing) Ring() Ring {
	m.lock.RLock()
	r := m.ring
	m.lock.RUnlock()
	return r
}

func (m *TCPMsgRing) MaxMsgLength() uint64 {
	return math.MaxUint64
}

func (m *TCPMsgRing) SetMsgHandler(msgType uint64, handler MsgUnmarshaller) {
	m.lock.Lock()
	m.msgHandlers[uint64(msgType)] = handler
	m.lock.Unlock()
}

func (m *TCPMsgRing) MsgToNode(nodeID uint64, msg Msg) {
	for i := time.Second; i <= 4*time.Second; i *= 2 {
		node := m.Ring().Node(nodeID)
		if node != nil && m.msgToNode(msg, node) == nil {
			break
		}
		time.Sleep(i)
	}
	msg.Done()
}

func (m *TCPMsgRing) connection(addr string) *ringConn {
	m.lock.RLock()
	conn := m.conns[addr]
	m.lock.RUnlock()
	if conn == nil {
		m.lock.Lock()
		conn = m.conns[addr]
		if conn == nil {
			conn = &ringConn{
				state: _STATE_CONNECTING,
				addr:  addr,
			}
			m.conns[addr] = conn
			m.lock.Unlock()
			go func() {
				tcpconn, err := net.DialTimeout("tcp", addr, m.connectionTimeout)
				if err != nil {
					m.lock.Lock()
					delete(m.conns, addr)
					m.lock.Unlock()
					// TODO: log error
					return
				}
				conn.conn = tcpconn
				conn.reader = newTimeoutReader(tcpconn, m.chunkSize, m.intraMessageTimeout)
				conn.writer = newTimeoutWriter(tcpconn, m.chunkSize, m.intraMessageTimeout)
				err = m.handshake(conn)
				if err != nil {
					m.lock.Lock()
					delete(m.conns, addr)
					m.lock.Unlock()
					// TODO: log error
					return
				}
				go m.handleForever(conn)
			}()
		} else {
			m.lock.Unlock()
		}
	}
	if atomic.LoadInt32(&conn.state) != _STATE_CONNECTED {
		return nil
	}
	return conn
}

func (m *TCPMsgRing) disconnection(addr string) {
	m.lock.Lock()
	conn := m.conns[addr]
	delete(m.conns, addr)
	m.lock.Unlock()
	if conn != nil {
		if conn.conn != nil {
			err := conn.conn.Close()
			if err != nil {
				log.Println("tcp msg ring disconnection close err:", err)
			}
		}

	}
}

func (m *TCPMsgRing) handshake(conn *ringConn) error {
	// TODO: trade version numbers and local ids
	atomic.StoreInt32(&conn.state, _STATE_CONNECTED)
	return nil
}

func (m *TCPMsgRing) msgToNode(msg Msg, node Node) error {
	conn := m.connection(node.Address(m.addressIndex))
	if conn == nil {
		return fmt.Errorf("no connection")
	}
	conn.writerLock.Lock()
	disconnect := func(err error) error {
		log.Println("msgToNode error:", err)
		m.disconnection(node.Address(m.addressIndex))
		conn.writerLock.Unlock()
		return err
	}
	b := make([]byte, 8)
	binary.BigEndian.PutUint64(b, msg.MsgType())
	_, err := conn.writer.Write(b)
	if err != nil {
		return disconnect(err)
	}
	binary.BigEndian.PutUint64(b, msg.MsgLength())
	_, err = conn.writer.Write(b)
	if err != nil {
		return disconnect(err)
	}
	length, err := msg.WriteContent(conn.writer)
	if err != nil {
		return disconnect(err)
	}
	err = conn.writer.Flush()
	if err != nil {
		return disconnect(err)
	}
	if length != msg.MsgLength() {
		return disconnect(fmt.Errorf("incorrect message length sent: %d != %d", length, msg.MsgLength()))
	}
	conn.writerLock.Unlock()
	return nil
}

func (m *TCPMsgRing) msgToNodeChan(msg Msg, node Node, retchan chan struct{}) {
	m.msgToNode(msg, node)
	retchan <- struct{}{}
}

func (m *TCPMsgRing) MsgToOtherReplicas(ringVersion int64, partition uint32, msg Msg) {
	r := m.Ring()
	if ringVersion != r.Version() {
		msg.Done()
		return
	}
	nodes := r.ResponsibleNodes(partition)
	retchan := make(chan struct{}, len(nodes))
	localNode := r.LocalNode()
	var localID uint64
	if localNode != nil {
		localID = localNode.ID()
	}
	sent := 0
	for _, node := range nodes {
		if node.ID() != localID {
			go m.msgToNodeChan(msg, node, retchan)
			sent++
		}
	}
	for ; sent > 0; sent-- {
		<-retchan
	}
	msg.Done()
}

func (m *TCPMsgRing) handleOne(conn *ringConn) error {
	var msgType uint64
	conn.reader.Timeout = m.interMessageTimeout
	b, err := conn.reader.ReadByte()
	conn.reader.Timeout = m.intraMessageTimeout
	if err != nil {
		return err
	}
	msgType = uint64(b)
	for i := 1; i < 8; i++ {
		b, err = conn.reader.ReadByte()
		if err != nil {
			return err
		}
		msgType <<= 8
		msgType |= uint64(b)
	}
	handler := m.msgHandlers[msgType]
	if handler == nil {
		return fmt.Errorf("no handler for MsgType %x", msgType)
	}
	var length uint64
	for i := 0; i < 8; i++ {
		b, err = conn.reader.ReadByte()
		if err != nil {
			return err
		}
		length <<= 8
		length |= uint64(b)
	}
	consumed, err := handler(conn.reader, length)
	if consumed != length {
		if err == nil {
			err = fmt.Errorf("did not read %d bytes; only read %d", length, consumed)
		}
	}
	if err != nil {
		return err
	}
	return nil
}

func (m *TCPMsgRing) handleForever(conn *ringConn) {
	for {
		if err := m.handleOne(conn); err != nil {
			log.Println("handleForever error:", err)
			m.disconnection(conn.addr)
			break
		}
	}
}

func (m *TCPMsgRing) Listen() error {
	node := m.ring.LocalNode()
	tcpAddr, err := net.ResolveTCPAddr("tcp", node.Address(m.addressIndex))
	if err != nil {
		return err
	}
	server, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return err
	}
	for {
		tcpconn, err := server.AcceptTCP()
		if err != nil {
			log.Println("Listen/AcceptTCP error:", err)
			server.Close()
			return err
		}
		addr := tcpconn.RemoteAddr().String()
		conn := &ringConn{
			state:  _STATE_CONNECTING,
			addr:   addr,
			conn:   tcpconn,
			reader: newTimeoutReader(tcpconn, m.chunkSize, m.intraMessageTimeout),
			writer: newTimeoutWriter(tcpconn, m.chunkSize, m.intraMessageTimeout),
		}
		m.lock.Lock()
		c := m.conns[addr]
		if c != nil {
			c.conn.Close()
		}
		m.conns[addr] = conn
		m.lock.Unlock()
		go func() {
			m.handshake(conn)
			go m.handleForever(conn)
		}()
	}
}
<commit_msg>Add RingSet()<commit_after>package ring

import (
	"encoding/binary"
	"fmt"
	"log"
	"math"
	"net"
	"sync"
	"sync/atomic"
	"time"
)

const (
	_STATE_UNKNOWN = iota
	_STATE_CONNECTING
	_STATE_CONNECTED
	_STATE_DISCONNECTING
)

type ringConn struct {
	state      int32
	addr       string
	conn       net.Conn
	reader     *timeoutReader
	writerLock sync.Mutex
	writer     *timeoutWriter
}

type TCPMsgRing struct {
	lock sync.RWMutex
	// addressIndex is the index given to a Node's Address method to determine
	// the network address to connect to (see Node's Address method for more
	// information).
	addressIndex        int
	chunkSize           int
	connectionTimeout   time.Duration
	intraMessageTimeout time.Duration
	interMessageTimeout time.Duration
	ring                Ring
	msgHandlers         map[uint64]MsgUnmarshaller
	conns               map[string]*ringConn
}

func NewTCPMsgRing(r Ring) *TCPMsgRing {
	return &TCPMsgRing{
		ring:                r,
		msgHandlers:         make(map[uint64]MsgUnmarshaller),
		conns:               make(map[string]*ringConn),
		chunkSize:           16 * 1024,
		connectionTimeout:   60 * time.Second,
		intraMessageTimeout: 2 * time.Second,
		interMessageTimeout: 2 * time.Hour,
	}
}

func (m *TCPMsgRing) Ring() Ring {
	m.lock.RLock()
	r := m.ring
	m.lock.RUnlock()
	return r
}

func (m *TCPMsgRing) RingSet(ring Ring) Ring {
	m.lock.Lock()
	m.ring = ring
	m.lock.Unlock()
	return r
}

func (m *TCPMsgRing) MaxMsgLength() uint64 {
	return math.MaxUint64
}

func (m *TCPMsgRing) SetMsgHandler(msgType uint64, handler MsgUnmarshaller) {
	m.lock.Lock()
	m.msgHandlers[uint64(msgType)] = handler
	m.lock.Unlock()
}

func (m *TCPMsgRing) MsgToNode(nodeID uint64, msg Msg) {
	for i := time.Second; i <= 4*time.Second; i *= 2 {
		node := m.Ring().Node(nodeID)
		if node != nil && m.msgToNode(msg, node) == nil {
			break
		}
		time.Sleep(i)
	}
	msg.Done()
}

func (m *TCPMsgRing) connection(addr string) *ringConn {
	m.lock.RLock()
	conn := m.conns[addr]
	m.lock.RUnlock()
	if conn == nil {
		m.lock.Lock()
		conn = m.conns[addr]
		if conn == nil {
			conn = &ringConn{
				state: _STATE_CONNECTING,
				addr:  addr,
			}
			m.conns[addr] = conn
			m.lock.Unlock()
			go func() {
				tcpconn, err := net.DialTimeout("tcp", addr, m.connectionTimeout)
				if err != nil {
					m.lock.Lock()
					delete(m.conns, addr)
					m.lock.Unlock()
					// TODO: log error
					return
				}
				conn.conn = tcpconn
				conn.reader = newTimeoutReader(tcpconn, m.chunkSize, m.intraMessageTimeout)
				conn.writer = newTimeoutWriter(tcpconn, m.chunkSize, m.intraMessageTimeout)
				err = m.handshake(conn)
				if err != nil {
					m.lock.Lock()
					delete(m.conns, addr)
					m.lock.Unlock()
					// TODO: log error
					return
				}
				go m.handleForever(conn)
			}()
		} else {
			m.lock.Unlock()
		}
	}
	if atomic.LoadInt32(&conn.state) != _STATE_CONNECTED {
		return nil
	}
	return conn
}

func (m *TCPMsgRing) disconnection(addr string) {
	m.lock.Lock()
	conn := m.conns[addr]
	delete(m.conns, addr)
	m.lock.Unlock()
	if conn != nil {
		if conn.conn != nil {
			err := conn.conn.Close()
			if err != nil {
				log.Println("tcp msg ring disconnection close err:", err)
			}
		}

	}
}

func (m *TCPMsgRing) handshake(conn *ringConn) error {
	// TODO: trade version numbers and local ids
	atomic.StoreInt32(&conn.state, _STATE_CONNECTED)
	return nil
}

func (m *TCPMsgRing) msgToNode(msg Msg, node Node) error {
	conn := m.connection(node.Address(m.addressIndex))
	if conn == nil {
		return fmt.Errorf("no connection")
	}
	conn.writerLock.Lock()
	disconnect := func(err error) error {
		log.Println("msgToNode error:", err)
		m.disconnection(node.Address(m.addressIndex))
		conn.writerLock.Unlock()
		return err
	}
	b := make([]byte, 8)
	binary.BigEndian.PutUint64(b, msg.MsgType())
	_, err := conn.writer.Write(b)
	if err != nil {
		return disconnect(err)
	}
	binary.BigEndian.PutUint64(b, msg.MsgLength())
	_, err = conn.writer.Write(b)
	if err != nil {
		return disconnect(err)
	}
	length, err := msg.WriteContent(conn.writer)
	if err != nil {
		return disconnect(err)
	}
	err = conn.writer.Flush()
	if err != nil {
		return disconnect(err)
	}
	if length != msg.MsgLength() {
		return disconnect(fmt.Errorf("incorrect message length sent: %d != %d", length, msg.MsgLength()))
	}
	conn.writerLock.Unlock()
	return nil
}

func (m *TCPMsgRing) msgToNodeChan(msg Msg, node Node, retchan chan struct{}) {
	m.msgToNode(msg, node)
	retchan <- struct{}{}
}

func (m *TCPMsgRing) MsgToOtherReplicas(ringVersion int64, partition uint32, msg Msg) {
	r := m.Ring()
	if ringVersion != r.Version() {
		msg.Done()
		return
	}
	nodes := r.ResponsibleNodes(partition)
	retchan := make(chan struct{}, len(nodes))
	localNode := r.LocalNode()
	var localID uint64
	if localNode != nil {
		localID = localNode.ID()
	}
	sent := 0
	for _, node := range nodes {
		if node.ID() != localID {
			go m.msgToNodeChan(msg, node, retchan)
			sent++
		}
	}
	for ; sent > 0; sent-- {
		<-retchan
	}
	msg.Done()
}

func (m *TCPMsgRing) handleOne(conn *ringConn) error {
	var msgType uint64
	conn.reader.Timeout = m.interMessageTimeout
	b, err := conn.reader.ReadByte()
	conn.reader.Timeout = m.intraMessageTimeout
	if err != nil {
		return err
	}
	msgType = uint64(b)
	for i := 1; i < 8; i++ {
		b, err = conn.reader.ReadByte()
		if err != nil {
			return err
		}
		msgType <<= 8
		msgType |= uint64(b)
	}
	handler := m.msgHandlers[msgType]
	if handler == nil {
		return fmt.Errorf("no handler for MsgType %x", msgType)
	}
	var length uint64
	for i := 0; i < 8; i++ {
		b, err = conn.reader.ReadByte()
		if err != nil {
			return err
		}
		length <<= 8
		length |= uint64(b)
	}
	consumed, err := handler(conn.reader, length)
	if consumed != length {
		if err == nil {
			err = fmt.Errorf("did not read %d bytes; only read %d", length, consumed)
		}
	}
	if err != nil {
		return err
	}
	return nil
}

func (m *TCPMsgRing) handleForever(conn *ringConn) {
	for {
		if err := m.handleOne(conn); err != nil {
			log.Println("handleForever error:", err)
			m.disconnection(conn.addr)
			break
		}
	}
}

func (m *TCPMsgRing) Listen() error {
	node := m.Ring().LocalNode()
	tcpAddr, err := net.ResolveTCPAddr("tcp", node.Address(m.addressIndex))
	if err != nil {
		return err
	}
	server, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return err
	}
	for {
		tcpconn, err := server.AcceptTCP()
		if err != nil {
			log.Println("Listen/AcceptTCP error:", err)
			server.Close()
			return err
		}
		addr := tcpconn.RemoteAddr().String()
		conn := &ringConn{
			state:  _STATE_CONNECTING,
			addr:   addr,
			conn:   tcpconn,
			reader: newTimeoutReader(tcpconn, m.chunkSize, m.intraMessageTimeout),
			writer: newTimeoutWriter(tcpconn, m.chunkSize, m.intraMessageTimeout),
		}
		m.lock.Lock()
		c := m.conns[addr]
		if c != nil {
			c.conn.Close()
		}
		m.conns[addr] = conn
		m.lock.Unlock()
		go func() {
			m.handshake(conn)
			go m.handleForever(conn)
		}()
	}
}
<|endoftext|>


<commit_before>package serializer

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"math/big"
	"strings"
)

// SecureSerializer holds EncryptKey and ValidateKey
type SecureSerializer struct {
	EncryptKey  []byte
	ValidateKey []byte
}

func md5sum(d []byte) []byte {
	h := md5.New()
	h.Write(d)
	return h.Sum(nil)
}

func evpBytesToKey(password string, keyLen int) (key []byte) {
	const md5Len = 16

	cnt := (keyLen-1)/md5Len + 1
	m := make([]byte, cnt*md5Len)
	copy(m, md5sum([]byte(password)))

	// Repeatedly call md5 until bytes generated is enough.
	// Each call to md5 uses data: prev md5 sum + password.
	d := make([]byte, md5Len+len(password))
	start := 0
	for i := 1; i < cnt; i++ {
		start += md5Len
		copy(d, m[start-md5Len:start])
		copy(d[md5Len:], password)
		copy(m[start:], md5sum(d))
	}
	return m[:keyLen]
}

func randString(n int) []byte {
	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	symbols := big.NewInt(int64(len(alphanum)))
	states := big.NewInt(0)
	states.Exp(symbols, big.NewInt(int64(n)), nil)
	r, err := rand.Int(rand.Reader, states)
	if err != nil {
		panic(err)
	}
	var bytes = make([]byte, n)
	r2 := big.NewInt(0)
	symbol := big.NewInt(0)
	for i := range bytes {
		r2.DivMod(r, symbols, symbol)
		r, r2 = r2, r
		bytes[i] = alphanum[symbol.Int64()]
	}
	return bytes
}

func sign(data, key []byte) []byte {
	mac := hmac.New(sha1.New, key)
	mac.Write(data)
	return mac.Sum(nil)
}

func pKCS5Padding(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(src, padtext...)
}

func pKCS5UnPadding(src []byte) []byte {
	length := len(src)
	unpadding := int(src[length-1])
	return src[:(length - unpadding)]
}

// Stringify serializes and encrypts interface{} given as argument and returns encrypted data as a string or an possible error
func (serializer *SecureSerializer) Stringify(obj interface{}) (string, error) {
	jsonData, err := json.Marshal(obj)

	if err != nil {
		return "", err
	}

	nonceCheck := randString(8)
	if err != nil {
		return "", err
	}

	nonceCrypt := randString(8)
	if err != nil {
		return "", err
	}

	password := append(serializer.EncryptKey, nonceCrypt[:]...)
	key := evpBytesToKey(string(password), 48)

	block, err := aes.NewCipher(key[:32])
	if err != nil {
		return "", err
	}

	iv := key[32:]

	encrypter := cipher.NewCBCEncrypter(block, iv)

	dataToEncrypt := pKCS5Padding(append(nonceCheck, jsonData[:]...), aes.BlockSize)

	encrypted := make([]byte, len(dataToEncrypt))

	encrypter.CryptBlocks(encrypted, dataToEncrypt)

	digest := sign(jsonData, append(serializer.ValidateKey, nonceCheck[:]...))

	digestBase64 := base64.StdEncoding.EncodeToString(digest)
	digestBase64 = strings.Replace(digestBase64, "+", "-", -1)
	digestBase64 = strings.Replace(digestBase64, "/", "_", -1)

	return fmt.Sprint(
		digestBase64,
		string(nonceCrypt),
		hex.EncodeToString(encrypted)), nil
}

// Parse deserializes and decrypts encrypted data (returned by Stringify) to a pointer
func (serializer *SecureSerializer) Parse(base64data string, obj interface{}) error {
	expectedDigest := base64data[0:28]
	nonceCrypt := base64data[28:36]
	encryptedDataHex := base64data[36:]

	password := append(serializer.EncryptKey, nonceCrypt[:]...)
	key := evpBytesToKey(string(password), 48)

	block, err := aes.NewCipher(key[:32])
	if err != nil {
		return err
	}

	iv := key[32:]

	decrypter := cipher.NewCBCDecrypter(block, iv)

	encryptedData, err := hex.DecodeString(encryptedDataHex)
	if err != nil {
		return err
	}

	decrypter.CryptBlocks(encryptedData, encryptedData)

	encryptedData = pKCS5UnPadding(encryptedData)

	nonceCheck := encryptedData[:8]

	digest := sign(encryptedData[8:], append(serializer.ValidateKey, nonceCheck[:]...))
	digestBase64 := base64.StdEncoding.EncodeToString(digest)
	digestBase64 = strings.Replace(digestBase64, "+", "-", -1)
	digestBase64 = strings.Replace(digestBase64, "/", "_", -1)

	if !strings.EqualFold(digestBase64, expectedDigest) {
		return errors.New("Bad digest")
	}

	return json.Unmarshal(encryptedData[8:], obj)
}

// NewSecureSerializer creates new serializer instance with encrypt key and validate key
func NewSecureSerializer(encryptKey []byte, validateKey []byte) *SecureSerializer {
	serializer := &SecureSerializer{encryptKey, validateKey}
	return serializer
}

// SecureStringify is a shorthand for serializer := NewSecureSerializer(...) encryptedData := serializer.Stringify(...)
func SecureStringify(obj interface{}, encryptKey []byte, validateKey []byte) (string, error) {
	serializer := NewSecureSerializer(encryptKey, validateKey)
	return serializer.Stringify(obj)
}

// SecureParse is a shorthand for serializer := NewSecureSerializer(...) serializer.Parse(...)
func SecureParse(data string, obj interface{}, encryptKey []byte, validateKey []byte) error {
	serializer := NewSecureSerializer(encryptKey, validateKey)
	return serializer.Parse(data, obj)
}
<commit_msg>Rename variable<commit_after>package serializer

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"math/big"
	"strings"
)

// SecureSerializer holds EncryptKey and ValidateKey
type SecureSerializer struct {
	EncryptKey  []byte
	ValidateKey []byte
}

func md5sum(d []byte) []byte {
	h := md5.New()
	h.Write(d)
	return h.Sum(nil)
}

func evpBytesToKey(password string, keyLen int) (key []byte) {
	const md5Len = 16

	cnt := (keyLen-1)/md5Len + 1
	m := make([]byte, cnt*md5Len)
	copy(m, md5sum([]byte(password)))

	// Repeatedly call md5 until bytes generated is enough.
	// Each call to md5 uses data: prev md5 sum + password.
	d := make([]byte, md5Len+len(password))
	start := 0
	for i := 1; i < cnt; i++ {
		start += md5Len
		copy(d, m[start-md5Len:start])
		copy(d[md5Len:], password)
		copy(m[start:], md5sum(d))
	}
	return m[:keyLen]
}

func randString(n int) []byte {
	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	symbols := big.NewInt(int64(len(alphanum)))
	states := big.NewInt(0)
	states.Exp(symbols, big.NewInt(int64(n)), nil)
	r, err := rand.Int(rand.Reader, states)
	if err != nil {
		panic(err)
	}
	var bytes = make([]byte, n)
	r2 := big.NewInt(0)
	symbol := big.NewInt(0)
	for i := range bytes {
		r2.DivMod(r, symbols, symbol)
		r, r2 = r2, r
		bytes[i] = alphanum[symbol.Int64()]
	}
	return bytes
}

func sign(data, key []byte) []byte {
	mac := hmac.New(sha1.New, key)
	mac.Write(data)
	return mac.Sum(nil)
}

func pKCS5Padding(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(src, padtext...)
}

func pKCS5UnPadding(src []byte) []byte {
	length := len(src)
	unpadding := int(src[length-1])
	return src[:(length - unpadding)]
}

// Stringify serializes and encrypts interface{} given as argument and returns encrypted data as a string or an possible error
func (serializer *SecureSerializer) Stringify(obj interface{}) (string, error) {
	jsonData, err := json.Marshal(obj)

	if err != nil {
		return "", err
	}

	nonceCheck := randString(8)
	if err != nil {
		return "", err
	}

	nonceCrypt := randString(8)
	if err != nil {
		return "", err
	}

	password := append(serializer.EncryptKey, nonceCrypt[:]...)
	key := evpBytesToKey(string(password), 48)

	block, err := aes.NewCipher(key[:32])
	if err != nil {
		return "", err
	}

	iv := key[32:]

	encrypter := cipher.NewCBCEncrypter(block, iv)

	dataToEncrypt := pKCS5Padding(append(nonceCheck, jsonData[:]...), aes.BlockSize)

	encrypted := make([]byte, len(dataToEncrypt))

	encrypter.CryptBlocks(encrypted, dataToEncrypt)

	digest := sign(jsonData, append(serializer.ValidateKey, nonceCheck[:]...))

	digestBase64 := base64.StdEncoding.EncodeToString(digest)
	digestBase64 = strings.Replace(digestBase64, "+", "-", -1)
	digestBase64 = strings.Replace(digestBase64, "/", "_", -1)

	return fmt.Sprint(
		digestBase64,
		string(nonceCrypt),
		hex.EncodeToString(encrypted)), nil
}

// Parse deserializes and decrypts encrypted data (returned by Stringify) to a pointer
func (serializer *SecureSerializer) Parse(serializedData string, obj interface{}) error {
	expectedDigest := serializedData[0:28]
	nonceCrypt := serializedData[28:36]
	encryptedDataHex := serializedData[36:]

	password := append(serializer.EncryptKey, nonceCrypt[:]...)
	key := evpBytesToKey(string(password), 48)

	block, err := aes.NewCipher(key[:32])
	if err != nil {
		return err
	}

	iv := key[32:]

	decrypter := cipher.NewCBCDecrypter(block, iv)

	encryptedData, err := hex.DecodeString(encryptedDataHex)
	if err != nil {
		return err
	}

	decrypter.CryptBlocks(encryptedData, encryptedData)

	encryptedData = pKCS5UnPadding(encryptedData)

	nonceCheck := encryptedData[:8]

	digest := sign(encryptedData[8:], append(serializer.ValidateKey, nonceCheck[:]...))
	digestBase64 := base64.StdEncoding.EncodeToString(digest)
	digestBase64 = strings.Replace(digestBase64, "+", "-", -1)
	digestBase64 = strings.Replace(digestBase64, "/", "_", -1)

	if !strings.EqualFold(digestBase64, expectedDigest) {
		return errors.New("Bad digest")
	}

	return json.Unmarshal(encryptedData[8:], obj)
}

// NewSecureSerializer creates new serializer instance with encrypt key and validate key
func NewSecureSerializer(encryptKey []byte, validateKey []byte) *SecureSerializer {
	serializer := &SecureSerializer{encryptKey, validateKey}
	return serializer
}

// SecureStringify is a shorthand for serializer := NewSecureSerializer(...) encryptedData := serializer.Stringify(...)
func SecureStringify(obj interface{}, encryptKey []byte, validateKey []byte) (string, error) {
	serializer := NewSecureSerializer(encryptKey, validateKey)
	return serializer.Stringify(obj)
}

// SecureParse is a shorthand for serializer := NewSecureSerializer(...) serializer.Parse(...)
func SecureParse(data string, obj interface{}, encryptKey []byte, validateKey []byte) error {
	serializer := NewSecureSerializer(encryptKey, validateKey)
	return serializer.Parse(data, obj)
}
<|endoftext|>


<commit_before>// Copyright 2016 Elliott Polk. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/elliottpolk/confgr/config"

	"github.com/golang/glog"
)

func init() {
	http.HandleFunc("/list", list)
	http.HandleFunc("/get", get)
	http.HandleFunc("/set", set)
	http.HandleFunc("/remove", remove)
}

//  list is a http.Handlefunc that retrieves a list of config app names
func list(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintln(w, config.ListApps())
}

//  get is a http.HandleFunc that retrieves the relevant config for the provided
//  "app" query parameter. The results are run through json.MarshalIndent prior
//  to writing back to the HTTP reponse.
func get(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	app := r.URL.Query().Get("app")
	if len(app) < 1 {
		glog.Errorln("empty app name provided")
		http.Error(w, "invalid app name provided", http.StatusBadRequest)
		return
	}

	out, err := json.MarshalIndent(config.Get(app), "", "   ")
	if err != nil {
		glog.Errorln("unable to marshal conf: %v\n", err)
		http.Error(w, "unable to format data", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintln(w, string(out))
}

//  set is a http.HandleFunc that expects a valid config.Config in the request
//  body. It attempts to save the config to the datastore, overwriting the existing
//  app config if one exists. If the save writes properly, a http.StatusOK (200)
//  is returned automatically upon return.
func set(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		glog.Errorf("unable to read request body: %v\n", err)
		http.Error(w, "unable to read request", http.StatusInternalServerError)
		return
	}

	c := &config.Config{}
	if err := json.Unmarshal(data, &c); err != nil {
		glog.Errorf("unable to unmarshal content: %v\n", err)
		http.Error(w, "invalid content submitted", http.StatusBadRequest)
		return
	}

	if err := c.Save(); err != nil {
		glog.Errorf("unable to set config %s for app %s: %v\n", c.App, c.Value, err)
		http.Error(w, "unable to add key / value", http.StatusInternalServerError)
		return
	}
}

//  remove is a http.HandleFunc that removes the relevant config for the provided
//  "app" query parameter. If no config exists, no error is returned. If the remove
//  occurs properly, a http.StatusOK (200) is returned automatically upon return.
func remove(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	app := r.URL.Query().Get("app")
	if len(app) < 1 {
		glog.Errorln("empty app name provided")
		http.Error(w, "invalid app name provided", http.StatusBadRequest)
		return
	}

	if err := config.Remove(app); err != nil {
		glog.Errorf("unable to remove config for app %s: %v\n", app, err)
		http.Error(w, "unable to remove app config", http.StatusInternalServerError)
		return
	}
}
<commit_msg>returns saved config back from the set api<commit_after>// Copyright 2016 Elliott Polk. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/elliottpolk/confgr/config"

	"github.com/golang/glog"
)

func init() {
	http.HandleFunc("/list", list)
	http.HandleFunc("/get", get)
	http.HandleFunc("/set", set)
	http.HandleFunc("/remove", remove)
}

//  list is a http.Handlefunc that retrieves a list of config app names
func list(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintln(w, config.ListApps())
}

//  get is a http.HandleFunc that retrieves the relevant config for the provided
//  "app" query parameter. The results are run through json.MarshalIndent prior
//  to writing back to the HTTP reponse.
func get(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	app := r.URL.Query().Get("app")
	if len(app) < 1 {
		glog.Errorln("empty app name provided")
		http.Error(w, "invalid app name provided", http.StatusBadRequest)
		return
	}

	out, err := json.MarshalIndent(config.Get(app), "", "   ")
	if err != nil {
		glog.Errorln("unable to marshal conf: %v\n", err)
		http.Error(w, "unable to format data", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintln(w, string(out))
}

//  set is a http.HandleFunc that expects a valid config.Config in the request
//  body. It attempts to save the config to the datastore, overwriting the existing
//  app config if one exists. If the save writes properly, a http.StatusOK (200)
//  is returned automatically upon return.
func set(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		glog.Errorf("unable to read request body: %v\n", err)
		http.Error(w, "unable to read request", http.StatusInternalServerError)
		return
	}

	c := &config.Config{}
	if err := json.Unmarshal(data, &c); err != nil {
		glog.Errorf("unable to unmarshal content: %v\n", err)
		http.Error(w, "invalid content submitted", http.StatusBadRequest)
		return
	}

	if err := c.Save(); err != nil {
		glog.Errorf("unable to set config %s for app %s: %v\n", c.App, c.Value, err)
		http.Error(w, "unable to add key / value", http.StatusInternalServerError)
		return
	}

	out, err := json.MarshalIndent(c, "", "   ")
	if err != nil {
		glog.Errorln("unable to marshal conf: %v\n", err)
		http.Error(w, "unable to format data", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintln(w, string(out))
}

//  remove is a http.HandleFunc that removes the relevant config for the provided
//  "app" query parameter. If no config exists, no error is returned. If the remove
//  occurs properly, a http.StatusOK (200) is returned automatically upon return.
func remove(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	app := r.URL.Query().Get("app")
	if len(app) < 1 {
		glog.Errorln("empty app name provided")
		http.Error(w, "invalid app name provided", http.StatusBadRequest)
		return
	}

	if err := config.Remove(app); err != nil {
		glog.Errorf("unable to remove config for app %s: %v\n", app, err)
		http.Error(w, "unable to remove app config", http.StatusInternalServerError)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rsa"
	"github.com/ayufan/golang-kardianos-service"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"gopkg.in/fsnotify.v1"
	"gopkg.in/tylerb/graceful.v1"
	"strings"
	"time"

	"github.com/golang-devops/go-psexec/shared"
)

type app struct {
	logger          service.Logger
	gracefulTimeout time.Duration
	privateKey      *rsa.PrivateKey
	srv             *graceful.Server

	h *handler

	watcherPublicKeys *fsnotify.Watcher
}

func (a *app) Run(logger service.Logger) {
	a.logger = logger
	a.gracefulTimeout = 30 * time.Second //Because a command could be busy executing

	pvtKey, err := shared.ReadPemKey(*serverPemFlag)
	if err != nil {
		logger.Errorf("Cannot read server pem file, error: %s. Exiting server.", err.Error())
		return
	}

	a.privateKey = pvtKey

	a.h = &handler{logger, a.privateKey, nil}

	allowedKeys, err := shared.LoadAllowedPublicKeysFile(*allowedPublicKeysFileFlag)
	if err != nil {
		logger.Errorf("Cannot read allowed public keys, error: %s. Exiting server.", err.Error())
		return
	}
	if len(allowedKeys) == 0 {
		logger.Errorf("Allowed public key file '%s' was read but contains no keys. Exiting server.", *allowedPublicKeysFileFlag)
		return
	}

	a.setAllowedPublicKeys(allowedKeys)

	watcher, err := shared.StartWatcher(*allowedPublicKeysFileFlag, a)
	if err != nil {

	} else {
		a.watcherPublicKeys = watcher
	}

	e := echo.New()
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	t := &htmlTemplateRenderer{}
	e.SetRenderer(t)

	// Unrestricted group
	e.Post("/token", a.h.handleGenerateTokenFunc)
	e.Get("/webui", a.h.handleWebUIFunc)

	// Restricted group
	r := e.Group("/auth")
	r.Use(GetClientPubkey())
	r.Post("/exec", a.h.handleExecFunc)

	a.logger.Infof("Now serving on '%s'", *addressFlag)

	a.srv = &graceful.Server{
		Timeout: a.gracefulTimeout,
		Server:  e.Server(*addressFlag),
	}

	a.srv.ListenAndServe()
	if err != nil {
		if !strings.Contains(err.Error(), "closed network connection") {
			logger.Errorf("Unable to ListenAndServe, error: %s", err.Error())
		}
	}
}

func (a *app) OnStop() {
	if a.watcherPublicKeys != nil {
		a.watcherPublicKeys.Close()
	}

	// a.srv.Stop(a.gracefulTimeout)
	<-a.srv.StopChan()
}
<commit_msg>Fix a previous commit for services shutdown and also add `os.Interrupt` signal handler.<commit_after>package main

import (
	"crypto/rsa"
	"github.com/ayufan/golang-kardianos-service"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"gopkg.in/fsnotify.v1"
	"gopkg.in/tylerb/graceful.v1"
	"os"
	"os/signal"
	"strings"
	"time"

	"github.com/golang-devops/go-psexec/shared"
)

type app struct {
	logger          service.Logger
	gracefulTimeout time.Duration
	privateKey      *rsa.PrivateKey
	srv             *graceful.Server

	h *handler

	watcherPublicKeys *fsnotify.Watcher
}

func (a *app) registerInterruptSignal() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c { //for sig := range c {
			if a.srv != nil {
				a.logger.Warning("Interrupt signal received, stopping gracefully")

				c2 := make(chan bool, 1)
				go func() {
					a.srv.Stop(a.gracefulTimeout)
					c2 <- true
				}()

				select {
				case <-c2:
					a.logger.Warning("Graceful shutdown complete")
					os.Exit(0)
				case <-time.After(a.gracefulTimeout):
					a.logger.Warning("Normal timeout, forcefully exiting")
					os.Exit(1)
				}
			}
		}
	}()
}

func (a *app) Run(logger service.Logger) {
	a.logger = logger
	a.gracefulTimeout = 30 * time.Second //Because a command could be busy executing

	pvtKey, err := shared.ReadPemKey(*serverPemFlag)
	if err != nil {
		logger.Errorf("Cannot read server pem file, error: %s. Exiting server.", err.Error())
		return
	}
	a.privateKey = pvtKey

	a.h = &handler{logger, a.privateKey, nil}

	allowedKeys, err := shared.LoadAllowedPublicKeysFile(*allowedPublicKeysFileFlag)
	if err != nil {
		logger.Errorf("Cannot read allowed public keys, error: %s. Exiting server.", err.Error())
		return
	}
	if len(allowedKeys) == 0 {
		logger.Errorf("Allowed public key file '%s' was read but contains no keys. Exiting server.", *allowedPublicKeysFileFlag)
		return
	}

	a.setAllowedPublicKeys(allowedKeys)

	watcher, err := shared.StartWatcher(*allowedPublicKeysFileFlag, a)
	if err != nil {

	} else {
		a.watcherPublicKeys = watcher
	}

	e := echo.New()
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	t := &htmlTemplateRenderer{}
	e.SetRenderer(t)

	// Unrestricted group
	e.Post("/token", a.h.handleGenerateTokenFunc)
	e.Get("/webui", a.h.handleWebUIFunc)

	// Restricted group
	r := e.Group("/auth")
	r.Use(GetClientPubkey())
	r.Post("/exec", a.h.handleExecFunc)

	a.logger.Infof("Now serving on '%s'", *addressFlag)

	a.srv = &graceful.Server{
		Timeout: a.gracefulTimeout,
		Server:  e.Server(*addressFlag),
	}

	a.registerInterruptSignal()

	a.srv.ListenAndServe()
	if err != nil {
		if !strings.Contains(err.Error(), "closed network connection") {
			logger.Errorf("Unable to ListenAndServe, error: %s", err.Error())
		}
	}
}

func (a *app) OnStop() {
	if a.watcherPublicKeys != nil {
		a.watcherPublicKeys.Close()
	}

	a.srv.Stop(a.gracefulTimeout)
	<-a.srv.StopChan()
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"							//used for unifrom database access
	"fmt"									//print statements
	"github.com/go-martini/martini"			//extra frame work build on net/http
	_ "github.com/lib/pq"					//go sql driver
	"net/http"								//framework
)

func SetupDB() *sql.DB {
	db, err := sql.Open("postgres", "host=192.168.50.131 user=postgres password=1 dbname=postgres sslmode=disable") 		//my only lib/pq usage? login into postgres database
	PanicIf(err)

	return db
}

func PanicIf(err error) {
	if err != nil {
		panic(err)
	}
}

func ShowDB(db *sql.DB, r *http.Request, rw http.ResponseWriter) { //localhost:3000/?search=name
		search := "%" + r.URL.Query().Get("search") + "%"
		rows, err := db.Query(`SELECT fname, LName, cost, city
                           FROM custauth
                           WHERE FName ILIKE $1
                           OR LName ILIKE $1
                           OR city ILIKE $1`, search)
		PanicIf(err)
		defer rows.Close()

		var FirstName, LastName, cost, city string
		for rows.Next() {
			err := rows.Scan(&FirstName, &LastName, &cost, &city)
			PanicIf(err)
			fmt.Fprintf(rw, "First Name: %s\nLast Name: %s\nCost: %s\nCity: %s\n\n", FirstName, LastName, cost, city)
		}
	}

func InsertPur(r *http.Request, db *sql.DB){
//	_, err := db.Query("INSERT INTO custauth (custid, fname, lname, city,state, country,email,cost,errorflag) VALUES ($1, $2, $3, $4, $5, $6, $7, $8,$9)",
	_, err := db.Exec("INSERT INTO custauth (custid, fname, lname, city,state, country,email,cost,errorflag) VALUES ($1, $2, $3, $4, $5, $6, $7, $8,$9)",
	r.FormValue("custid"),
		r.FormValue("fname"),
		r.FormValue("lname"),
		r.FormValue("city"),
		r.FormValue("state"),
		r.FormValue("country"),
		r.FormValue("email"),
		r.FormValue("cost"),
		r.FormValue("errorflag"))

	PanicIf(err)
}

func main() {
	m := martini.Classic()
	m.Map(SetupDB())
	m.Get("/", func() string {
    return "Hello world!"
  })
	m.Get("/show", ShowDB)
	m.Post("/add", InsertPur)
	m.Run()
}
<commit_msg>Update webservice.go<commit_after>package main

import (
	"database/sql"							//used for unifrom database access
	"fmt"									//print statements
	"github.com/go-martini/martini"			//extra frame work build on net/http
	_ "github.com/lib/pq"					//go sql driver
	"net/http"								//framework
)

func SetupDB() *sql.DB {
	db, err := sql.Open("postgres", "host=192.168.50.131 user=postgres password=1 dbname=postgres sslmode=disable") 		//my only lib/pq usage? login into postgres database
	PanicIf(err)

	return db
}

func PanicIf(err error) {
	if err != nil {
		panic(err)
	}
}

func ShowDB(db *sql.DB, r *http.Request, rw http.ResponseWriter) { //localhost:3000/?search=name
		search := "%" + r.URL.Query().Get("search") + "%"
		rows, err := db.Query(`SELECT fname, LName, cost, city
                           FROM custauth
                           WHERE FName ILIKE $1
                           OR LName ILIKE $1
                           OR city ILIKE $1`, search)
		PanicIf(err)
		defer rows.Close()

		var FirstName, LastName, cost, city string
		for rows.Next() {
			err := rows.Scan(&FirstName, &LastName, &cost, &city)
			PanicIf(err)
			fmt.Fprintf(rw, "First Name: %s\nLast Name: %s\nCost: %s\nCity: %s\n\n", FirstName, LastName, cost, city)
		}
	}

func InsertPur(r *http.Request, db *sql.DB){
//	_, err := db.Query("INSERT INTO custauth (custid, fname, lname, city,state, country,email,cost,errorflag) VALUES ($1, $2, $3, $4, $5, $6, $7, $8,$9)",
	_, err := db.Exec("INSERT INTO custauth (custid, fname, lname, city,state, country,email,cost,errorflag) VALUES ($1, $2, $3, $4, $5, $6, $7, $8,$9)",
	r.FormValue("custid"),
		r.FormValue("fname"),
		r.FormValue("lname"),
		r.FormValue("city"),
		r.FormValue("state"),
		r.FormValue("country"),
		r.FormValue("email"),
		r.FormValue("cost"),
		r.FormValue("errorflag"))

	PanicIf(err)
}

func main() {
	m := martini.Classic()
	m.Map(SetupDB())
	m.Get("/", func() string {
    return "192.168.50.131 !"
  })
	m.Get("/show", ShowDB)
	m.Post("/add", InsertPur)
	m.Run()
}
<|endoftext|>