<commit_before>// +build android

package vulkan

/*
#cgo android LDFLAGS: -Wl,--no-warn-mismatch -lm_hard
#cgo android CFLAGS: -DVK_USE_PLATFORM_ANDROID_KHR -D__ARM_ARCH_7A__ -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfp -mfloat-abi=hard -march=armv7-a

#include <android/native_window.h>

#include "vulkan/vulkan.h"
#include "vk_wrapper.h"
#include "vk_bridge.h"
#include "cgo_helpers.h"
*/
import "C"
import "unsafe"

const (
	// UsePlatformAndroid as defined in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html
	UsePlatformAndroid = 1
	// KhrAndroidSurface as defined in vulkan/vulkan.h:3669
	KhrAndroidSurface = 1
	// KhrAndroidSurfaceSpecVersion as defined in vulkan/vulkan.h:3672
	KhrAndroidSurfaceSpecVersion = 6
	// KhrAndroidSurfaceExtensionName as defined in vulkan/vulkan.h:3673
	KhrAndroidSurfaceExtensionName = "VK_KHR_android_surface"
)

// CreateWindowSurface creates a Vulkan surface (VK_KHR_android_surface) for ANativeWindow from Android NDK.
func CreateWindowSurface(instance Instance, nativeWindow uintptr, pAllocator *AllocationCallbacks, pSurface *Surface) Result {
	cinstance, _ := *(*C.VkInstance)(unsafe.Pointer(&instance)), cgoAllocsUnknown
	cpAllocator, _ := (*C.VkAllocationCallbacks)(unsafe.Pointer(pAllocator)), cgoAllocsUnknown
	cpSurface, _ := (*C.VkSurfaceKHR)(unsafe.Pointer(pSurface)), cgoAllocsUnknown
	pCreateInfo := &AndroidSurfaceCreateInfo{
		SType:  StructureTypeAndroidSurfaceCreateInfo,
		Window: (*ANativeWindow)(unsafe.Pointer(nativeWindow)),
	}
	cpCreateInfo, _ := pCreateInfo.PassRef()
	__ret := C.callVkCreateAndroidSurfaceKHR(cinstance, cpCreateInfo, cpAllocator, cpSurface)
	__v := (Result)(__ret)
	return __v
}

// GetRequiredInstanceExtensions should be used to query instance extensions required for surface initialization.
func GetRequiredInstanceExtensions() []string {
	return []string{
		"VK_KHR_surface\x00",
		"VK_KHR_android_surface\x00",
	}
}

// CreateAndroidSurface function as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkCreateAndroidSurfaceKHR
func CreateAndroidSurface(instance Instance, pCreateInfo *AndroidSurfaceCreateInfo, pAllocator *AllocationCallbacks, pSurface *Surface) Result {
	cinstance, _ := *(*C.VkInstance)(unsafe.Pointer(&instance)), cgoAllocsUnknown
	cpCreateInfo, _ := pCreateInfo.PassRef()
	cpAllocator, _ := (*C.VkAllocationCallbacks)(unsafe.Pointer(pAllocator)), cgoAllocsUnknown
	cpSurface, _ := (*C.VkSurfaceKHR)(unsafe.Pointer(pSurface)), cgoAllocsUnknown
	__ret := C.callVkCreateAndroidSurfaceKHR(cinstance, cpCreateInfo, cpAllocator, cpSurface)
	__v := (Result)(__ret)
	return __v
}

// allocAndroidSurfaceCreateInfoMemory allocates memory for type C.VkAndroidSurfaceCreateInfoKHR in C.
// The caller is responsible for freeing the this memory via C.free.
func allocAndroidSurfaceCreateInfoMemory(n int) unsafe.Pointer {
	mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfAndroidSurfaceCreateInfoValue))
	if err != nil {
		panic("memory alloc error: " + err.Error())
	}
	return mem
}

const sizeOfAndroidSurfaceCreateInfoValue = unsafe.Sizeof([1]C.VkAndroidSurfaceCreateInfoKHR{})

// Ref returns the underlying reference to C object or nil if struct is nil.
func (x *AndroidSurfaceCreateInfo) Ref() *C.VkAndroidSurfaceCreateInfoKHR {
	if x == nil {
		return nil
	}
	return x.refeca5c35c
}

// Free invokes alloc map's free mechanism that cleanups any allocated memory using C free.
// Does nothing if struct is nil or has no allocation map.
func (x *AndroidSurfaceCreateInfo) Free() {
	if x != nil && x.allocseca5c35c != nil {
		x.allocseca5c35c.(*cgoAllocMap).Free()
		x.refeca5c35c = nil
	}
}

// NewAndroidSurfaceCreateInfoRef creates a new wrapper struct with underlying reference set to the original C object.
// Returns nil if the provided pointer to C object is nil too.
func NewAndroidSurfaceCreateInfoRef(ref unsafe.Pointer) *AndroidSurfaceCreateInfo {
	if ref == nil {
		return nil
	}
	obj := new(AndroidSurfaceCreateInfo)
	obj.refeca5c35c = (*C.VkAndroidSurfaceCreateInfoKHR)(unsafe.Pointer(ref))
	return obj
}

// PassRef returns the underlying C object, otherwise it will allocate one and set its values
// from this wrapping struct, counting allocations into an allocation map.
func (x *AndroidSurfaceCreateInfo) PassRef() (*C.VkAndroidSurfaceCreateInfoKHR, *cgoAllocMap) {
	if x == nil {
		return nil, nil
	} else if x.refeca5c35c != nil {
		return x.refeca5c35c, nil
	}
	memeca5c35c := allocAndroidSurfaceCreateInfoMemory(1)
	refeca5c35c := (*C.VkAndroidSurfaceCreateInfoKHR)(memeca5c35c)
	allocseca5c35c := new(cgoAllocMap)
	var csType_allocs *cgoAllocMap
	refeca5c35c.sType, csType_allocs = (C.VkStructureType)(x.SType), cgoAllocsUnknown
	allocseca5c35c.Borrow(csType_allocs)

	var cpNext_allocs *cgoAllocMap
	refeca5c35c.pNext, cpNext_allocs = *(*unsafe.Pointer)(unsafe.Pointer(&x.PNext)), cgoAllocsUnknown
	allocseca5c35c.Borrow(cpNext_allocs)

	var cflags_allocs *cgoAllocMap
	refeca5c35c.flags, cflags_allocs = (C.VkAndroidSurfaceCreateFlagsKHR)(x.Flags), cgoAllocsUnknown
	allocseca5c35c.Borrow(cflags_allocs)

	var cwindow_allocs *cgoAllocMap
	refeca5c35c.window, cwindow_allocs = *(**C.ANativeWindow)(unsafe.Pointer(&x.Window)), cgoAllocsUnknown
	allocseca5c35c.Borrow(cwindow_allocs)

	x.refeca5c35c = refeca5c35c
	x.allocseca5c35c = allocseca5c35c
	return refeca5c35c, allocseca5c35c

}

// PassValue does the same as PassRef except that it will try to dereference the returned pointer.
func (x AndroidSurfaceCreateInfo) PassValue() (C.VkAndroidSurfaceCreateInfoKHR, *cgoAllocMap) {
	if x.refeca5c35c != nil {
		return *x.refeca5c35c, nil
	}
	ref, allocs := x.PassRef()
	return *ref, allocs
}

// Deref uses the underlying reference to C object and fills the wrapping struct with values.
// Do not forget to call this method whether you get a struct for C object and want to read its values.
func (x *AndroidSurfaceCreateInfo) Deref() {
	if x.refeca5c35c == nil {
		return
	}
	x.SType = (StructureType)(x.refeca5c35c.sType)
	x.PNext = (unsafe.Pointer)(unsafe.Pointer(x.refeca5c35c.pNext))
	x.Flags = (AndroidSurfaceCreateFlags)(x.refeca5c35c.flags)
	x.Window = (*ANativeWindow)(unsafe.Pointer(x.refeca5c35c.window))
}

// ANativeWindow as declared in android/native_window.h:36
type ANativeWindow C.ANativeWindow

// AndroidSurfaceCreateFlags type as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkAndroidSurfaceCreateFlagsKHR
type AndroidSurfaceCreateFlags uint32

// AndroidSurfaceCreateInfo as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkAndroidSurfaceCreateInfoKHR
type AndroidSurfaceCreateInfo struct {
	SType          StructureType
	PNext          unsafe.Pointer
	Flags          AndroidSurfaceCreateFlags
	Window         *ANativeWindow
	refeca5c35c    *C.VkAndroidSurfaceCreateInfoKHR
	allocseca5c35c interface{}
}

// Ref returns a reference to C object as it is.
func (x *ANativeWindow) Ref() *C.ANativeWindow {
	if x == nil {
		return nil
	}
	return (*C.ANativeWindow)(unsafe.Pointer(x))
}

// Free cleanups the referenced memory using C free.
func (x *ANativeWindow) Free() {
	if x != nil {
		C.free(unsafe.Pointer(x))
	}
}

// NewANativeWindowRef converts the C object reference into a raw struct reference without wrapping.
func NewANativeWindowRef(ref unsafe.Pointer) *ANativeWindow {
	return (*ANativeWindow)(ref)
}

// NewANativeWindow allocates a new C object of this type and converts the reference into
// a raw struct reference without wrapping.
func NewANativeWindow() *ANativeWindow {
	return (*ANativeWindow)(allocANativeWindowMemory(1))
}

// allocANativeWindowMemory allocates memory for type C.ANativeWindow in C.
// The caller is responsible for freeing the this memory via C.free.
func allocANativeWindowMemory(n int) unsafe.Pointer {
	mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfANativeWindowValue))
	if err != nil {
		panic("memory alloc error: " + err.Error())
	}
	return mem
}

const sizeOfANativeWindowValue = unsafe.Sizeof([1]C.ANativeWindow{})

// PassRef returns a reference to C object as it is or allocates a new C object of this type.
func (x *ANativeWindow) PassRef() *C.ANativeWindow {
	if x == nil {
		x = (*ANativeWindow)(allocANativeWindowMemory(1))
	}
	return (*C.ANativeWindow)(unsafe.Pointer(x))
}
<commit_msg>bump to NDK 25 with clang (#66)<commit_after>// +build android

package vulkan

/*
#cgo android LDFLAGS: -Wl,--no-warn-mismatch -lm_hard
#cgo android CFLAGS: -DVK_USE_PLATFORM_ANDROID_KHR -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfp

#include <android/native_window.h>

#include "vulkan/vulkan.h"
#include "vk_wrapper.h"
#include "vk_bridge.h"
#include "cgo_helpers.h"
*/
import "C"
import "unsafe"

const (
	// UsePlatformAndroid as defined in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html
	UsePlatformAndroid = 1
	// KhrAndroidSurface as defined in vulkan/vulkan.h:3669
	KhrAndroidSurface = 1
	// KhrAndroidSurfaceSpecVersion as defined in vulkan/vulkan.h:3672
	KhrAndroidSurfaceSpecVersion = 6
	// KhrAndroidSurfaceExtensionName as defined in vulkan/vulkan.h:3673
	KhrAndroidSurfaceExtensionName = "VK_KHR_android_surface"
)

// CreateWindowSurface creates a Vulkan surface (VK_KHR_android_surface) for ANativeWindow from Android NDK.
func CreateWindowSurface(instance Instance, nativeWindow uintptr, pAllocator *AllocationCallbacks, pSurface *Surface) Result {
	cinstance, _ := *(*C.VkInstance)(unsafe.Pointer(&instance)), cgoAllocsUnknown
	cpAllocator, _ := (*C.VkAllocationCallbacks)(unsafe.Pointer(pAllocator)), cgoAllocsUnknown
	cpSurface, _ := (*C.VkSurfaceKHR)(unsafe.Pointer(pSurface)), cgoAllocsUnknown
	pCreateInfo := &AndroidSurfaceCreateInfo{
		SType:  StructureTypeAndroidSurfaceCreateInfo,
		Window: (*ANativeWindow)(unsafe.Pointer(nativeWindow)),
	}
	cpCreateInfo, _ := pCreateInfo.PassRef()
	__ret := C.callVkCreateAndroidSurfaceKHR(cinstance, cpCreateInfo, cpAllocator, cpSurface)
	__v := (Result)(__ret)
	return __v
}

// GetRequiredInstanceExtensions should be used to query instance extensions required for surface initialization.
func GetRequiredInstanceExtensions() []string {
	return []string{
		"VK_KHR_surface\x00",
		"VK_KHR_android_surface\x00",
	}
}

// CreateAndroidSurface function as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkCreateAndroidSurfaceKHR
func CreateAndroidSurface(instance Instance, pCreateInfo *AndroidSurfaceCreateInfo, pAllocator *AllocationCallbacks, pSurface *Surface) Result {
	cinstance, _ := *(*C.VkInstance)(unsafe.Pointer(&instance)), cgoAllocsUnknown
	cpCreateInfo, _ := pCreateInfo.PassRef()
	cpAllocator, _ := (*C.VkAllocationCallbacks)(unsafe.Pointer(pAllocator)), cgoAllocsUnknown
	cpSurface, _ := (*C.VkSurfaceKHR)(unsafe.Pointer(pSurface)), cgoAllocsUnknown
	__ret := C.callVkCreateAndroidSurfaceKHR(cinstance, cpCreateInfo, cpAllocator, cpSurface)
	__v := (Result)(__ret)
	return __v
}

// allocAndroidSurfaceCreateInfoMemory allocates memory for type C.VkAndroidSurfaceCreateInfoKHR in C.
// The caller is responsible for freeing the this memory via C.free.
func allocAndroidSurfaceCreateInfoMemory(n int) unsafe.Pointer {
	mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfAndroidSurfaceCreateInfoValue))
	if err != nil {
		panic("memory alloc error: " + err.Error())
	}
	return mem
}

const sizeOfAndroidSurfaceCreateInfoValue = unsafe.Sizeof([1]C.VkAndroidSurfaceCreateInfoKHR{})

// Ref returns the underlying reference to C object or nil if struct is nil.
func (x *AndroidSurfaceCreateInfo) Ref() *C.VkAndroidSurfaceCreateInfoKHR {
	if x == nil {
		return nil
	}
	return x.refeca5c35c
}

// Free invokes alloc map's free mechanism that cleanups any allocated memory using C free.
// Does nothing if struct is nil or has no allocation map.
func (x *AndroidSurfaceCreateInfo) Free() {
	if x != nil && x.allocseca5c35c != nil {
		x.allocseca5c35c.(*cgoAllocMap).Free()
		x.refeca5c35c = nil
	}
}

// NewAndroidSurfaceCreateInfoRef creates a new wrapper struct with underlying reference set to the original C object.
// Returns nil if the provided pointer to C object is nil too.
func NewAndroidSurfaceCreateInfoRef(ref unsafe.Pointer) *AndroidSurfaceCreateInfo {
	if ref == nil {
		return nil
	}
	obj := new(AndroidSurfaceCreateInfo)
	obj.refeca5c35c = (*C.VkAndroidSurfaceCreateInfoKHR)(unsafe.Pointer(ref))
	return obj
}

// PassRef returns the underlying C object, otherwise it will allocate one and set its values
// from this wrapping struct, counting allocations into an allocation map.
func (x *AndroidSurfaceCreateInfo) PassRef() (*C.VkAndroidSurfaceCreateInfoKHR, *cgoAllocMap) {
	if x == nil {
		return nil, nil
	} else if x.refeca5c35c != nil {
		return x.refeca5c35c, nil
	}
	memeca5c35c := allocAndroidSurfaceCreateInfoMemory(1)
	refeca5c35c := (*C.VkAndroidSurfaceCreateInfoKHR)(memeca5c35c)
	allocseca5c35c := new(cgoAllocMap)
	var csType_allocs *cgoAllocMap
	refeca5c35c.sType, csType_allocs = (C.VkStructureType)(x.SType), cgoAllocsUnknown
	allocseca5c35c.Borrow(csType_allocs)

	var cpNext_allocs *cgoAllocMap
	refeca5c35c.pNext, cpNext_allocs = *(*unsafe.Pointer)(unsafe.Pointer(&x.PNext)), cgoAllocsUnknown
	allocseca5c35c.Borrow(cpNext_allocs)

	var cflags_allocs *cgoAllocMap
	refeca5c35c.flags, cflags_allocs = (C.VkAndroidSurfaceCreateFlagsKHR)(x.Flags), cgoAllocsUnknown
	allocseca5c35c.Borrow(cflags_allocs)

	var cwindow_allocs *cgoAllocMap
	refeca5c35c.window, cwindow_allocs = *(**C.ANativeWindow)(unsafe.Pointer(&x.Window)), cgoAllocsUnknown
	allocseca5c35c.Borrow(cwindow_allocs)

	x.refeca5c35c = refeca5c35c
	x.allocseca5c35c = allocseca5c35c
	return refeca5c35c, allocseca5c35c

}

// PassValue does the same as PassRef except that it will try to dereference the returned pointer.
func (x AndroidSurfaceCreateInfo) PassValue() (C.VkAndroidSurfaceCreateInfoKHR, *cgoAllocMap) {
	if x.refeca5c35c != nil {
		return *x.refeca5c35c, nil
	}
	ref, allocs := x.PassRef()
	return *ref, allocs
}

// Deref uses the underlying reference to C object and fills the wrapping struct with values.
// Do not forget to call this method whether you get a struct for C object and want to read its values.
func (x *AndroidSurfaceCreateInfo) Deref() {
	if x.refeca5c35c == nil {
		return
	}
	x.SType = (StructureType)(x.refeca5c35c.sType)
	x.PNext = (unsafe.Pointer)(unsafe.Pointer(x.refeca5c35c.pNext))
	x.Flags = (AndroidSurfaceCreateFlags)(x.refeca5c35c.flags)
	x.Window = (*ANativeWindow)(unsafe.Pointer(x.refeca5c35c.window))
}

// ANativeWindow as declared in android/native_window.h:36
type ANativeWindow C.ANativeWindow

// AndroidSurfaceCreateFlags type as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkAndroidSurfaceCreateFlagsKHR
type AndroidSurfaceCreateFlags uint32

// AndroidSurfaceCreateInfo as declared in https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#vkAndroidSurfaceCreateInfoKHR
type AndroidSurfaceCreateInfo struct {
	SType          StructureType
	PNext          unsafe.Pointer
	Flags          AndroidSurfaceCreateFlags
	Window         *ANativeWindow
	refeca5c35c    *C.VkAndroidSurfaceCreateInfoKHR
	allocseca5c35c interface{}
}

// Ref returns a reference to C object as it is.
func (x *ANativeWindow) Ref() *C.ANativeWindow {
	if x == nil {
		return nil
	}
	return (*C.ANativeWindow)(unsafe.Pointer(x))
}

// Free cleanups the referenced memory using C free.
func (x *ANativeWindow) Free() {
	if x != nil {
		C.free(unsafe.Pointer(x))
	}
}

// NewANativeWindowRef converts the C object reference into a raw struct reference without wrapping.
func NewANativeWindowRef(ref unsafe.Pointer) *ANativeWindow {
	return (*ANativeWindow)(ref)
}

// NewANativeWindow allocates a new C object of this type and converts the reference into
// a raw struct reference without wrapping.
func NewANativeWindow() *ANativeWindow {
	return (*ANativeWindow)(allocANativeWindowMemory(1))
}

// allocANativeWindowMemory allocates memory for type C.ANativeWindow in C.
// The caller is responsible for freeing the this memory via C.free.
func allocANativeWindowMemory(n int) unsafe.Pointer {
	mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfANativeWindowValue))
	if err != nil {
		panic("memory alloc error: " + err.Error())
	}
	return mem
}

const sizeOfANativeWindowValue = unsafe.Sizeof([1]C.ANativeWindow{})

// PassRef returns a reference to C object as it is or allocates a new C object of this type.
func (x *ANativeWindow) PassRef() *C.ANativeWindow {
	if x == nil {
		x = (*ANativeWindow)(allocANativeWindowMemory(1))
	}
	return (*C.ANativeWindow)(unsafe.Pointer(x))
}
<|endoftext|>


<commit_before>package scpm

import (
	"errors"
	"fmt"
	"github.com/gronpipmaster/pb"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var homeFolder = os.Getenv("HOME")

type Host struct {
	User     string
	Addr     string
	Output   string
	Client   *ssh.Client
	sess     *ssh.Session
	Identity *ssh.ClientConfig
}

func NewHost(host string, key string, port int) (h *Host, err error) {
	h = new(Host)
	if strings.Index(host, "@") == -1 {
		h.User = os.Getenv("LOGNAME")
	} else {
		arrHost := strings.Split(host, "@")
		h.User = arrHost[0]
		host = strings.Replace(host, h.User+"@", "", -1)
	}
	if strings.Index(host, ":") == -1 {
		err = errors.New("host incorrect")
		return
	}
	arrHost := strings.Split(host, ":")
	h.Addr = arrHost[0] + ":" + fmt.Sprint(port)
	h.Output = arrHost[1]
	keys := []string{
		key,
		homeFolder + "/.ssh/id_rsa",
		homeFolder + "/.ssh/id_dsa",
		homeFolder + "/.ssh/id_ecdsa",
	}
	h.Identity = &ssh.ClientConfig{User: h.User}
	for _, k := range keys {
		//create ssh.Config from private keys
		f, err := os.Open(k)
		if err != nil {
			continue
		}
		data, err := ioutil.ReadAll(f)
		if err != nil {
			return h, err
		}
		signer, err := ssh.ParsePrivateKey(data)
		if err != nil {
			return h, err
		}
		h.Identity.Auth = append(h.Identity.Auth, ssh.PublicKeys(signer))
		f.Close()
	}
	return
}

func (h Host) String() string {
	str := fmt.Sprintf("%s ", h.Addr+" "+h.Output)
	//TODO fixed str size if > 50
	return str
}

func (h *Host) Auth() error {
	var err error
	if len(h.Identity.Auth) == 0 {
		return errors.New("TODO dialog password")
	} else {
		h.Client, err = ssh.Dial("tcp", h.Addr, h.Identity)
		if err != nil {
			// "TODO dialog password")
			return err
		}
	}
	return nil
}

func (h *Host) Copy(tree *Tree, wg *sync.WaitGroup, bar *pb.ProgressBar) {
	defer func() {
		bar.Finish()
		wg.Done()
	}()
	if err := h.Auth(); err != nil {
		log.Println("h.Auth", err)
		return
	}
	for _, file := range tree.Files {
		in := file.Dir + string(os.PathSeparator) + file.Info.Name()
		out := strings.Replace(in, tree.BaseDir, h.Output, -1)
		if err := h.cp(in, out, bar); err != nil && err != io.EOF {
			log.Println(err)
		}
	}
}

func (h *Host) exec(cmd string) error {
	var err error
	h.sess, err = h.Client.NewSession()
	if err != nil {
		return err
	}
	defer h.sess.Close()
	return h.sess.Run(cmd)
}

const (
	cmdCat   string = "cat > %s"
	cmdStat  string = "stat %s"
	cmdMkDir string = "mkdir -p %s"
)

//remote cp
func (h *Host) cp(in, out string, bar *pb.ProgressBar) error {
	var err error
	//create remote dir
	dir := filepath.Dir(out)
	//check folder exists
	if err := h.exec(fmt.Sprintf(cmdStat, dir)); err != nil {
		if err := h.mkdir(dir); err != nil {
			return err
		}
	}
	//open fd file
	f, err := os.Open(in)
	if err != nil {
		return err
	}
	defer f.Close()
	//open ssh session
	h.sess, err = h.Client.NewSession()
	if err != nil {
		return err
	}
	defer h.sess.Close()
	dest, err := h.sess.StdinPipe()
	if err != nil {
		return err
	}
	if err = h.sess.Start(fmt.Sprintf(cmdCat, out)); err != nil {
		return err
	}
	writer := io.MultiWriter(dest, bar)
	_, err = io.Copy(writer, f)
	return err
}

//remote mkdir
func (h *Host) mkdir(dir string) error {
	return h.exec(fmt.Sprintf(cmdMkDir, dir))
}

type Scp struct {
	hosts []*Host
	tree  *Tree
	wg    *sync.WaitGroup
	done  chan bool
}

func New(hosts []*Host, path string) (scp *Scp, err error) {
	if strings.Index(path, "~") != -1 {
		path = strings.Replace(path, "~", homeFolder, -1)
	}
	absPath, err := filepath.Abs(path)
	if err != nil {
		return
	}
	fmt.Println("Start copy", absPath)
	if len(hosts) == 0 {
		err = errors.New("hosts is nil")
		return
	}
	scp = new(Scp)
	scp.hosts = hosts
	scp.tree, err = NewTree(absPath)
	if err != nil {
		return
	}
	scp.wg = new(sync.WaitGroup)
	scp.done = make(chan bool)
	return
}

func (s *Scp) Run(quit chan bool) {
	pool := &pb.Pool{}
	for _, host := range s.hosts {
		s.wg.Add(1)
		bar := pb.New(int(s.tree.Size)).SetUnits(pb.U_BYTES).SetRefreshRate(time.Millisecond * 10)
		bar.ShowSpeed = true
		bar.Prefix(host.String())
		pool.Add(bar)
		go host.Copy(s.tree, s.wg, bar)
	}
	pool.Start()
	go func() {
		s.wg.Wait()
		time.Sleep(10 * time.Millisecond)
		s.done <- true
	}()
	for {
		select {
		case <-s.done:
			quit <- true
		}
	}
}

type Tree struct {
	BaseDir string
	Size    int64
	Files   []File
}

type File struct {
	Info os.FileInfo
	Dir  string
}

func NewTree(path string) (t *Tree, err error) {
	t = new(Tree)
	t.BaseDir = filepath.Dir(path)
	info, err := os.Stat(path)
	if err != nil {
		return
	}
	if info.IsDir() {
		err = filepath.Walk(path, t.Scan)
		return
	}
	t.Files = append(t.Files, File{Info: info, Dir: t.BaseDir})
	t.Size = info.Size()
	return
}

func (t *Tree) Scan(path string, fileInfo os.FileInfo, errInp error) (err error) {
	if errInp != nil {
		log.Println(errInp)
		return nil
	}
	if fileInfo.IsDir() {
		return nil
	}
	t.Files = append(t.Files, File{Info: fileInfo, Dir: filepath.Dir(path)})
	t.Size += fileInfo.Size()
	return
}
<commit_msg>add dialog password if identify keys is err<commit_after>package scpm

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/gronpipmaster/pb"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var homeFolder = os.Getenv("HOME")

type Host struct {
	User     string
	Addr     string
	Output   string
	Client   *ssh.Client
	sess     *ssh.Session
	Identity *ssh.ClientConfig
}

func NewHost(host string, key string, port int) (h *Host, err error) {
	h = new(Host)
	if strings.Index(host, "@") == -1 {
		h.User = os.Getenv("LOGNAME")
	} else {
		arrHost := strings.Split(host, "@")
		h.User = arrHost[0]
		host = strings.Replace(host, h.User+"@", "", -1)
	}
	if strings.Index(host, ":") == -1 {
		err = errors.New("host incorrect")
		return
	}
	arrHost := strings.Split(host, ":")
	h.Addr = arrHost[0] + ":" + fmt.Sprint(port)
	h.Output = arrHost[1]
	keys := []string{
		key,
		homeFolder + "/.ssh/id_rsa",
		homeFolder + "/.ssh/id_dsa",
		homeFolder + "/.ssh/id_ecdsa",
	}
	h.Identity = &ssh.ClientConfig{User: h.User}
	for _, k := range keys {
		//create ssh.Config from private keys
		f, err := os.Open(k)
		if err != nil {
			continue
		}
		data, err := ioutil.ReadAll(f)
		if err != nil {
			return h, err
		}
		signer, err := ssh.ParsePrivateKey(data)
		if err != nil {
			return h, err
		}
		h.Identity.Auth = append(h.Identity.Auth, ssh.PublicKeys(signer))
		f.Close()
	}
	return
}

func (h Host) String() string {
	str := fmt.Sprintf("%s ", h.Addr+" "+h.Output)
	//TODO fixed str size if > 50
	return str
}

func (h *Host) Auth() error {
	var err error
	h.Client, err = ssh.Dial("tcp", h.Addr, h.Identity)
	if err != nil {
		h.Identity.Auth = append(h.Identity.Auth, ssh.Password(dialogPassword(h.Addr)))
		h.Client, err = ssh.Dial("tcp", h.Addr, h.Identity)
		if err != nil {
			return err
		}
	}
	return nil
}

func (h *Host) Copy(tree *Tree, wg *sync.WaitGroup, bar *pb.ProgressBar) {
	defer func() {
		bar.Finish()
		wg.Done()
	}()
	for _, file := range tree.Files {
		in := file.Dir + string(os.PathSeparator) + file.Info.Name()
		out := strings.Replace(in, tree.BaseDir, h.Output, -1)
		if err := h.cp(in, out, bar); err != nil && err != io.EOF {
			log.Println(err)
		}
	}
}

func (h *Host) exec(cmd string) error {
	var err error
	h.sess, err = h.Client.NewSession()
	if err != nil {
		return err
	}
	defer h.sess.Close()
	return h.sess.Run(cmd)
}

const (
	cmdCat   string = "cat > %s"
	cmdStat  string = "stat %s"
	cmdMkDir string = "mkdir -p %s"
)

//remote cp
func (h *Host) cp(in, out string, bar *pb.ProgressBar) error {
	var err error
	//create remote dir
	dir := filepath.Dir(out)
	//check folder exists
	if err := h.exec(fmt.Sprintf(cmdStat, dir)); err != nil {
		if err := h.mkdir(dir); err != nil {
			return err
		}
	}
	//open fd file
	f, err := os.Open(in)
	if err != nil {
		return err
	}
	defer f.Close()
	//open ssh session
	h.sess, err = h.Client.NewSession()
	if err != nil {
		return err
	}
	defer h.sess.Close()
	dest, err := h.sess.StdinPipe()
	if err != nil {
		return err
	}
	if err = h.sess.Start(fmt.Sprintf(cmdCat, out)); err != nil {
		return err
	}
	writer := io.MultiWriter(dest, bar)
	_, err = io.Copy(writer, f)
	return err
}

//remote mkdir
func (h *Host) mkdir(dir string) error {
	return h.exec(fmt.Sprintf(cmdMkDir, dir))
}

type Scp struct {
	hosts []*Host
	tree  *Tree
	wg    *sync.WaitGroup
	done  chan bool
}

func New(hosts []*Host, path string) (scp *Scp, err error) {
	if strings.Index(path, "~") != -1 {
		path = strings.Replace(path, "~", homeFolder, -1)
	}
	absPath, err := filepath.Abs(path)
	if err != nil {
		return
	}
	fmt.Println("Start copy", absPath)
	if len(hosts) == 0 {
		err = errors.New("hosts is nil")
		return
	}
	scp = new(Scp)
	scp.hosts = hosts
	scp.tree, err = NewTree(absPath)
	if err != nil {
		return
	}
	scp.wg = new(sync.WaitGroup)
	scp.done = make(chan bool)
	return
}

func (s *Scp) Run(quit chan bool) {
	pool := &pb.Pool{}
	for _, host := range s.hosts {
		if err := host.Auth(); err != nil {
			fmt.Println("Auth err:", err)
			continue
		}
		s.wg.Add(1)
		bar := pb.New(int(s.tree.Size)).SetUnits(pb.U_BYTES).SetRefreshRate(time.Millisecond * 10)
		bar.ShowSpeed = true
		bar.Prefix(host.String())
		pool.Add(bar)
		go host.Copy(s.tree, s.wg, bar)
	}
	pool.Start()
	go func() {
		s.wg.Wait()
		time.Sleep(10 * time.Millisecond)
		s.done <- true
	}()
	for {
		select {
		case <-s.done:
			quit <- true
		}
	}
}

type Tree struct {
	BaseDir string
	Size    int64
	Files   []File
}

type File struct {
	Info os.FileInfo
	Dir  string
}

func NewTree(path string) (t *Tree, err error) {
	t = new(Tree)
	t.BaseDir = filepath.Dir(path)
	info, err := os.Stat(path)
	if err != nil {
		return
	}
	if info.IsDir() {
		err = filepath.Walk(path, t.Scan)
		return
	}
	t.Files = append(t.Files, File{Info: info, Dir: t.BaseDir})
	t.Size = info.Size()
	return
}

func (t *Tree) Scan(path string, fileInfo os.FileInfo, errInp error) (err error) {
	if errInp != nil {
		log.Println(errInp)
		return nil
	}
	if fileInfo.IsDir() {
		return nil
	}
	t.Files = append(t.Files, File{Info: fileInfo, Dir: filepath.Dir(path)})
	t.Size += fileInfo.Size()
	return
}

func dialogPassword(addr string) (pass string) {
	reader := bufio.NewReader(os.Stdin)
	fmt.Println(addr)
	fmt.Print("Enter Password: ")
	pass, _ = reader.ReadString('\n')
	return strings.TrimSpace(pass)
}
<|endoftext|>


<commit_before>package main

import (
	_ "time"
	"crypto/rand"
	// "encoding/binary"
	"encoding/json"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

const STATUS_FAILURE = "{\"status\":\"failure\"}"

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      []byte
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 1)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 1 {
			return
		}
		// crId, _ := binary.Varint(b)

		room := &Room{b, c1, c2}

		fmt.Println("ChatroomID: ", b)

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/question/new", newQuestion)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	chatroom := <- retChan

	fmt.Println("joinChatRoom-chatroom.id: ", chatroom.id)

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":\"", string(chatroom.id), "\"}")
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	delete(clients, uid)
	fmt.Fprint(w, "{\"status\":\"success\"}")
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}")
	} else {
		fmt.Fprint(w, STATUS_FAILURE)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		select {
		case message, ok := <- clients[uid].in:
			// fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, message)
			} else {
				fmt.Fprint(w, "")
			}
		default:
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Fprint(w, "")
	}
}

type Question struct {
	id 	int64
	title string
	body string
	difficulty int
}

func newQuestion (w http.ResponseWriter, r *http.Request) {
	row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
	q := new(Question)
	err := row.Scan(&q.id, &q.title, &q.body, &q.difficulty)

	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	b, err := json.Marshal(q)
	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	fmt.Fprint(w, string(b))
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("INSERT INTO users (facebook_id, username, email, level, points) VALUES (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, STATUS_FAILURE)
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, STATUS_FAILURE)
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>asciify<commit_after>package main

import (
	_ "time"
	"crypto/rand"
	// "encoding/binary"
	"encoding/json"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

const STATUS_FAILURE = "{\"status\":\"failure\"}"

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      []byte
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 32)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 32 {
			return
		}
		// crId, _ := binary.Varint(b)

		room := &Room{b, c1, c2}

		fmt.Println("ChatroomID: ", b)

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/question/new", newQuestion)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	chatroom := <- retChan

	fmt.Println("joinChatRoom-chatroom.id: ", chatroom.id)

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":\"", asciify(chatroom.id), "\"}")
}

func asciify(ba []byte) string {
	for i, b := range ba {
		ba[i] = (b % 26) + 97
	}
	return string(ba)
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	delete(clients, uid)
	fmt.Fprint(w, "{\"status\":\"success\"}")
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}")
	} else {
		fmt.Fprint(w, STATUS_FAILURE)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		select {
		case message, ok := <- clients[uid].in:
			// fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, message)
			} else {
				fmt.Fprint(w, "")
			}
		default:
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Fprint(w, "")
	}
}

type Question struct {
	id 	int64
	title string
	body string
	difficulty int
}

func newQuestion (w http.ResponseWriter, r *http.Request) {
	row := db.QueryRow("SELECT * FROM questions ORDER BY RAND()")
	q := new(Question)
	err := row.Scan(&q.id, &q.title, &q.body, &q.difficulty)

	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	b, err := json.Marshal(q)
	if err != nil {
		fmt.Println(err)
		fmt.Fprint(w, STATUS_FAILURE)
	}

	fmt.Fprint(w, string(b))
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("INSERT INTO users (facebook_id, username, email, level, points) VALUES (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, STATUS_FAILURE)
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, STATUS_FAILURE)
					return
				}
			}

		}

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Fprint(w, "{\"status\":\"success\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"encoding/json"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      int64
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 8)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 8 {
			return
		}
		crId, _ := binary.Varint(b)

		room := &Room{c1, c2}

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	fmt.Println(session.Values)
	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

  	fmt.Println("uid: ", uid)
	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	fmt.Println("added ", uid, " to queue")
	chatroom := <- retChan

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":", chatroom.id, "}")
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	fmt.Fprint(w, uid)
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println(uid)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}-", message)
	} else {
		fmt.Fprint(w, "{\"status\":\"failure\"}-", message)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		fmt.Println("client found")
		select {
		case message, ok := <- clients[uid].in:
			fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, message)
			} else {
				fmt.Fprint(w, "")
			}
		default:
			fmt.Println("")
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Println("client not found")
		fmt.Fprint(w, "")
	}
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, "{\"status\":\"failure\"}")
					return
				}
			}

		}

		fmt.Println("session-id: ", iq.Id)

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Println(session.Values)

		fmt.Fprint(w, "{\"status\":\"success\"}")

	// 	if err == nil {
	// 		fmt.Fprint(w, "{\"status\":\"success\",\"uid\":", iq.Id, "}")
	// 	} else {
	// 		_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
	// 		if err == nil {
	// 			row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
	// 			err = row.Scan(&iq.Id)
	// 			if err == nil {
	// 				fmt.Fprint(w, "{\"status\":\"success\"},\"uid\":", iq.Id, "}")
	// 			} else {
	// 				fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 			}
	// 		} else {
	// 			fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 		}
	// 	}
	// } else {
	// 	fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>index.html<commit_after>package main

import (
	_ "time"
	"crypto/rand"
	"encoding/binary"
	"fmt"
	"github.com/gorilla/sessions"
	"io"
	"net/http"
	"encoding/json"
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"runtime"
	"errors"
	"html/template"
)

var templates = template.Must(template.ParseFiles("index.html"))

const MESSAGE_QUEUE_SIZE = 10

var authKey = []byte("somesecretauth")
var store sessions.Store

var pool *Pool
var clients map[int64]*Client

var db *sql.DB

type Pool struct {
	in  chan *Client
	out chan *Room
}

type Client struct {
	id      int64
	in      chan string
	out     chan string
	retChan chan *Room
}

type Room struct {
	id      int64
	client1 *Client
	client2 *Client
}

func (p *Pool) Pair() {
	for {
		c1, c2 := <-p.in, <-p.in

		fmt.Println("match found for ", c1.id, " and ", c2.id)

		b := make([]byte, 8)
		n, err := io.ReadFull(rand.Reader, b)
		if err != nil || n != 8 {
			return
		}
		crId, _ := binary.Varint(b)

		room := &Room{crId, c1, c2}

		c1.in, c2.in = c2.out, c1.out

		c1.retChan <- room
		c2.retChan <- room
	}
}

func newPool() *Pool {
	pool := &Pool{
		in:  make(chan *Client),
		out: make(chan *Room),
	}

	go pool.Pair()

	return pool
}

func UIDFromSession(w http.ResponseWriter, r *http.Request) (int64, error) {
	session, _ := store.Get(r, "session")
	userid := session.Values["userid"]

	fmt.Println(session.Values)
	if userid == nil {
		return 0, errors.New("no cookie set")
	}
	return userid.(int64), nil
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	db, _ = sql.Open("mysql", "root:pass@/suitup")
	defer db.Close()

	store = sessions.NewCookieStore(authKey)

	pool = newPool()
	clients = make(map[int64]*Client)

	http.HandleFunc("/", mainHandle)

	http.HandleFunc("/login", login)

	http.HandleFunc("/message/check", checkMessage)
	http.HandleFunc("/message/send", sendMessage)

	http.HandleFunc("/chatroom/join", joinChatRoom)
	http.HandleFunc("/chatroom/leave", leaveChatRoom)

	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("/home/suitup/hackmit/assets/"))))
	http.ListenAndServe(":8080", nil)
}

type IdQuery struct {
    Id            int64      `json:"id"`

}

func mainHandle(w http.ResponseWriter, r *http.Request) {
	templates.ExecuteTemplate(w, "index.html", nil)
}

func joinChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

  	fmt.Println("uid: ", uid)
	retChan := make(chan *Room)
	client := &Client{
		id:      uid,
		in:      nil,
		out:     make(chan string, MESSAGE_QUEUE_SIZE),
		retChan: retChan,
	}
	clients[uid] = client
	pool.in <- client

	fmt.Println("added ", uid, " to queue")
	chatroom := <- retChan

	fmt.Fprint(w, "{\"status\":\"success\",\"crid\":", chatroom.id, "}")
}

func leaveChatRoom(w http.ResponseWriter, r *http.Request) {
	uid, _ := UIDFromSession(w, r)
	fmt.Fprint(w, uid)
}

func sendMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	fmt.Println(uid)

	message := r.FormValue("s")

	// message := r.PostFormValue("message")

	client := clients[uid]

	if client != nil {
		client.out <- message
		fmt.Fprint(w, "{\"status\":\"success\"}-", message)
	} else {
		fmt.Fprint(w, "{\"status\":\"failure\"}-", message)
	}
}

func checkMessage(w http.ResponseWriter, r *http.Request) {
	uid, err := UIDFromSession(w, r)
	handleError(err)

	client := clients[uid]

	if client != nil {
		fmt.Println("client found")
		select {
		case message, ok := <- clients[uid].in:
			fmt.Println("message pulled from channel")
			if ok {
				fmt.Fprint(w, message)
			} else {
				fmt.Fprint(w, "")
			}
		default:
			fmt.Println("")
			fmt.Fprint(w, "")
		}

	} else {
		fmt.Println("client not found")
		fmt.Fprint(w, "")
	}
}

func login(w http.ResponseWriter, r *http.Request) {
	inputToken := r.FormValue("access_token")
	if len(inputToken) != 0 {
		uid := GetMe(inputToken)

		// row := db.QueryRow("SELECT id FROM users")
		row := db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
		iq := new(IdQuery)
		err := row.Scan(&iq.Id)

		if err != nil {
			_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
			if err != nil {
				fmt.Fprint(w, "{\"status\":\"failure\"}")
				return
			} else {
				row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
				err = row.Scan(&iq.Id)
				if err != nil {
					fmt.Fprint(w, "{\"status\":\"failure\"}")
					return
				}
			}

		}

		fmt.Println("session-id: ", iq.Id)

		session, _ := store.Get(r, "session")
		session.Values["userid"] = iq.Id
		session.Save(r, w)

		fmt.Println(session.Values)

		fmt.Fprint(w, "{\"status\":\"success\"}")

	// 	if err == nil {
	// 		fmt.Fprint(w, "{\"status\":\"success\",\"uid\":", iq.Id, "}")
	// 	} else {
	// 		_, err = db.Exec("insert into users (facebook_id, username, email, level, points) values (?, ?, ?, 0, 0)", uid, "", "")
	// 		if err == nil {
	// 			row = db.QueryRow("SELECT id FROM users WHERE facebook_id=?", string(uid))
	// 			err = row.Scan(&iq.Id)
	// 			if err == nil {
	// 				fmt.Fprint(w, "{\"status\":\"success\"},\"uid\":", iq.Id, "}")
	// 			} else {
	// 				fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 			}
	// 		} else {
	// 			fmt.Fprint(w, "{\"status\":\"failure\"}")
	// 		}
	// 	}
	// } else {
	// 	fmt.Fprint(w, "{\"status\":\"failure\"}")
	}
}

func readHttpBody(response *http.Response) string {
	bodyBuffer := make([]byte, 1000)
	var str string

	count, err := response.Body.Read(bodyBuffer)

	for ; count > 0; count, err = response.Body.Read(bodyBuffer) {

		if err != nil {

		}

		str += string(bodyBuffer[:count])
	}

	return str

}

func getUncachedResponse(uri string) (*http.Response, error) {
	request, err := http.NewRequest("GET", uri, nil)

	if err == nil {
		request.Header.Add("Cache-Control", "no-cache")

		client := new(http.Client)

		return client.Do(request)
	}

	if (err != nil) {
	}
	return nil, err

}

func GetMe(token string) string {
	response, err := getUncachedResponse("https://graph.facebook.com/me?access_token="+token)

	if err == nil {

		var jsonBlob interface{}

		responseBody := readHttpBody(response)

		if responseBody != "" {
			err = json.Unmarshal([]byte(responseBody), &jsonBlob)

			if err == nil {
				jsonObj := jsonBlob.(map[string]interface{})
				return jsonObj["id"].(string)
			}
		}
		return err.Error()
	}

	return err.Error()
}

func handleError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>// If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
// Find the sum of all the multiples of 3 or 5 below 1000.
package main

import "fmt"

func main() {
	fmt.Println(23)
}
<commit_msg>first problem solved<commit_after>// If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
// Find the sum of all the multiples of 3 or 5 below 1000.
package main

import "fmt"

func main() {
	i := 3
	sum := 0

	for i < 1000 {
		if i%3 == 0 {
			sum += i
		} else if i%5 == 0 {
			sum += i
		}

		i += 1
	}

	fmt.Println(sum)
}
<|endoftext|>


<commit_before>package spatial

import "io"

type Chunks interface {
	Next() bool
	Scan(fc *FeatureCollection) error
}

type Decoder interface {
	Decode(io.Reader, *FeatureCollection) error
}

type ChunkedDecoder interface {
	ChunkedDecode(io.Reader) (Chunks, error)
}

type Encoder interface {
	Encode(io.Writer, *FeatureCollection) error
}

// A Codec needs to be able to tell which file extensions (e.g. "geojson")
// are commonly used to persist files. Moreover a Codec SHOULD either implement
// a Decoder or Encoder.
type Codec interface {
	Extensions() []string
}
<commit_msg>lib/spatial: chunked encoder interface<commit_after>package spatial

import "io"

type Chunks interface {
	Next() bool
	Scan(fc *FeatureCollection) error
}

type Decoder interface {
	Decode(io.Reader, *FeatureCollection) error
}

type ChunkedDecoder interface {
	ChunkedDecode(io.Reader) (Chunks, error)
}

type Encoder interface {
	Encode(io.Writer, *FeatureCollection) error
}

type ChunkedEncoder interface {
	EncodeChunk(io.Writer, *FeatureCollection) error
	Close() error
}

// A Codec needs to be able to tell which file extensions (e.g. "geojson")
// are commonly used to persist files. Moreover a Codec SHOULD either implement
// a Decoder or Encoder.
type Codec interface {
	Extensions() []string
}
<|endoftext|>


<commit_before>// Package rcserver implements the HTTP endpoint to serve the remote control
package rcserver

import (
	"encoding/json"
	"mime"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"

	"github.com/ncw/rclone/cmd/serve/httplib"
	"github.com/ncw/rclone/cmd/serve/httplib/serve"
	"github.com/ncw/rclone/fs"
	"github.com/ncw/rclone/fs/cache"
	"github.com/ncw/rclone/fs/config"
	"github.com/ncw/rclone/fs/list"
	"github.com/ncw/rclone/fs/rc"
	"github.com/pkg/errors"
	"github.com/skratchdot/open-golang/open"
)

// Start the remote control server if configured
//
// If the server wasn't configured the *Server returned may be nil
func Start(opt *rc.Options) (*Server, error) {
	if opt.Enabled {
		// Serve on the DefaultServeMux so can have global registrations appear
		s := newServer(opt, http.DefaultServeMux)
		return s, s.Serve()
	}
	return nil, nil
}

// Server contains everything to run the rc server
type Server struct {
	*httplib.Server
	files http.Handler
	opt   *rc.Options
}

func newServer(opt *rc.Options, mux *http.ServeMux) *Server {
	s := &Server{
		Server: httplib.NewServer(mux, &opt.HTTPOptions),
		opt:    opt,
	}
	mux.HandleFunc("/", s.handler)

	// Add some more mime types which are often missing
	_ = mime.AddExtensionType(".wasm", "application/wasm")
	_ = mime.AddExtensionType(".js", "application/javascript")

	// File handling
	if opt.Files != "" {
		fs.Logf(nil, "Serving files from %q", opt.Files)
		s.files = http.FileServer(http.Dir(opt.Files))
	}
	return s
}

// Serve runs the http server in the background.
//
// Use s.Close() and s.Wait() to shutdown server
func (s *Server) Serve() error {
	err := s.Server.Serve()
	if err != nil {
		return err
	}
	fs.Logf(nil, "Serving remote control on %s", s.URL())
	// Open the files in the browser if set
	if s.files != nil {
		openURL, err := url.Parse(s.URL())
		if err != nil {
			return errors.Wrap(err, "invalid serving URL")
		}
		// Add username, password into the URL if they are set
		user, pass := s.opt.HTTPOptions.BasicUser, s.opt.HTTPOptions.BasicPass
		if user != "" || pass != "" {
			openURL.User = url.UserPassword(user, pass)
		}
		_ = open.Start(openURL.String())
	}
	return nil
}

// writeError writes a formatted error to the output
func writeError(path string, in rc.Params, w http.ResponseWriter, err error, status int) {
	fs.Errorf(nil, "rc: %q: error: %v", path, err)
	// Adjust the error return for some well known errors
	errOrig := errors.Cause(err)
	switch {
	case errOrig == fs.ErrorDirNotFound || errOrig == fs.ErrorObjectNotFound:
		status = http.StatusNotFound
	case rc.IsErrParamInvalid(err) || rc.IsErrParamNotFound(err):
		status = http.StatusBadRequest
	}
	w.WriteHeader(status)
	err = rc.WriteJSON(w, rc.Params{
		"status": status,
		"error":  err.Error(),
		"input":  in,
		"path":   path,
	})
	if err != nil {
		// can't return the error at this point
		fs.Errorf(nil, "rc: failed to write JSON output: %v", err)
	}
}

// handler reads incoming requests and dispatches them
func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
	path := strings.TrimLeft(r.URL.Path, "/")

	w.Header().Add("Access-Control-Allow-Origin", "*")

	// echo back access control headers client needs
	reqAccessHeaders := r.Header.Get("Access-Control-Request-Headers")
	w.Header().Add("Access-Control-Allow-Headers", reqAccessHeaders)

	switch r.Method {
	case "POST":
		s.handlePost(w, r, path)
	case "OPTIONS":
		s.handleOptions(w, r, path)
	case "GET", "HEAD":
		s.handleGet(w, r, path)
	default:
		writeError(path, nil, w, errors.Errorf("method %q not allowed", r.Method), http.StatusMethodNotAllowed)
		return
	}
}

func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string) {
	contentType := r.Header.Get("Content-Type")

	values := r.URL.Query()
	if contentType == "application/x-www-form-urlencoded" {
		// Parse the POST and URL parameters into r.Form, for others r.Form will be empty value
		err := r.ParseForm()
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to parse form/URL parameters"), http.StatusBadRequest)
			return
		}
		values = r.Form
	}

	// Read the POST and URL parameters into in
	in := make(rc.Params)
	for k, vs := range values {
		if len(vs) > 0 {
			in[k] = vs[len(vs)-1]
		}
	}

	// Parse a JSON blob from the input
	if contentType == "application/json" {
		err := json.NewDecoder(r.Body).Decode(&in)
		if err != nil {
			writeError(path, in, w, errors.Wrap(err, "failed to read input JSON"), http.StatusBadRequest)
			return
		}
	}

	// Find the call
	call := rc.Calls.Get(path)
	if call == nil {
		writeError(path, in, w, errors.Errorf("couldn't find method %q", path), http.StatusNotFound)
		return
	}

	// Check to see if it requires authorisation
	if !s.opt.NoAuth && call.AuthRequired && !s.UsingAuth() {
		writeError(path, in, w, errors.Errorf("authentication must be set up on the rc server to use %q or the --rc-no-auth flag must be in use", path), http.StatusForbidden)
		return
	}

	// Check to see if it is async or not
	isAsync, err := in.GetBool("_async")
	if rc.NotErrParamNotFound(err) {
		writeError(path, in, w, err, http.StatusBadRequest)
		return
	}

	fs.Debugf(nil, "rc: %q: with parameters %+v", path, in)
	var out rc.Params
	if isAsync {
		out, err = rc.StartJob(call.Fn, in)
	} else {
		out, err = call.Fn(r.Context(), in)
	}
	if err != nil {
		writeError(path, in, w, err, http.StatusInternalServerError)
		return
	}
	if out == nil {
		out = make(rc.Params)
	}

	fs.Debugf(nil, "rc: %q: reply %+v: %v", path, out, err)
	err = rc.WriteJSON(w, out)
	if err != nil {
		// can't return the error at this point
		fs.Errorf(nil, "rc: failed to write JSON output: %v", err)
	}
}

func (s *Server) handleOptions(w http.ResponseWriter, r *http.Request, path string) {
	w.WriteHeader(http.StatusOK)
}

func (s *Server) serveRoot(w http.ResponseWriter, r *http.Request) {
	remotes := config.FileSections()
	sort.Strings(remotes)
	directory := serve.NewDirectory("", s.HTMLTemplate)
	directory.Title = "List of all rclone remotes."
	q := url.Values{}
	for _, remote := range remotes {
		q.Set("fs", remote)
		directory.AddEntry("["+remote+":]", true)
	}
	directory.Serve(w, r)
}

func (s *Server) serveRemote(w http.ResponseWriter, r *http.Request, path string, fsName string) {
	f, err := cache.Get(fsName)
	if err != nil {
		writeError(path, nil, w, errors.Wrap(err, "failed to make Fs"), http.StatusInternalServerError)
		return
	}
	if path == "" || strings.HasSuffix(path, "/") {
		path = strings.Trim(path, "/")
		entries, err := list.DirSorted(r.Context(), f, false, path)
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to list directory"), http.StatusInternalServerError)
			return
		}
		// Make the entries for display
		directory := serve.NewDirectory(path, s.HTMLTemplate)
		for _, entry := range entries {
			_, isDir := entry.(fs.Directory)
			directory.AddEntry(entry.Remote(), isDir)
		}
		directory.Serve(w, r)
	} else {
		path = strings.Trim(path, "/")
		o, err := f.NewObject(r.Context(), path)
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to find object"), http.StatusInternalServerError)
			return
		}
		serve.Object(w, r, o)
	}
}

// Match URLS of the form [fs]/remote
var fsMatch = regexp.MustCompile(`^\[(.*?)\](.*)$`)

func (s *Server) handleGet(w http.ResponseWriter, r *http.Request, path string) {
	// Look to see if this has an fs in the path
	match := fsMatch.FindStringSubmatch(path)
	switch {
	case match != nil && s.opt.Serve:
		// Serve /[fs]/remote files
		s.serveRemote(w, r, match[2], match[1])
		return
	case path == "*" && s.opt.Serve:
		// Serve /* as the remote listing
		s.serveRoot(w, r)
		return
	case s.files != nil:
		// Serve the files
		s.files.ServeHTTP(w, r)
		return
	case path == "" && s.opt.Serve:
		// Serve the root as a remote listing
		s.serveRoot(w, r)
		return
	}
	http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
<commit_msg>rcserver: remove _async key from input parameters after parsing so later operations won't get confused - fixes #3346<commit_after>// Package rcserver implements the HTTP endpoint to serve the remote control
package rcserver

import (
	"encoding/json"
	"mime"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"

	"github.com/ncw/rclone/cmd/serve/httplib"
	"github.com/ncw/rclone/cmd/serve/httplib/serve"
	"github.com/ncw/rclone/fs"
	"github.com/ncw/rclone/fs/cache"
	"github.com/ncw/rclone/fs/config"
	"github.com/ncw/rclone/fs/list"
	"github.com/ncw/rclone/fs/rc"
	"github.com/pkg/errors"
	"github.com/skratchdot/open-golang/open"
)

// Start the remote control server if configured
//
// If the server wasn't configured the *Server returned may be nil
func Start(opt *rc.Options) (*Server, error) {
	if opt.Enabled {
		// Serve on the DefaultServeMux so can have global registrations appear
		s := newServer(opt, http.DefaultServeMux)
		return s, s.Serve()
	}
	return nil, nil
}

// Server contains everything to run the rc server
type Server struct {
	*httplib.Server
	files http.Handler
	opt   *rc.Options
}

func newServer(opt *rc.Options, mux *http.ServeMux) *Server {
	s := &Server{
		Server: httplib.NewServer(mux, &opt.HTTPOptions),
		opt:    opt,
	}
	mux.HandleFunc("/", s.handler)

	// Add some more mime types which are often missing
	_ = mime.AddExtensionType(".wasm", "application/wasm")
	_ = mime.AddExtensionType(".js", "application/javascript")

	// File handling
	if opt.Files != "" {
		fs.Logf(nil, "Serving files from %q", opt.Files)
		s.files = http.FileServer(http.Dir(opt.Files))
	}
	return s
}

// Serve runs the http server in the background.
//
// Use s.Close() and s.Wait() to shutdown server
func (s *Server) Serve() error {
	err := s.Server.Serve()
	if err != nil {
		return err
	}
	fs.Logf(nil, "Serving remote control on %s", s.URL())
	// Open the files in the browser if set
	if s.files != nil {
		openURL, err := url.Parse(s.URL())
		if err != nil {
			return errors.Wrap(err, "invalid serving URL")
		}
		// Add username, password into the URL if they are set
		user, pass := s.opt.HTTPOptions.BasicUser, s.opt.HTTPOptions.BasicPass
		if user != "" || pass != "" {
			openURL.User = url.UserPassword(user, pass)
		}
		_ = open.Start(openURL.String())
	}
	return nil
}

// writeError writes a formatted error to the output
func writeError(path string, in rc.Params, w http.ResponseWriter, err error, status int) {
	fs.Errorf(nil, "rc: %q: error: %v", path, err)
	// Adjust the error return for some well known errors
	errOrig := errors.Cause(err)
	switch {
	case errOrig == fs.ErrorDirNotFound || errOrig == fs.ErrorObjectNotFound:
		status = http.StatusNotFound
	case rc.IsErrParamInvalid(err) || rc.IsErrParamNotFound(err):
		status = http.StatusBadRequest
	}
	w.WriteHeader(status)
	err = rc.WriteJSON(w, rc.Params{
		"status": status,
		"error":  err.Error(),
		"input":  in,
		"path":   path,
	})
	if err != nil {
		// can't return the error at this point
		fs.Errorf(nil, "rc: failed to write JSON output: %v", err)
	}
}

// handler reads incoming requests and dispatches them
func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
	path := strings.TrimLeft(r.URL.Path, "/")

	w.Header().Add("Access-Control-Allow-Origin", "*")

	// echo back access control headers client needs
	reqAccessHeaders := r.Header.Get("Access-Control-Request-Headers")
	w.Header().Add("Access-Control-Allow-Headers", reqAccessHeaders)

	switch r.Method {
	case "POST":
		s.handlePost(w, r, path)
	case "OPTIONS":
		s.handleOptions(w, r, path)
	case "GET", "HEAD":
		s.handleGet(w, r, path)
	default:
		writeError(path, nil, w, errors.Errorf("method %q not allowed", r.Method), http.StatusMethodNotAllowed)
		return
	}
}

func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string) {
	contentType := r.Header.Get("Content-Type")

	values := r.URL.Query()
	if contentType == "application/x-www-form-urlencoded" {
		// Parse the POST and URL parameters into r.Form, for others r.Form will be empty value
		err := r.ParseForm()
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to parse form/URL parameters"), http.StatusBadRequest)
			return
		}
		values = r.Form
	}

	// Read the POST and URL parameters into in
	in := make(rc.Params)
	for k, vs := range values {
		if len(vs) > 0 {
			in[k] = vs[len(vs)-1]
		}
	}

	// Parse a JSON blob from the input
	if contentType == "application/json" {
		err := json.NewDecoder(r.Body).Decode(&in)
		if err != nil {
			writeError(path, in, w, errors.Wrap(err, "failed to read input JSON"), http.StatusBadRequest)
			return
		}
	}

	// Find the call
	call := rc.Calls.Get(path)
	if call == nil {
		writeError(path, in, w, errors.Errorf("couldn't find method %q", path), http.StatusNotFound)
		return
	}

	// Check to see if it requires authorisation
	if !s.opt.NoAuth && call.AuthRequired && !s.UsingAuth() {
		writeError(path, in, w, errors.Errorf("authentication must be set up on the rc server to use %q or the --rc-no-auth flag must be in use", path), http.StatusForbidden)
		return
	}

	// Check to see if it is async or not
	isAsync, err := in.GetBool("_async")
	if rc.NotErrParamNotFound(err) {
		writeError(path, in, w, err, http.StatusBadRequest)
		return
	}

	delete(in, "_async") // remove the async parameter after parsing so vfs operations don't get confused

	fs.Debugf(nil, "rc: %q: with parameters %+v", path, in)
	var out rc.Params
	if isAsync {
		out, err = rc.StartJob(call.Fn, in)
	} else {
		out, err = call.Fn(r.Context(), in)
	}
	if err != nil {
		writeError(path, in, w, err, http.StatusInternalServerError)
		return
	}
	if out == nil {
		out = make(rc.Params)
	}

	fs.Debugf(nil, "rc: %q: reply %+v: %v", path, out, err)
	err = rc.WriteJSON(w, out)
	if err != nil {
		// can't return the error at this point
		fs.Errorf(nil, "rc: failed to write JSON output: %v", err)
	}
}

func (s *Server) handleOptions(w http.ResponseWriter, r *http.Request, path string) {
	w.WriteHeader(http.StatusOK)
}

func (s *Server) serveRoot(w http.ResponseWriter, r *http.Request) {
	remotes := config.FileSections()
	sort.Strings(remotes)
	directory := serve.NewDirectory("", s.HTMLTemplate)
	directory.Title = "List of all rclone remotes."
	q := url.Values{}
	for _, remote := range remotes {
		q.Set("fs", remote)
		directory.AddEntry("["+remote+":]", true)
	}
	directory.Serve(w, r)
}

func (s *Server) serveRemote(w http.ResponseWriter, r *http.Request, path string, fsName string) {
	f, err := cache.Get(fsName)
	if err != nil {
		writeError(path, nil, w, errors.Wrap(err, "failed to make Fs"), http.StatusInternalServerError)
		return
	}
	if path == "" || strings.HasSuffix(path, "/") {
		path = strings.Trim(path, "/")
		entries, err := list.DirSorted(r.Context(), f, false, path)
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to list directory"), http.StatusInternalServerError)
			return
		}
		// Make the entries for display
		directory := serve.NewDirectory(path, s.HTMLTemplate)
		for _, entry := range entries {
			_, isDir := entry.(fs.Directory)
			directory.AddEntry(entry.Remote(), isDir)
		}
		directory.Serve(w, r)
	} else {
		path = strings.Trim(path, "/")
		o, err := f.NewObject(r.Context(), path)
		if err != nil {
			writeError(path, nil, w, errors.Wrap(err, "failed to find object"), http.StatusInternalServerError)
			return
		}
		serve.Object(w, r, o)
	}
}

// Match URLS of the form [fs]/remote
var fsMatch = regexp.MustCompile(`^\[(.*?)\](.*)$`)

func (s *Server) handleGet(w http.ResponseWriter, r *http.Request, path string) {
	// Look to see if this has an fs in the path
	match := fsMatch.FindStringSubmatch(path)
	switch {
	case match != nil && s.opt.Serve:
		// Serve /[fs]/remote files
		s.serveRemote(w, r, match[2], match[1])
		return
	case path == "*" && s.opt.Serve:
		// Serve /* as the remote listing
		s.serveRoot(w, r)
		return
	case s.files != nil:
		// Serve the files
		s.files.ServeHTTP(w, r)
		return
	case path == "" && s.opt.Serve:
		// Serve the root as a remote listing
		s.serveRoot(w, r)
		return
	}
	http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "log"
    "fmt"
    "flag"
    "time"
    "sort"
    "bufio"
    "regexp"
    "strings"
    "strconv"
)

const (
    HISTORY_SIZE = 600
    AGING_CONSTANT = 86400
    FIELD_SEP = "\x00"
    BACKUP_SUFFIX = ".bak"
    SORT_BY_FRECENCY = "frecency"
    SORT_BY_HITS = "hits"
    SORT_BY_ATIME = "atime"
)

var (
    now = time.Now().Unix()
    historySize int64
    agingConstant int64
)

type Data struct {
    path string
    hits, atime int64
}

type Datae []Data

type ByFrecency struct {
    Datae
}

type ByAtime struct {
    Datae
}

type ByHits struct {
    Datae
}

func (d Datae) Len() int {
    return len(d)
}

func (d Datae) Swap(i, j int) {
    d[i], d[j] = d[j], d[i]
}

func(b ByFrecency) Less(i, j int) bool {
    return Score(b.Datae[i].hits, now - b.Datae[i].atime) < Score(b.Datae[j].hits, now - b.Datae[j].atime)
}

func (b ByHits) Less(i, j int) bool {
    return b.Datae[i].hits < b.Datae[j].hits
}

func (b ByAtime) Less(i, j int) bool {
    return b.Datae[i].atime < b.Datae[j].atime
}

func Score(hits int64, age int64) (float64) {
    return float64(hits) * float64(agingConstant) / float64(agingConstant + age)
}

func (d Datae) Sort(method string) {
    if method == SORT_BY_FRECENCY {
        sort.Sort(sort.Reverse(ByFrecency{d}))
    } else if method == SORT_BY_HITS {
        sort.Sort(sort.Reverse(ByHits{d}))
    } else if method == SORT_BY_ATIME {
        sort.Sort(sort.Reverse(ByAtime{d}))
    } else {
        log.Fatalf("Unknown sort method: '%v'.", method)
    }
}

func check(e error) {
    if (e != nil) {
        panic(e)
    }
}

func ReadData(r *bufio.Reader) (Data, error) {
    line, err := r.ReadString('\n')
    if (err != nil) {
        return Data{}, err
    }
    line = line[:len(line) - 1]
    tok := strings.Split(line, FIELD_SEP)
    atime, err := strconv.ParseInt(tok[0], 10, 64)
    check(err)
    hits, err := strconv.ParseInt(tok[1], 10, 64)
    check(err)
    path := tok[2]
    return Data{path, hits, atime}, nil
}

func main() {
    var dataFile string
    var pathFlag string
    if dataFile = os.Getenv("Z_DATA_FILE"); len(dataFile) == 0 {
        dataFile = os.Getenv("HOME") + string(os.PathSeparator) + ".z"
    }
    if historySize, _ = strconv.ParseInt(os.Getenv("Z_HISTORY_SIZE"), 10, 64); historySize < 1 {
        historySize = HISTORY_SIZE
    }
    if agingConstant, _ = strconv.ParseInt(os.Getenv("Z_AGING_CONSTANT"), 10, 64); agingConstant < 1 {
        agingConstant = AGING_CONSTANT
    }
    results := make(Datae, 0, historySize)
    addFlag := flag.String("a", "", "Add the given item to the data file")
    deleteFlag := flag.String("d", "", "Delete the given item from the data file")
    sortFlag := flag.String("s", SORT_BY_FRECENCY, "Use the given sort method")
    inputFlag := flag.String("i", dataFile, "Use the given file as data file")
    flag.Parse()
    dataFile = *inputFlag
    if len(*addFlag) != 0 {
        pathFlag = *addFlag
    } else if len(*deleteFlag) != 0 {
        pathFlag = *deleteFlag
    }
    fobj, err := os.Open(dataFile)
    check(err)
    defer fobj.Close()
    var bf = bufio.NewReader(fobj)
    if len(pathFlag) == 0 {
        var sPattern string
        if sPattern = strings.Join(flag.Args(), ".*"); len(sPattern) == 0 {
            sPattern = ".*"
        }
        pattern, err := regexp.Compile("(?i)" + sPattern)
        check(err)
        for d, err := ReadData(bf); err == nil; d, err = ReadData(bf) {
            if pattern.MatchString(d.path) {
                results = append(results, d)
            }
        }
        results.Sort(*sortFlag)
        for _, d := range results {
            fmt.Printf("%v\n", d.path)
        }
    } else {
        var index int64 = -1
        var cur int64
        for d, err := ReadData(bf); err == nil; d, err = ReadData(bf) {
            if (index < 0 && pathFlag == d.path) {
                index = cur
            }
            results = append(results, d)
            cur++
        }
        if len(*addFlag) != 0 {
            if (index < 0) {
                results = append(results, Data{pathFlag, 1, now})
            } else {
                results[index] = Data{pathFlag, results[index].hits + 1, now}
            }
            results.Sort(*sortFlag)
        } else if len(*deleteFlag) != 0 {
            if (index < 0) {
                log.Printf("Item is missing: '%v'.", pathFlag)
            } else {
                results = append(results[:index], results[index + 1:]...)
            }
        }
        dataFileBackup := dataFile + BACKUP_SUFFIX
        fobj, err := os.Create(dataFileBackup)
        check(err)
        defer fobj.Close()
        bf := bufio.NewWriter(fobj)
        cur = 0
        for _, d := range results {
            if cur >= historySize {
                break
            }
            _, err := bf.WriteString(fmt.Sprintf("%v%v%v%v%v\n", d.atime, FIELD_SEP, d.hits, FIELD_SEP, d.path))
            check(err)
            cur++
        }
        err = bf.Flush()
        check(err)
        err = os.Rename(dataFileBackup, dataFile)
        check(err)
    }
}
<commit_msg>Try to prevent data file corruption<commit_after>package main

import (
    "os"
    "log"
    "fmt"
    "flag"
    "time"
    "sort"
    "bufio"
    "regexp"
    "strings"
    "strconv"
    "io/ioutil"
    "path/filepath"
)

const (
    HISTORY_SIZE = 600
    AGING_CONSTANT = 86400
    FIELD_SEP = "\x00"
    SORT_BY_FRECENCY = "frecency"
    SORT_BY_HITS = "hits"
    SORT_BY_ATIME = "atime"
)

var (
    now = time.Now().Unix()
    historySize int64
    agingConstant int64
)

type Data struct {
    path string
    hits, atime int64
}

type Datae []Data

type ByFrecency struct {
    Datae
}

type ByAtime struct {
    Datae
}

type ByHits struct {
    Datae
}

func (d Datae) Len() int {
    return len(d)
}

func (d Datae) Swap(i, j int) {
    d[i], d[j] = d[j], d[i]
}

func(b ByFrecency) Less(i, j int) bool {
    return Score(b.Datae[i].hits, now - b.Datae[i].atime) < Score(b.Datae[j].hits, now - b.Datae[j].atime)
}

func (b ByHits) Less(i, j int) bool {
    return b.Datae[i].hits < b.Datae[j].hits
}

func (b ByAtime) Less(i, j int) bool {
    return b.Datae[i].atime < b.Datae[j].atime
}

func Score(hits int64, age int64) (float64) {
    return float64(hits) * float64(agingConstant) / float64(agingConstant + age)
}

func (d Datae) Sort(method string) {
    if method == SORT_BY_FRECENCY {
        sort.Sort(sort.Reverse(ByFrecency{d}))
    } else if method == SORT_BY_HITS {
        sort.Sort(sort.Reverse(ByHits{d}))
    } else if method == SORT_BY_ATIME {
        sort.Sort(sort.Reverse(ByAtime{d}))
    } else {
        log.Fatalf("Unknown sort method: '%v'.", method)
    }
}

func check(e error) {
    if (e != nil) {
        panic(e)
    }
}

func ReadData(r *bufio.Reader) (Data, error) {
    line, err := r.ReadString('\n')
    if (err != nil) {
        return Data{}, err
    }
    line = line[:len(line) - 1]
    tok := strings.Split(line, FIELD_SEP)
    atime, err := strconv.ParseInt(tok[0], 10, 64)
    check(err)
    hits, err := strconv.ParseInt(tok[1], 10, 64)
    check(err)
    path := tok[2]
    return Data{path, hits, atime}, nil
}

func main() {
    var dataFile string
    var pathFlag string
    if dataFile = os.Getenv("Z_DATA_FILE"); len(dataFile) == 0 {
        dataFile = os.Getenv("HOME") + string(os.PathSeparator) + ".z"
    }
    if historySize, _ = strconv.ParseInt(os.Getenv("Z_HISTORY_SIZE"), 10, 64); historySize < 1 {
        historySize = HISTORY_SIZE
    }
    if agingConstant, _ = strconv.ParseInt(os.Getenv("Z_AGING_CONSTANT"), 10, 64); agingConstant < 1 {
        agingConstant = AGING_CONSTANT
    }
    results := make(Datae, 0, historySize)
    addFlag := flag.String("a", "", "Add the given item to the data file")
    deleteFlag := flag.String("d", "", "Delete the given item from the data file")
    sortFlag := flag.String("s", SORT_BY_FRECENCY, "Use the given sort method")
    inputFlag := flag.String("i", dataFile, "Use the given file as data file")
    flag.Parse()
    dataFile = *inputFlag
    if len(*addFlag) != 0 {
        pathFlag = *addFlag
    } else if len(*deleteFlag) != 0 {
        pathFlag = *deleteFlag
    }
    fobj, err := os.Open(dataFile)
    check(err)
    defer fobj.Close()
    var bf = bufio.NewReader(fobj)
    if len(pathFlag) == 0 {
        var sPattern string
        if sPattern = strings.Join(flag.Args(), ".*"); len(sPattern) == 0 {
            sPattern = ".*"
        }
        pattern, err := regexp.Compile("(?i)" + sPattern)
        check(err)
        for d, err := ReadData(bf); err == nil; d, err = ReadData(bf) {
            if pattern.MatchString(d.path) {
                results = append(results, d)
            }
        }
        results.Sort(*sortFlag)
        for _, d := range results {
            fmt.Printf("%v\n", d.path)
        }
    } else {
        var index int64 = -1
        var cur int64
        for d, err := ReadData(bf); err == nil; d, err = ReadData(bf) {
            if (index < 0 && pathFlag == d.path) {
                index = cur
            }
            results = append(results, d)
            cur++
        }
        if len(*addFlag) != 0 {
            if (index < 0) {
                results = append(results, Data{pathFlag, 1, now})
            } else {
                results[index] = Data{pathFlag, results[index].hits + 1, now}
            }
            results.Sort(*sortFlag)
        } else if len(*deleteFlag) != 0 {
            if (index < 0) {
                log.Printf("Item is missing: '%v'.", pathFlag)
            } else {
                results = append(results[:index], results[index + 1:]...)
            }
        }
        fobj, err := ioutil.TempFile(filepath.Dir(dataFile), filepath.Base(dataFile))
        check(err)
        defer fobj.Close()
        bf := bufio.NewWriter(fobj)
        cur = 0
        for _, d := range results {
            if cur >= historySize {
                break
            }
            _, err := bf.WriteString(fmt.Sprintf("%v%v%v%v%v\n", d.atime, FIELD_SEP, d.hits, FIELD_SEP, d.path))
            check(err)
            cur++
        }
        err = bf.Flush()
        check(err)
        err = os.Rename(fobj.Name(), dataFile)
        check(err)
    }
}
<|endoftext|>


<commit_before>package wavreader

import (
	"fmt"
	"io"
	"os"
	"os/exec"
)

// ToMP3 creates a WAV Writer that encodes the output into an MP3 stream
func ToMP3(mp3Out io.Writer, format StreamFormat) (Writer, error) {
	return defaultConfig.ToMP3(mp3Out, format)
}

// ToMP3 creates a WAV Writer that encodes the output into an MP3 stream
func (c Config) ToMP3(mp3Out io.Writer, format StreamFormat) (Writer, error) {
	var err error

	var mode string
	if format.Channels == 1 {
		mode = "m"
	} else if format.Channels == 2 {
		mode = "j" // joint stereo
	} else {
		return nil, fmt.Errorf("unsupported number of channels %d", format.Channels)
	}

	lamecmd := []string{
		"-r", "--quiet", "--replaygain-accurate", "--id3v2-only",
		"-s", fmt.Sprintf("%g", float64(format.Rate)/1000.0),
		"--bitwidth", fmt.Sprintf("%d", format.Bits),
		"-m", mode,
	}
	if c.MaxBitrate > 0 {
		lamecmd = append(lamecmd, "-B", fmt.Sprintf("%d", c.MaxBitrate))
	} else {
		lamecmd = append(lamecmd, "--vbr-new", fmt.Sprintf("-V%d", c.VBRQuality))
	}
	lamecmd = append(lamecmd, "-", "-")

	mw := &wavWriter{
		initialized: true,
		format:      format,
	}
	mw.targetProcess = exec.Command(c.lame(), lamecmd...)

	mw.targetProcess.Stderr = os.Stderr
	mw.targetProcess.Stdout = mp3Out

	mw.target, err = mw.targetProcess.StdinPipe()
	if err != nil {
		return nil, err
	}

	err = mw.targetProcess.Start()
	if err != nil {
		return nil, err
	}

	return mw, nil
}
<commit_msg>Turns out the `-B` flag is mostly ignored in what I thought was CBR mode.<commit_after>package wavreader

import (
	"fmt"
	"io"
	"os"
	"os/exec"
)

// ToMP3 creates a WAV Writer that encodes the output into an MP3 stream
func ToMP3(mp3Out io.Writer, format StreamFormat) (Writer, error) {
	return defaultConfig.ToMP3(mp3Out, format)
}

// ToMP3 creates a WAV Writer that encodes the output into an MP3 stream
func (c Config) ToMP3(mp3Out io.Writer, format StreamFormat) (Writer, error) {
	var err error

	var mode string
	if format.Channels == 1 {
		mode = "m"
	} else if format.Channels == 2 {
		mode = "j" // joint stereo
	} else {
		return nil, fmt.Errorf("unsupported number of channels %d", format.Channels)
	}

	lamecmd := []string{
		"-r", "--quiet", "--replaygain-accurate", "--id3v2-only",
		"-s", fmt.Sprintf("%g", float64(format.Rate)/1000.0),
		"--bitwidth", fmt.Sprintf("%d", format.Bits),
		"-m", mode,
	}
	if c.MaxBitrate > 0 {
		lamecmd = append(lamecmd, "--abr", fmt.Sprintf("%d", c.MaxBitrate))
	} else {
		lamecmd = append(lamecmd, "--vbr-new", fmt.Sprintf("-V%d", c.VBRQuality))
	}
	lamecmd = append(lamecmd, "-", "-")

	mw := &wavWriter{
		initialized: true,
		format:      format,
	}
	mw.targetProcess = exec.Command(c.lame(), lamecmd...)

	mw.targetProcess.Stderr = os.Stderr
	mw.targetProcess.Stdout = mp3Out

	mw.target, err = mw.targetProcess.StdinPipe()
	if err != nil {
		return nil, err
	}

	err = mw.targetProcess.Start()
	if err != nil {
		return nil, err
	}

	return mw, nil
}
<|endoftext|>


<commit_before>package webapi

// webapiだお

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/RobotClubKut/SlackBot/lib/conf"
	"github.com/RobotClubKut/SlackBot/lib/mysql"
)

func home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

func deny(w http.ResponseWriter, r *http.Request) {
	configure := conf.ReadConfigure()
	text := r.PostFormValue("text")
	token := r.PostFormValue("token")
	userName := r.PostFormValue("user_name")
	fmt.Println("command flag:", strings.Contains(text, "deny:"))
	fmt.Println("token check:", configure.OutgoingSlackConf.Token == token)
	fmt.Println("user name:", configure.OutgoingSlackConf.UserName != userName)
	if strings.Contains(text, "deny:") && configure.OutgoingSlackConf.Token == token && configure.OutgoingSlackConf.UserName != userName {
		words := strings.Split(text, "deny:")
		var bufStr string
		for _, w := range words {
			if w != "" {
				bufStr += w
			}
		}
		words = strings.Split(bufStr, " ")
		bufStr = ""
		for _, w := range words {
			if w != "" {
				bufStr += w
			}
		}
		words = strings.Split(bufStr, ":")
		var bufStrings []string
		for _, w := range words {
			if w != "" {
				bufStrings = append(bufStrings, w)
			}
		}
		words = bufStrings
		postText := ""

		if len(words) == 0 {
			postText = "{\"text\":\"nilぱすー\"}"
		} else {
			fmt.Println("words:", words)
			mysql.InsertDenyWord(words)
			//postText := "{\"text\":\"" +  + ""\"}"
			postText = "{\"text\":\""
			for _, w := range words {
				if w != "" {
					postText += w
					postText += ","
				}
			}
			postText += "\"}"
		}

		fmt.Fprintf(w, postText)
	} else {
		if configure.OutgoingSlackConf.UserName == userName {

		} else {
			//postText := "{\"text\":\"nilぱすー\"}"
			//fmt.Fprintf(w, postText)
		}
	}
}

//ViewWebPage is view web api
func ViewWebPage() {
	configure := conf.ReadConfigure()
	http.HandleFunc("/", home)
	http.HandleFunc("/deny", deny)
	http.ListenAndServe(":"+configure.OutgoingSlackConf.Port, nil)
}
<commit_msg>受理メッセージの変更<commit_after>package webapi

// webapiだお

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/RobotClubKut/SlackBot/lib/conf"
	"github.com/RobotClubKut/SlackBot/lib/mysql"
)

func home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

func deny(w http.ResponseWriter, r *http.Request) {
	configure := conf.ReadConfigure()
	text := r.PostFormValue("text")
	token := r.PostFormValue("token")
	userName := r.PostFormValue("user_name")
	fmt.Println("command flag:", strings.Contains(text, "deny:"))
	fmt.Println("token check:", configure.OutgoingSlackConf.Token == token)
	fmt.Println("user name:", configure.OutgoingSlackConf.UserName != userName)
	if strings.Contains(text, "deny:") && configure.OutgoingSlackConf.Token == token && configure.OutgoingSlackConf.UserName != userName {
		words := strings.Split(text, "deny:")
		var bufStr string
		for _, w := range words {
			if w != "" {
				bufStr += w
			}
		}
		words = strings.Split(bufStr, " ")
		bufStr = ""
		for _, w := range words {
			if w != "" {
				bufStr += w
			}
		}
		words = strings.Split(bufStr, ":")
		var bufStrings []string
		for _, w := range words {
			if w != "" {
				bufStrings = append(bufStrings, w)
			}
		}
		words = bufStrings
		postText := ""

		if len(words) == 0 {
			postText = "{\"text\":\"nilぱすー\"}"
		} else {
			fmt.Println("words:", words)
			mysql.InsertDenyWord(words)
			//postText := "{\"text\":\"" +  + ""\"}"
			postText = "{\"text\":\"次のリストを受理したのん,: "
			for _, w := range words {
				if w != "" {
					postText += w
					postText += ","
				}
			}
			postText += "\"}"
		}

		fmt.Fprintf(w, postText)
	} else {
		if configure.OutgoingSlackConf.UserName == userName {

		} else {
			//postText := "{\"text\":\"nilぱすー\"}"
			//fmt.Fprintf(w, postText)
		}
	}
}

//ViewWebPage is view web api
func ViewWebPage() {
	configure := conf.ReadConfigure()
	http.HandleFunc("/", home)
	http.HandleFunc("/deny", deny)
	http.ListenAndServe(":"+configure.OutgoingSlackConf.Port, nil)
}
<|endoftext|>