<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package install

import (
	"bufio"
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"golang.org/x/sys/windows/registry"
	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"

	"io/ioutil"

	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

// Install only handles the driver part on Windows
func Install(context Context, binPath string, sourcePath string, components []string, force bool, timeout time.Duration, log Log) keybase1.InstallResult {
	return keybase1.InstallResult{}
}

func componentResult(name string, err error) keybase1.ComponentResult {
	if err != nil {
		return keybase1.ComponentResult{Name: string(name), Status: keybase1.StatusFromCode(keybase1.StatusCode_SCInstallError, err.Error())}
	}
	return keybase1.ComponentResult{Name: string(name), Status: keybase1.StatusOK("")}
}

// AutoInstall is not supported on Windows
func AutoInstall(context Context, binPath string, force bool, timeout time.Duration, log Log) (bool, error) {
	return false, nil
}

// Uninstall empty implementation for unsupported platforms
func Uninstall(context Context, components []string, log Log) keybase1.UninstallResult {
	return keybase1.UninstallResult{}
}

// CheckIfValidLocation is not supported on Windows
func CheckIfValidLocation() *keybase1.Error {
	return nil
}

// KBFSBinPath returns the path to the KBFS executable
func KBFSBinPath(runMode libkb.RunMode, binPath string) (string, error) {
	return kbfsBinPathDefault(runMode, binPath)
}

func kbfsBinName() string {
	return "kbfsdokan.exe"
}

func updaterBinName() (string, error) {
	// Can't name it updater.exe because of Windows "Install Detection Heuristic",
	// which is complete and total BULLSHIT LOL:
	// https://technet.microsoft.com/en-us/library/cc709628%28v=ws.10%29.aspx?f=255&MSPPError=-2147217396
	return "upd.exe", nil
}

// RunApp starts the app
func RunApp(context Context, log Log) error {
	// TODO: Start the app
	return nil
}

type utfScanner interface {
	Read(p []byte) (n int, err error)
}

// newScannerUTF16or8 creates a scanner similar to os.Open() but decodes
// the file as UTF-16 if the special byte order mark is present.
func newScannerUTF16or8(filename string) (utfScanner, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	// Check for BOM
	marker := make([]byte, 2)
	numread, err := io.ReadAtLeast(file, marker, 2)
	file.Seek(0, 0)
	if numread == 2 && err == nil && ((marker[0] == 0xFE && marker[1] == 0xFF) || (marker[0] == 0xFF && marker[1] == 0xFE)) {
		// Make an tranformer that converts MS-Win default to UTF8:
		win16be := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
		// Make a transformer that is like win16be, but abides by BOM:
		utf16bom := unicode.BOMOverride(win16be.NewDecoder())

		// Make a Reader that uses utf16bom:
		unicodeReader := transform.NewReader(file, utf16bom)
		return unicodeReader, nil
	}
	return file, nil
}

// InstallLogPath combines a handful of install logs in to one for
// server upload.
// Unfortunately, Dokan can generate UTF16 logs, so we test each file
// and translate if necessary.
func InstallLogPath() (string, error) {
	// Get the 3 newest keybase logs - sorting by name works because timestamp
	keybaseLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "Keybase*.log")))
	sort.Sort(sort.Reverse(sort.StringSlice(keybaseLogFiles)))
	if len(keybaseLogFiles) > 6 {
		keybaseLogFiles = keybaseLogFiles[:6]
	}

	// Get the latest msi log - this is the clean install .msi log
	msiLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "MSI*.LOG")))
	sort.Sort(sort.Reverse(sort.StringSlice(msiLogFiles)))
	if len(msiLogFiles) >= 1 {
		keybaseLogFiles = append(keybaseLogFiles, msiLogFiles[0])
	}

	// Get the 2 newest dokan logs - sorting by name works because timestamp
	dokanLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "Dokan*.log")))
	sort.Sort(sort.Reverse(sort.StringSlice(dokanLogFiles)))
	if len(dokanLogFiles) > 2 {
		dokanLogFiles = dokanLogFiles[:2]
	}
	keybaseLogFiles = append(keybaseLogFiles, dokanLogFiles...)

	logName, logFile, err := libkb.OpenTempFile("KeybaseInstallUpload", ".log", 0)
	defer logFile.Close()
	if err != nil {
		return "", err
	}

	getVersionAndDrivers(logFile)

	if len(keybaseLogFiles) == 0 {
		fmt.Fprintf(logFile, "   --- NO INSTALL LOGS FOUND!?! ---\n")
	}
	for _, path := range keybaseLogFiles {
		fmt.Fprintf(logFile, "   --- %s ---\n", path)

		// We have to parse the contents and write them because some files need to
		// be decoded from utf16
		s, err := newScannerUTF16or8(path)
		if err != nil {
			fmt.Fprintf(logFile, "  --- NewScannerUTF16(%s) returns %v---\n", path, err)
		} else {
			scanner := bufio.NewScanner(s)
			for scanner.Scan() {
				fmt.Fprintln(logFile, scanner.Text()) // Println will add back the final '\n'
			}
			if err := scanner.Err(); err != nil {
				fmt.Fprintf(logFile, "  --- error reading (%s): %v---\n", path, err)
			}
		}
		fmt.Fprint(logFile, "\n\n")
	}

	return logName, err
}

// WatchdogLogPath combines a handful of watchdog logs in to one for
// server upload.
func WatchdogLogPath(logGlobPath string) (string, error) {
	// Get the 5 newest watchdog logs - sorting by name works because timestamp
	watchdogLogFiles, err := filepath.Glob(logGlobPath)
	sort.Sort(sort.Reverse(sort.StringSlice(watchdogLogFiles)))
	if len(watchdogLogFiles) > 5 {
		watchdogLogFiles = watchdogLogFiles[:5]
	}

	logName, logFile, err := libkb.OpenTempFile("KeybaseWatchdogUpload", ".log", 0)
	defer logFile.Close()
	if err != nil {
		return "", err
	}

	if len(watchdogLogFiles) == 0 {
		fmt.Fprintf(logFile, "   --- NO WATCHDOG LOGS FOUND!?! ---\n")
	}
	for _, path := range watchdogLogFiles {
		fmt.Fprintf(logFile, "   --- %s ---\n", path)

		// append the files
		func() {
			fd, err := os.Open(path)
			defer fd.Close()
			if err != nil {
				fmt.Fprintf(logFile, "open error: %s\n", err.Error())
				return
			}
			_, err = io.Copy(logFile, fd)
			if err != nil {
				fmt.Fprintf(logFile, "copy error: %s\n", err.Error())
			}
		}()
	}

	return logName, err
}

func getVersionAndDrivers(logFile *os.File) {
	// Capture Windows Version
	cmd := exec.Command("cmd", "ver")
	cmd.Stdout = logFile
	cmd.Stderr = logFile
	err := cmd.Run()
	if err != nil {
		logFile.WriteString("Error getting version\n")
	}
	logFile.WriteString("\n")

	// Check 64 or 32
	cmd = exec.Command("reg", "query", "HKLM\\Hardware\\Description\\System\\CentralProcessor\\0")
	cmd.Stdout = logFile
	cmd.Stderr = logFile
	err = cmd.Run()
	if err != nil {
		logFile.WriteString("Error getting CPU type\n")
	}
	logFile.WriteString("\n")

	// Check whether the service shortcut is still present and not disabled
	if appDataDir, err := libkb.AppDataDir(); err != nil {
		logFile.WriteString("Error getting AppDataDir\n")
	} else {
		if exists, err := libkb.FileExists(filepath.Join(appDataDir, "Microsoft\\Windows\\Start Menu\\Programs\\Startup\\KeybaseStartup.lnk")); err == nil && exists == false {
			logFile.WriteString("  -- Service startup shortcut missing! --\n\n")
		} else if err != nil {
			k, err := registry.OpenKey(registry.CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\StartupFolder", registry.QUERY_VALUE|registry.READ)
			if err != nil {
				logFile.WriteString("Error opening Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\StartupFolder\n")
			} else {
				val, _, err := k.GetBinaryValue("KeybaseStartup.lnk")
				if err == nil && len(val) > 0 && val[0] != 2 {
					logFile.WriteString("  -- Service startup shortcut disabled in registry! --\n\n")
				}
			}
		}
	}

	// List filesystem drivers
	outputBytes, err := exec.Command("driverquery").Output()
	if err != nil {
		fmt.Fprintf(logFile, "Error querying drivers: %v\n", err)
	}
	// For now, only list filesystem ones
	scanner := bufio.NewScanner(bytes.NewReader(outputBytes))
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), "File System") {
			logFile.WriteString(scanner.Text() + "\n")
		}
	}
	logFile.WriteString("\n\n")
}

func SystemLogPath() string {
	return ""
}

// IsInUse returns true if the mount is in use. This may be used by the updater
// to determine if it's safe to apply an update and restart.
func IsInUse(mountDir string, log Log) bool {
	if mountDir == "" {
		return false
	}
	if _, serr := os.Stat(mountDir); os.IsNotExist(serr) {
		log.Debug("%s doesn't exist", mountDir)
		return false
	}

	dat, err := ioutil.ReadFile(filepath.Join(mountDir, ".kbfs_number_of_handles"))
	if err != nil {
		log.Debug("Error reading kbfs handles: %s", err)
		return false
	}
	i, err := strconv.Atoi(string(dat))
	if err != nil {
		log.Debug("Error converting count of kbfs handles: %s", err)
		return false
	}
	if i > 0 {
		log.Debug("Found kbfs handles in use: %d", i)
		return true
	}

	return false
}

func getCachedPackageModifyString(log Log) (string, error) {

	k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Keybase\Keybase\`, registry.READ|registry.WOW64_64KEY)
	defer k.Close()
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't open SOFTWARE\\Keybase\\Keybase\\")
		return "", err
	}
	bundleKey, _, err := k.GetStringValue("BUNDLEKEY")
	if err != nil || bundleKey == "" {
		log.Debug("getCachedPackageModifyString: can't read SOFTWARE\\Keybase\\Keybase\\BUNDLEKEY")
		return "", err
	}

	k2, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`+bundleKey, registry.QUERY_VALUE|registry.WOW64_64KEY)
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
		return "", err
	}
	displayName, _, err := k2.GetStringValue("DisplayName")
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read DisplayName of " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
	}
	publisher, _, err := k2.GetStringValue("Publisher")
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read publisher of " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
	}
	if displayName == "Keybase" && publisher == "Keybase, Inc." {
		modify, _, err := k2.GetStringValue("ModifyPath")
		return modify, err
	}
	log.Debug("getCachedPackageModifyString: " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey + "displayName " + displayName + ", publisher " + publisher)
	return "", errors.New("no cached package path found")
}

// StartUpdateIfNeeded starts to update the app if there's one available. It
// calls `updater check` internally so it ignores the snooze.
func StartUpdateIfNeeded(ctx context.Context, log logger.Logger) error {
	updaterPath, err := UpdaterBinPath()
	if err != nil {
		return err
	}
	pid, err := libcmdline.SpawnDetachedProcess(
		updaterPath, []string{"check"}, log)
	if err != nil {
		return err
	}
	log.Debug("Started background updater process (%s). pid=%d", updaterPath, pid)
	process, err := os.FindProcess(pid)
	if err != nil {
		return err
	}
	// Ignore the exit status here as user may have hit "Ignore". If we are
	// here without getting killed, it's likely user has hit "Ignore". Just
	// just return `nil` and GUI would check for update info again where it'd
	// know we don't need to update anymore.
	process.Wait()
	return nil
}
<commit_msg>use keybaserq.exe for "Update Now" on win (#14755)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package install

import (
	"bufio"
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"golang.org/x/sys/windows/registry"
	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"

	"io/ioutil"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
)

// Install only handles the driver part on Windows
func Install(context Context, binPath string, sourcePath string, components []string, force bool, timeout time.Duration, log Log) keybase1.InstallResult {
	return keybase1.InstallResult{}
}

func componentResult(name string, err error) keybase1.ComponentResult {
	if err != nil {
		return keybase1.ComponentResult{Name: string(name), Status: keybase1.StatusFromCode(keybase1.StatusCode_SCInstallError, err.Error())}
	}
	return keybase1.ComponentResult{Name: string(name), Status: keybase1.StatusOK("")}
}

// AutoInstall is not supported on Windows
func AutoInstall(context Context, binPath string, force bool, timeout time.Duration, log Log) (bool, error) {
	return false, nil
}

// Uninstall empty implementation for unsupported platforms
func Uninstall(context Context, components []string, log Log) keybase1.UninstallResult {
	return keybase1.UninstallResult{}
}

// CheckIfValidLocation is not supported on Windows
func CheckIfValidLocation() *keybase1.Error {
	return nil
}

// KBFSBinPath returns the path to the KBFS executable
func KBFSBinPath(runMode libkb.RunMode, binPath string) (string, error) {
	return kbfsBinPathDefault(runMode, binPath)
}

func kbfsBinName() string {
	return "kbfsdokan.exe"
}

func updaterBinName() (string, error) {
	// Can't name it updater.exe because of Windows "Install Detection Heuristic",
	// which is complete and total BULLSHIT LOL:
	// https://technet.microsoft.com/en-us/library/cc709628%28v=ws.10%29.aspx?f=255&MSPPError=-2147217396
	return "upd.exe", nil
}

func rqBinPath() (string, error) {
	path, err := BinPath()
	if err != nil {
		return "", err
	}
	return filepath.Join(filepath.Dir(path), "keybaserq.exe"), nil
}

// RunApp starts the app
func RunApp(context Context, log Log) error {
	// TODO: Start the app
	return nil
}

type utfScanner interface {
	Read(p []byte) (n int, err error)
}

// newScannerUTF16or8 creates a scanner similar to os.Open() but decodes
// the file as UTF-16 if the special byte order mark is present.
func newScannerUTF16or8(filename string) (utfScanner, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	// Check for BOM
	marker := make([]byte, 2)
	numread, err := io.ReadAtLeast(file, marker, 2)
	file.Seek(0, 0)
	if numread == 2 && err == nil && ((marker[0] == 0xFE && marker[1] == 0xFF) || (marker[0] == 0xFF && marker[1] == 0xFE)) {
		// Make an tranformer that converts MS-Win default to UTF8:
		win16be := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
		// Make a transformer that is like win16be, but abides by BOM:
		utf16bom := unicode.BOMOverride(win16be.NewDecoder())

		// Make a Reader that uses utf16bom:
		unicodeReader := transform.NewReader(file, utf16bom)
		return unicodeReader, nil
	}
	return file, nil
}

// InstallLogPath combines a handful of install logs in to one for
// server upload.
// Unfortunately, Dokan can generate UTF16 logs, so we test each file
// and translate if necessary.
func InstallLogPath() (string, error) {
	// Get the 3 newest keybase logs - sorting by name works because timestamp
	keybaseLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "Keybase*.log")))
	sort.Sort(sort.Reverse(sort.StringSlice(keybaseLogFiles)))
	if len(keybaseLogFiles) > 6 {
		keybaseLogFiles = keybaseLogFiles[:6]
	}

	// Get the latest msi log - this is the clean install .msi log
	msiLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "MSI*.LOG")))
	sort.Sort(sort.Reverse(sort.StringSlice(msiLogFiles)))
	if len(msiLogFiles) >= 1 {
		keybaseLogFiles = append(keybaseLogFiles, msiLogFiles[0])
	}

	// Get the 2 newest dokan logs - sorting by name works because timestamp
	dokanLogFiles, err := filepath.Glob(os.ExpandEnv(filepath.Join("${TEMP}", "Dokan*.log")))
	sort.Sort(sort.Reverse(sort.StringSlice(dokanLogFiles)))
	if len(dokanLogFiles) > 2 {
		dokanLogFiles = dokanLogFiles[:2]
	}
	keybaseLogFiles = append(keybaseLogFiles, dokanLogFiles...)

	logName, logFile, err := libkb.OpenTempFile("KeybaseInstallUpload", ".log", 0)
	defer logFile.Close()
	if err != nil {
		return "", err
	}

	getVersionAndDrivers(logFile)

	if len(keybaseLogFiles) == 0 {
		fmt.Fprintf(logFile, "   --- NO INSTALL LOGS FOUND!?! ---\n")
	}
	for _, path := range keybaseLogFiles {
		fmt.Fprintf(logFile, "   --- %s ---\n", path)

		// We have to parse the contents and write them because some files need to
		// be decoded from utf16
		s, err := newScannerUTF16or8(path)
		if err != nil {
			fmt.Fprintf(logFile, "  --- NewScannerUTF16(%s) returns %v---\n", path, err)
		} else {
			scanner := bufio.NewScanner(s)
			for scanner.Scan() {
				fmt.Fprintln(logFile, scanner.Text()) // Println will add back the final '\n'
			}
			if err := scanner.Err(); err != nil {
				fmt.Fprintf(logFile, "  --- error reading (%s): %v---\n", path, err)
			}
		}
		fmt.Fprint(logFile, "\n\n")
	}

	return logName, err
}

// WatchdogLogPath combines a handful of watchdog logs in to one for
// server upload.
func WatchdogLogPath(logGlobPath string) (string, error) {
	// Get the 5 newest watchdog logs - sorting by name works because timestamp
	watchdogLogFiles, err := filepath.Glob(logGlobPath)
	sort.Sort(sort.Reverse(sort.StringSlice(watchdogLogFiles)))
	if len(watchdogLogFiles) > 5 {
		watchdogLogFiles = watchdogLogFiles[:5]
	}

	logName, logFile, err := libkb.OpenTempFile("KeybaseWatchdogUpload", ".log", 0)
	defer logFile.Close()
	if err != nil {
		return "", err
	}

	if len(watchdogLogFiles) == 0 {
		fmt.Fprintf(logFile, "   --- NO WATCHDOG LOGS FOUND!?! ---\n")
	}
	for _, path := range watchdogLogFiles {
		fmt.Fprintf(logFile, "   --- %s ---\n", path)

		// append the files
		func() {
			fd, err := os.Open(path)
			defer fd.Close()
			if err != nil {
				fmt.Fprintf(logFile, "open error: %s\n", err.Error())
				return
			}
			_, err = io.Copy(logFile, fd)
			if err != nil {
				fmt.Fprintf(logFile, "copy error: %s\n", err.Error())
			}
		}()
	}

	return logName, err
}

func getVersionAndDrivers(logFile *os.File) {
	// Capture Windows Version
	cmd := exec.Command("cmd", "ver")
	cmd.Stdout = logFile
	cmd.Stderr = logFile
	err := cmd.Run()
	if err != nil {
		logFile.WriteString("Error getting version\n")
	}
	logFile.WriteString("\n")

	// Check 64 or 32
	cmd = exec.Command("reg", "query", "HKLM\\Hardware\\Description\\System\\CentralProcessor\\0")
	cmd.Stdout = logFile
	cmd.Stderr = logFile
	err = cmd.Run()
	if err != nil {
		logFile.WriteString("Error getting CPU type\n")
	}
	logFile.WriteString("\n")

	// Check whether the service shortcut is still present and not disabled
	if appDataDir, err := libkb.AppDataDir(); err != nil {
		logFile.WriteString("Error getting AppDataDir\n")
	} else {
		if exists, err := libkb.FileExists(filepath.Join(appDataDir, "Microsoft\\Windows\\Start Menu\\Programs\\Startup\\KeybaseStartup.lnk")); err == nil && exists == false {
			logFile.WriteString("  -- Service startup shortcut missing! --\n\n")
		} else if err != nil {
			k, err := registry.OpenKey(registry.CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\StartupFolder", registry.QUERY_VALUE|registry.READ)
			if err != nil {
				logFile.WriteString("Error opening Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\StartupFolder\n")
			} else {
				val, _, err := k.GetBinaryValue("KeybaseStartup.lnk")
				if err == nil && len(val) > 0 && val[0] != 2 {
					logFile.WriteString("  -- Service startup shortcut disabled in registry! --\n\n")
				}
			}
		}
	}

	// List filesystem drivers
	outputBytes, err := exec.Command("driverquery").Output()
	if err != nil {
		fmt.Fprintf(logFile, "Error querying drivers: %v\n", err)
	}
	// For now, only list filesystem ones
	scanner := bufio.NewScanner(bytes.NewReader(outputBytes))
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), "File System") {
			logFile.WriteString(scanner.Text() + "\n")
		}
	}
	logFile.WriteString("\n\n")
}

func SystemLogPath() string {
	return ""
}

// IsInUse returns true if the mount is in use. This may be used by the updater
// to determine if it's safe to apply an update and restart.
func IsInUse(mountDir string, log Log) bool {
	if mountDir == "" {
		return false
	}
	if _, serr := os.Stat(mountDir); os.IsNotExist(serr) {
		log.Debug("%s doesn't exist", mountDir)
		return false
	}

	dat, err := ioutil.ReadFile(filepath.Join(mountDir, ".kbfs_number_of_handles"))
	if err != nil {
		log.Debug("Error reading kbfs handles: %s", err)
		return false
	}
	i, err := strconv.Atoi(string(dat))
	if err != nil {
		log.Debug("Error converting count of kbfs handles: %s", err)
		return false
	}
	if i > 0 {
		log.Debug("Found kbfs handles in use: %d", i)
		return true
	}

	return false
}

func getCachedPackageModifyString(log Log) (string, error) {

	k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Keybase\Keybase\`, registry.READ|registry.WOW64_64KEY)
	defer k.Close()
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't open SOFTWARE\\Keybase\\Keybase\\")
		return "", err
	}
	bundleKey, _, err := k.GetStringValue("BUNDLEKEY")
	if err != nil || bundleKey == "" {
		log.Debug("getCachedPackageModifyString: can't read SOFTWARE\\Keybase\\Keybase\\BUNDLEKEY")
		return "", err
	}

	k2, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`+bundleKey, registry.QUERY_VALUE|registry.WOW64_64KEY)
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
		return "", err
	}
	displayName, _, err := k2.GetStringValue("DisplayName")
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read DisplayName of " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
	}
	publisher, _, err := k2.GetStringValue("Publisher")
	if err != nil {
		log.Debug("getCachedPackageModifyString: can't read publisher of " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey)
	}
	if displayName == "Keybase" && publisher == "Keybase, Inc." {
		modify, _, err := k2.GetStringValue("ModifyPath")
		return modify, err
	}
	log.Debug("getCachedPackageModifyString: " + `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + bundleKey + "displayName " + displayName + ", publisher " + publisher)
	return "", errors.New("no cached package path found")
}

// StartUpdateIfNeeded starts to update the app if there's one available. It
// calls `updater check` internally so it ignores the snooze.
func StartUpdateIfNeeded(ctx context.Context, log logger.Logger) error {
	rqPath, err := rqBinPath()
	if err != nil {
		return err
	}
	updaterPath, err := UpdaterBinPath()
	if err != nil {
		return err
	}
	log.Debug("Starting updater with keybaserq.exe")
	if err = exec.Command(rqPath, updaterPath, "check").Run(); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package weed_server

import (
	"bytes"
	"code.google.com/p/weed-fs/go/glog"
	"code.google.com/p/weed-fs/go/operation"
	"code.google.com/p/weed-fs/go/stats"
	"code.google.com/p/weed-fs/go/storage"
	"code.google.com/p/weed-fs/go/util"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
)

var serverStats *stats.ServerStats

func init() {
	serverStats = stats.NewServerStats()
	go serverStats.Start()

}

func writeJson(w http.ResponseWriter, r *http.Request, obj interface{}) (err error) {
	w.Header().Set("Content-Type", "application/javascript")
	var bytes []byte
	if r.FormValue("pretty") != "" {
		bytes, err = json.MarshalIndent(obj, "", "  ")
	} else {
		bytes, err = json.Marshal(obj)
	}
	if err != nil {
		return
	}
	callback := r.FormValue("callback")
	if callback == "" {
		_, err = w.Write(bytes)
	} else {
		if _, err = w.Write([]uint8(callback)); err != nil {
			return
		}
		if _, err = w.Write([]uint8("(")); err != nil {
			return
		}
		fmt.Fprint(w, string(bytes))
		if _, err = w.Write([]uint8(")")); err != nil {
			return
		}
	}
	return
}

// wrapper for writeJson - just logs errors
func writeJsonQuiet(w http.ResponseWriter, r *http.Request, obj interface{}) {
	if err := writeJson(w, r, obj); err != nil {
		glog.V(0).Infof("error writing JSON %s: %s", obj, err.Error())
	}
}
func writeJsonError(w http.ResponseWriter, r *http.Request, err error) {
	w.WriteHeader(http.StatusInternalServerError)
	m := make(map[string]interface{})
	m["error"] = err.Error()
	writeJsonQuiet(w, r, m)
}

func debug(params ...interface{}) {
	glog.V(4).Infoln(params)
}

func secure(whiteList []string, f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if len(whiteList) == 0 {
			f(w, r)
			return
		}
		host, _, err := net.SplitHostPort(r.RemoteAddr)
		if err == nil {
			for _, ip := range whiteList {
				if ip == host {
					f(w, r)
					return
				}
			}
		}
		writeJsonQuiet(w, r, map[string]interface{}{"error": "No write permisson from " + host})
	}
}

func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
	m := make(map[string]interface{})
	if r.Method != "POST" {
		m["error"] = "Only submit via POST!"
		writeJsonQuiet(w, r, m)
		return
	}

	debug("parsing upload file...")
	fname, data, mimeType, isGzipped, lastModified, pe := storage.ParseUpload(r)
	if pe != nil {
		writeJsonError(w, r, pe)
		return
	}

	debug("assigning file id for", fname)
	assignResult, ae := operation.Assign(masterUrl, 1, r.FormValue("replication"), r.FormValue("collection"))
	if ae != nil {
		writeJsonError(w, r, ae)
		return
	}

	url := "http://" + assignResult.PublicUrl + "/" + assignResult.Fid
	if lastModified != 0 {
		url = url + "?ts=" + strconv.FormatUint(lastModified, 10)
	}

	debug("upload file to store", url)
	uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType)
	if err != nil {
		writeJsonError(w, r, err)
		return
	}

	m["fileName"] = fname
	m["fid"] = assignResult.Fid
	m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid
	m["size"] = uploadResult.Size
	writeJsonQuiet(w, r, m)
	return
}

func deleteForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
	r.ParseForm()
	fids := r.Form["fid"]
	ret, err := operation.DeleteFiles(masterUrl, fids)
	if err != nil {
		writeJsonError(w, r, err)
		return
	}
	writeJsonQuiet(w, r, ret)
}

func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) {
	switch strings.Count(path, "/") {
	case 3:
		parts := strings.Split(path, "/")
		vid, fid, filename = parts[1], parts[2], parts[3]
		ext = filepath.Ext(filename)
	case 2:
		parts := strings.Split(path, "/")
		vid, fid = parts[1], parts[2]
		dotIndex := strings.LastIndex(fid, ".")
		if dotIndex > 0 {
			ext = fid[dotIndex:]
			fid = fid[0:dotIndex]
		}
	default:
		sepIndex := strings.LastIndex(path, "/")
		commaIndex := strings.LastIndex(path[sepIndex:], ",")
		if commaIndex <= 0 {
			vid, isVolumeIdOnly = path[sepIndex+1:], true
			return
		}
		dotIndex := strings.LastIndex(path[sepIndex:], ".")
		vid = path[sepIndex+1 : commaIndex]
		fid = path[commaIndex+1:]
		ext = ""
		if dotIndex > 0 {
			fid = path[commaIndex+1 : dotIndex]
			ext = path[dotIndex:]
		}
	}
	return
}

func statsCounterHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Counters"] = serverStats
	writeJsonQuiet(w, r, m)
}

func statsMemoryHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Memory"] = stats.MemStat()
	writeJsonQuiet(w, r, m)
}
<commit_msg>Setting application/json for json result. Setting application/javascript for jsonp result.<commit_after>package weed_server

import (
	"bytes"
	"code.google.com/p/weed-fs/go/glog"
	"code.google.com/p/weed-fs/go/operation"
	"code.google.com/p/weed-fs/go/stats"
	"code.google.com/p/weed-fs/go/storage"
	"code.google.com/p/weed-fs/go/util"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
)

var serverStats *stats.ServerStats

func init() {
	serverStats = stats.NewServerStats()
	go serverStats.Start()

}

func writeJson(w http.ResponseWriter, r *http.Request, obj interface{}) (err error) {
	var bytes []byte
	if r.FormValue("pretty") != "" {
		bytes, err = json.MarshalIndent(obj, "", "  ")
	} else {
		bytes, err = json.Marshal(obj)
	}
	if err != nil {
		return
	}
	callback := r.FormValue("callback")
	if callback == "" {
		w.Header().Set("Content-Type", "application/json")
		_, err = w.Write(bytes)
	} else {
		w.Header().Set("Content-Type", "application/javascript")
		if _, err = w.Write([]uint8(callback)); err != nil {
			return
		}
		if _, err = w.Write([]uint8("(")); err != nil {
			return
		}
		fmt.Fprint(w, string(bytes))
		if _, err = w.Write([]uint8(")")); err != nil {
			return
		}
	}
	return
}

// wrapper for writeJson - just logs errors
func writeJsonQuiet(w http.ResponseWriter, r *http.Request, obj interface{}) {
	if err := writeJson(w, r, obj); err != nil {
		glog.V(0).Infof("error writing JSON %s: %s", obj, err.Error())
	}
}
func writeJsonError(w http.ResponseWriter, r *http.Request, err error) {
	w.WriteHeader(http.StatusInternalServerError)
	m := make(map[string]interface{})
	m["error"] = err.Error()
	writeJsonQuiet(w, r, m)
}

func debug(params ...interface{}) {
	glog.V(4).Infoln(params)
}

func secure(whiteList []string, f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if len(whiteList) == 0 {
			f(w, r)
			return
		}
		host, _, err := net.SplitHostPort(r.RemoteAddr)
		if err == nil {
			for _, ip := range whiteList {
				if ip == host {
					f(w, r)
					return
				}
			}
		}
		writeJsonQuiet(w, r, map[string]interface{}{"error": "No write permisson from " + host})
	}
}

func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
	m := make(map[string]interface{})
	if r.Method != "POST" {
		m["error"] = "Only submit via POST!"
		writeJsonQuiet(w, r, m)
		return
	}

	debug("parsing upload file...")
	fname, data, mimeType, isGzipped, lastModified, pe := storage.ParseUpload(r)
	if pe != nil {
		writeJsonError(w, r, pe)
		return
	}

	debug("assigning file id for", fname)
	assignResult, ae := operation.Assign(masterUrl, 1, r.FormValue("replication"), r.FormValue("collection"))
	if ae != nil {
		writeJsonError(w, r, ae)
		return
	}

	url := "http://" + assignResult.PublicUrl + "/" + assignResult.Fid
	if lastModified != 0 {
		url = url + "?ts=" + strconv.FormatUint(lastModified, 10)
	}

	debug("upload file to store", url)
	uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType)
	if err != nil {
		writeJsonError(w, r, err)
		return
	}

	m["fileName"] = fname
	m["fid"] = assignResult.Fid
	m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid
	m["size"] = uploadResult.Size
	writeJsonQuiet(w, r, m)
	return
}

func deleteForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
	r.ParseForm()
	fids := r.Form["fid"]
	ret, err := operation.DeleteFiles(masterUrl, fids)
	if err != nil {
		writeJsonError(w, r, err)
		return
	}
	writeJsonQuiet(w, r, ret)
}

func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) {
	switch strings.Count(path, "/") {
	case 3:
		parts := strings.Split(path, "/")
		vid, fid, filename = parts[1], parts[2], parts[3]
		ext = filepath.Ext(filename)
	case 2:
		parts := strings.Split(path, "/")
		vid, fid = parts[1], parts[2]
		dotIndex := strings.LastIndex(fid, ".")
		if dotIndex > 0 {
			ext = fid[dotIndex:]
			fid = fid[0:dotIndex]
		}
	default:
		sepIndex := strings.LastIndex(path, "/")
		commaIndex := strings.LastIndex(path[sepIndex:], ",")
		if commaIndex <= 0 {
			vid, isVolumeIdOnly = path[sepIndex+1:], true
			return
		}
		dotIndex := strings.LastIndex(path[sepIndex:], ".")
		vid = path[sepIndex+1 : commaIndex]
		fid = path[commaIndex+1:]
		ext = ""
		if dotIndex > 0 {
			fid = path[commaIndex+1 : dotIndex]
			ext = path[dotIndex:]
		}
	}
	return
}

func statsCounterHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Counters"] = serverStats
	writeJsonQuiet(w, r, m)
}

func statsMemoryHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]interface{})
	m["Version"] = util.VERSION
	m["Memory"] = stats.MemStat()
	writeJsonQuiet(w, r, m)
}
<|endoftext|>


<commit_before>// ships
package main

type ship struct {
	Fatness int
	Numbers int
}

func newShip(F int, N int) ship {
	sh := new(ship)
	sh.Fatness = F
	sh.Numbers = N
	return *sh
}

func allShips() *map[string]ship {
	s := make(map[string]ship)
	s["battleship"] = newShip(4, 1)
	s["cruiser"] = newShip(3, 2)
	s["destroyer"] = newShip(2, 3)
	s["cutter"] = newShip(1, 4)
	return &s
}
<commit_msg>Added field size declaration into game rules<commit_after>// ships
package main

type ship struct {
	Fatness int
	Numbers int
}

func newShip(F int, N int) ship {
	sh := new(ship)
	sh.Fatness = F
	sh.Numbers = N
	return *sh
}

func allShips() *map[string]ship {
	s := make(map[string]ship)
	s["battleship"] = newShip(4, 1)
	s["cruiser"] = newShip(3, 2)
	s["destroyer"] = newShip(2, 3)
	s["cutter"] = newShip(1, 4)
	return &s
}

type rules struct {
	fWid, fLen int
	Ships      *map[string]ship
}

func getRules() (rules, error) {
	var r rules
	r.Ships = allShips()
	r.fWid, r.fLen = 10, 10
	return r, nil
}
<|endoftext|>


<commit_before>package assert

func ShouldPanic(t Exam, fn func()) {
	t.Log("Expecting panic error.")
	defer func() {
		t.Log("Expecting panic error.")
		err := recover()
		t.Log(err)
		if err == nil {
			t.Log("Expected panic occured.")
			t.Fail()
		}
	}()
//	fn()
	t.Log("Expected panic.")
//	t.Fail()
}

func ShouldNotPanic(t Exam, fn func()) {
	defer func() {
		err := recover()
		if err != nil {
			t.Log("Expect func() not to panic.", err)
			t.Fail()
		}
	}()
	fn()
}<commit_msg>Commented out the proper behavior of ShouldPanic.  It's fixed now.<commit_after>package assert

func ShouldPanic(t Exam, fn func()) {
	defer func() {
		t.Log("Expecting panic error.")
		err := recover()
		t.Log(err)
		if err == nil {
			t.Log("Expected panic occured.")
			t.Fail()
		}
	}()
	fn()
	t.Log("Expected panic.")
	t.Fail()
}

func ShouldNotPanic(t Exam, fn func()) {
	defer func() {
		err := recover()
		if err != nil {
			t.Log("Expect func() not to panic.", err)
			t.Fail()
		}
	}()
	fn()
}<|endoftext|>


<commit_before>package api

import (
	"io/ioutil"
	"net/http"

	"github.com/anyweez/matchgrab/config"
	"github.com/anyweez/matchgrab/utils"
)

// Get : Make a request to the Riot API and call the specified function on success.
func Get(url string, cb func(body []byte)) error {
	client := http.Client{
		Timeout: config.Config.HTTPTimeout,
	}

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		utils.Log(err.Error())
		return err
	}
	request.Header.Set("X-Riot-Token", config.Config.RiotAPIKey)

	resp, err := client.Do(request)
	if err != nil {
		return err
	}

	defer resp.Body.Close()
	raw, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	cb(raw)

	return nil
}
<commit_msg>Request and receive gzipped data (no api changes!)<commit_after>package api

import (
	"compress/gzip"
	"io/ioutil"
	"net/http"

	"github.com/anyweez/matchgrab/config"
	"github.com/anyweez/matchgrab/utils"
)

// Get : Make a request to the Riot API and call the specified function on success.
func Get(url string, cb func(body []byte)) error {
	client := http.Client{
		Timeout: config.Config.HTTPTimeout,
	}

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		utils.Log(err.Error())
		return err
	}
	request.Header.Set("X-Riot-Token", config.Config.RiotAPIKey)
	request.Header.Set("Accept-Encoding", "gzip")

	resp, err := client.Do(request)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	// Decode the body first if its gzip'd.
	src := resp.Body
	if resp.Header.Get("Content-Encoding") == "gzip" {
		src, _ = gzip.NewReader(src)
	}

	raw, err := ioutil.ReadAll(src)
	if err != nil {
		return err
	}

	cb(raw)

	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"context"

	"github.com/bytom/errors"
	"github.com/bytom/protocol/bc"
	"github.com/bytom/protocol/bc/types"
)

func (a *API) getWork() Response {
	work, err := a.GetWork()
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(work)
}

func (a *API) getWorkJSON() Response {
	work, err := a.GetWork()
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(work)
}

// SubmitWorkReq used to submitWork req
type SubmitWorkReq struct {
	BlockHeader *types.BlockHeader `json:"block_header"`
}

func (a *API) submitWork(ctx context.Context, req *SubmitWorkReq) Response {
	if err := a.SubmitWork(req.BlockHeader); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(true)
}

func (a *API) submitWorkJSON(ctx context.Context, req *SubmitWorkReq) Response {
	if err := a.SubmitWork(req.BlockHeader); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(true)
}

// GetWorkResp is resp struct for API
type GetWorkResp struct {
	BlockHeader *types.BlockHeader `json:"block_header"`
	Seed        *bc.Hash           `json:"seed"`
}

// GetWork get work
func (a *API) GetWork() (*GetWorkResp, error) {
	bh, err := a.miningPool.GetWork()
	if err != nil {
		return nil, err
	}

	seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
	if err != nil {
		return nil, err
	}

	return &GetWorkResp{
		BlockHeader: bh,
		Seed:        seed,
	}, nil
}

// SubmitWork submit work
func (a *API) SubmitWork(bh *types.BlockHeader) error {
	return a.miningPool.SubmitWork(bh)
}

func (a *API) setMining(in struct {
	IsMining bool `json:"is_mining"`
}) Response {
	if in.IsMining {
		return a.startMining()
	}
	return a.stopMining()
}

func (a *API) startMining() Response {
	a.cpuMiner.Start()
	if !a.IsMining() {
		return NewErrorResponse(errors.New("Failed to start mining"))
	}
	return NewSuccessResponse("")
}

func (a *API) stopMining() Response {
	a.cpuMiner.Stop()
	if a.IsMining() {
		return NewErrorResponse(errors.New("Failed to stop mining"))
	}
	return NewSuccessResponse("")
}
<commit_msg>BlockCommitment for get-work-json<commit_after>package api

import (
	"context"

	"github.com/bytom/errors"
	"github.com/bytom/protocol/bc"
	"github.com/bytom/protocol/bc/types"
)

func (a *API) getWork() Response {
	work, err := a.GetWork()
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(work)
}

func (a *API) getWorkJSON() Response {
	work, err := a.GetWorkJSON()
	if err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(work)
}

// SubmitWorkReq used to submitWork req
type SubmitWorkReq struct {
	BlockHeader *types.BlockHeader `json:"block_header"`
}

func (a *API) submitWork(ctx context.Context, req *SubmitWorkReq) Response {
	if err := a.SubmitWork(req.BlockHeader); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(true)
}

func (a *API) submitWorkJSON(ctx context.Context, req *SubmitWorkReq) Response {
	if err := a.SubmitWork(req.BlockHeader); err != nil {
		return NewErrorResponse(err)
	}
	return NewSuccessResponse(true)
}

// GetWorkResp is resp struct for API
type GetWorkResp struct {
	BlockHeader *types.BlockHeader `json:"block_header"`
	Seed        *bc.Hash           `json:"seed"`
}

// GetWork get work
func (a *API) GetWork() (*GetWorkResp, error) {
	bh, err := a.miningPool.GetWork()
	if err != nil {
		return nil, err
	}

	seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
	if err != nil {
		return nil, err
	}

	return &GetWorkResp{
		BlockHeader: bh,
		Seed:        seed,
	}, nil
}

type BlockHeaderJSON struct {
	Version           uint64 				`json:"version"`  // The version of the block.
	Height            uint64 				`json:"height"`  // The height of the block.
	PreviousBlockHash bc.Hash 				`json:"previous_block_hash"` // The hash of the previous block.
	Timestamp         uint64  				`json:"timestamp"` // The time of the block in seconds.
	Nonce             uint64 				`json:"nonce"` // Nonce used to generate the block.
	Bits              uint64 				`json:"bits"` // Difficulty target for the block.
	BlockCommitment   *types.BlockCommitment `json:"block_commitment"` //Block commitment
}

// GetWorkResp is resp struct for API get-work-json
type GetWorkJSONResp struct {
	BlockHeader *BlockHeaderJSON 	`json:"block_header"`
	Seed        *bc.Hash           	`json:"seed"`
}

// GetWorkJSON get work in json
func (a *API) GetWorkJSON() (*GetWorkJSONResp, error) {
	bh, err := a.miningPool.GetWork()
	if err != nil {
		return nil, err
	}

	seed, err := a.chain.CalcNextSeed(&bh.PreviousBlockHash)
	if err != nil {
		return nil, err
	}

	blockCommitment := &types.BlockCommitment{
							TransactionsMerkleRoot: bh.BlockCommitment.TransactionsMerkleRoot,
							TransactionStatusHash:  bh.BlockCommitment.TransactionStatusHash,
						}

	return &GetWorkJSONResp{
		BlockHeader: &BlockHeaderJSON{
			Version:			bh.Version,
			Height:				bh.Height,
			PreviousBlockHash:	bh.PreviousBlockHash,
			Timestamp:         	bh.Timestamp,
			Nonce:             	bh.Nonce,
			Bits:              	bh.Bits,
			BlockCommitment:	blockCommitment,
		},
		Seed:        seed,
	}, nil
}

// SubmitWork submit work
func (a *API) SubmitWork(bh *types.BlockHeader) error {
	return a.miningPool.SubmitWork(bh)
}

func (a *API) setMining(in struct {
	IsMining bool `json:"is_mining"`
}) Response {
	if in.IsMining {
		return a.startMining()
	}
	return a.stopMining()
}

func (a *API) startMining() Response {
	a.cpuMiner.Start()
	if !a.IsMining() {
		return NewErrorResponse(errors.New("Failed to start mining"))
	}
	return NewSuccessResponse("")
}

func (a *API) stopMining() Response {
	a.cpuMiner.Stop()
	if a.IsMining() {
		return NewErrorResponse(errors.New("Failed to stop mining"))
	}
	return NewSuccessResponse("")
}
<|endoftext|>


<commit_before>package main

import ()

var configuredOauths []string

func oauthConfigure() error {
	configuredOauths = []string{}

	if err := googleOauthConfigure(); err != nil {
		return err
	}

	if err := githubOauthConfigure(); err != nil {
		return err
	}

	if err := twitterOauthConfigure(); err != nil {
		return err
	}

	if err := gitlabOauthConfigure(); err != nil {
		return err
	}

	return nil
}
<commit_msg>oauth.go: re-arrange oauth providers<commit_after>package main

import ()

var configuredOauths []string

func oauthConfigure() error {
	configuredOauths = []string{}

	if err := googleOauthConfigure(); err != nil {
		return err
	}

	if err := twitterOauthConfigure(); err != nil {
		return err
	}

	if err := githubOauthConfigure(); err != nil {
		return err
	}

	if err := gitlabOauthConfigure(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package AuthorizeCIM

import (
	"net/http"
	"bytes"
	"io/ioutil"
	"encoding/json"
	"fmt"
	"time"
)

var api_endpoint string
var apiName string
var apiKey string
var testMode string

var CurrentUser User

func SetAPIInfo(name string, key string, mode string) {
	apiKey = key
	apiName = name
	if mode == "test" {
		testMode = "testMode"
		api_endpoint = "https://apitest.authorize.net/xml/v1/request.api"
	} else {
		testMode = "liveMode"
		api_endpoint = "https://api.authorize.net/xml/v1/request.api"
	}
}

func MakeUser (userID string) User {
	CurrentUser = User{ID: "55", Email: userID, ProfileID: "0"}
	return CurrentUser
}

func CreateCustomerProfile(userInfo AuthUser) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := Profile{MerchantCustomerID: userInfo.Uuid, Description: userInfo.Description, Email: userInfo.Email}
	request := CreateCustomerProfileRequest{authToken, profile}
	newprofile := NewCustomerProfile{request}
	jsoned, _ := json.Marshal(newprofile)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	var new_uuid string
	if success {
		new_uuid = outgoing["customerProfileId"].(string)
		CurrentUser.ProfileID = new_uuid
	} else {
		new_uuid = "0"
	}
	// Delay for Authorize.net
	time.Sleep(3 * time.Second)
	return new_uuid, success
}

func GetCustomerProfile(profileID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := getCustomerProfileRequest{authToken, profileID}
	input := CustomerProfile{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ :=SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	fmt.Println(outgoing)
	userProfile := outgoing["profile"].(map[string]interface{})
	fmt.Println(userProfile)
	return outgoing, success
}

func GetAllProfiles() []interface{} {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profilerequest := getCustomerProfileIdsRequest{authToken}
	all := AllCustomerProfileIds{profilerequest}
	jsoned, _ := json.Marshal(all)
	outgoing, _ :=SendRequest(string(jsoned))
	return outgoing["ids"].([]interface{})
}

func DeleteCustomerProfile(profileID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := deleteCustomerProfileRequest{authToken, profileID}
	input := deleteCustomerProfile{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func CreateCustomerBillingProfile(profileID string, creditCard CreditCard, address Address) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	paymentProfile := PaymentBillingProfile{Address: address, Payment: Payment{CreditCard:creditCard}}
	request := CreateCustomerBillingProfileRequest{authToken, profileID, paymentProfile, testMode}
	newprofile := NewCustomerBillingProfile{request}
	jsoned, _ := json.Marshal(newprofile)
	outgoing, _ :=SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	var new_paymentID string
	if status {
		new_paymentID = outgoing["customerPaymentProfileId"].(string)
	} else {
		new_paymentID = "0"
	}
	// Delay for Authorize.net
	time.Sleep(3 * time.Second)
	return new_paymentID, status
}

func GetCustomerPaymentProfile(profileID string, paymentID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := CustomerPaymentProfileRequest{authToken, profileID, paymentID}
	input := getCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	fmt.Println(CurrentUser)
	return outgoing["paymentProfile"].(map[string]interface{}), success
}

func UpdateCustomerPaymentProfile(profileID string, paymentID string, creditCard CreditCard, address Address) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	new_billing := UpdatePaymentBillingProfile{Address: address, Payment: Payment{CreditCard:creditCard}, CustomerPaymentProfileId: paymentID}
	profile := updateCustomerPaymentProfileRequest{authToken, profileID, new_billing, testMode}
	input := changeCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func DeleteCustomerPaymentProfile(profileID string, paymentID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := deleteCustomerPaymentProfile{authToken, profileID, paymentID}
	input := deleteCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ :=SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func SendRequest(input string) (map[string]interface{}, interface{}) {
	req, err := http.NewRequest("POST", api_endpoint, bytes.NewBuffer([]byte(input)))
	req.Header.Set("Content-Type", "application/json")
	errors := false
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	body = bytes.TrimPrefix(body, []byte("\xef\xbb\xbf"))
	var dat map[string]interface{}
	//fmt.Printf(string(body))
	err = json.Unmarshal(body, &dat)
	if err!=nil {
		panic(err)
	}
	return dat, errors
}

func CreateTransaction(profileID string, paymentID string, item LineItem, amount string) (map[string]interface{}, bool, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	items := LineItems{LineItem: item}
	subProfile := SubProfile{CustomerPaymentProfileId: paymentID}
	transProfile := TranProfile{CustomerProfileId: profileID, SubProfile: subProfile}
	transaction := TransactionRequest{TransactionType: "authCaptureTransaction", Amount: amount, TranProfile: transProfile, LineItems: items}
	tranxrequest := CreateTransactionRequest{MerchantAuthentication: authToken, RefID: "none33", TransactionRequest: transaction}
	doTranx := DoCreateTransaction{tranxrequest}
	jsoned, _ := json.Marshal(doTranx)
	outgoing, _ := SendRequest(string(jsoned))
	var status, approved bool
	var response map[string]interface{}
	transxResponse := outgoing["transactionResponse"].(map[string]interface{})
	if transxResponse["responseCode"]!=nil {
		if transxResponse["responseCode"].(string) != "1" {
			approved = false
			status = true
			response = transxResponse
		} else {
			status = FindResultCode(outgoing)
			approved = TransactionApproved(outgoing)
			response = outgoing["transactionResponse"].(map[string]interface{})
		}
	} else {
		approved = false
		status = false
		response = map[string]interface{}{}
	}

	return response, approved, status
}

func TestConnection() bool {
	authToken := AuthenticateTestRequest{MerchantAuthentication{Name: apiName, TransactionKey: apiKey}}
	authnettest := AuthorizeNetTest{AuthenticateTestRequest:authToken}
	jsoned, _ := json.Marshal(authnettest)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func CreateShippingAddress(profileID string, address Address) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := CustomerShippingAddress{authToken,profileID,address}
	customerShippingRequest := CustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	var new_address_id string
	if !success {
		new_address_id = "0"
	} else {
		new_address_id = outgoing["customerAddressId"].(string)
	}
	// Delay for Authorize.net
	time.Sleep(3 * time.Second)
	return new_address_id, success
}

func GetShippingAddress(profileID string, shippingID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := GetCustomerShippingAddress{authToken,profileID,shippingID}
	customerShippingRequest := GetCustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	return outgoing["address"].(map[string]interface{}), success
}

func DeleteShippingAddress(profileID string, shippingID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := GetCustomerShippingAddress{authToken,profileID,shippingID}
	customerShippingRequest := DeleteCustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func GetTransactionDetails(tranID string) map[string]interface{} {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	transDetails := TransactionDetails{authToken,tranID}
	transactionRequest := TransactionDetailsRequest{transDetails}
	jsoned, _ := json.Marshal(transactionRequest)
	outgoing, _ := SendRequest(string(jsoned))
	if outgoing["transaction"]!=nil {
		return outgoing["transaction"].(map[string]interface{})
	}
	return map[string]interface{}{}
}

func FindResultCode(incoming map[string]interface{}) bool {
	messages, _ := incoming["messages"].(map[string]interface{})
	if messages!=nil {
		if messages["resultCode"] == "Ok" {
			return true
		}
	}
	return false
}

func TransactionApproved(incoming map[string]interface{}) bool {
	if incoming!=nil {
		messages, _ := incoming["transactionResponse"].(map[string]interface{})
		if messages["responseCode"] == "1" {
			return true
		}
	}
	return false
}

func CreateSubscription(newSubscription Subscription) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	subscriptonSubmit := CreateSubscriptionRequest{ARBCreateSubscription{authToken, newSubscription}}
	jsoned, _ := json.Marshal(subscriptonSubmit)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	if status {
		return outgoing["subscriptionId"].(string), status
	}
	return "0", status
}

func RefundTransactions(){

}

func VoidTransaction(){

}

func DeleteSubscription(){

}

func UpdateSubscription(){

}

func GetSubscriptions(){

}

<commit_msg>errors on nil profiles<commit_after>package AuthorizeCIM

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

var api_endpoint string
var apiName string
var apiKey string
var testMode string

var CurrentUser User

func SetAPIInfo(name string, key string, mode string) {
	apiKey = key
	apiName = name
	if mode == "test" {
		testMode = "testMode"
		api_endpoint = "https://apitest.authorize.net/xml/v1/request.api"
	} else {
		testMode = "liveMode"
		api_endpoint = "https://api.authorize.net/xml/v1/request.api"
	}
}

func MakeUser (userID string) User {
	CurrentUser = User{ID: "55", Email: userID, ProfileID: "0"}
	return CurrentUser
}

func CreateCustomerProfile(userInfo AuthUser) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := Profile{MerchantCustomerID: userInfo.Uuid, Description: userInfo.Description, Email: userInfo.Email}
	request := CreateCustomerProfileRequest{authToken, profile}
	newprofile := NewCustomerProfile{request}
	jsoned, _ := json.Marshal(newprofile)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	var new_uuid string
	if success {
		new_uuid = outgoing["customerProfileId"].(string)
		CurrentUser.ProfileID = new_uuid
	} else {
		new_uuid = "0"
	}
	return new_uuid, success
}

func GetCustomerProfile(profileID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := getCustomerProfileRequest{authToken, profileID}
	input := CustomerProfile{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ :=SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	if outgoing["profile"]==nil {
		return nil, success
	} else {
		userProfile := outgoing["profile"].(map[string]interface{})
		return userProfile, success
	}
}

func GetAllProfiles() []interface{} {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profilerequest := getCustomerProfileIdsRequest{authToken}
	all := AllCustomerProfileIds{profilerequest}
	jsoned, _ := json.Marshal(all)
	outgoing, _ :=SendRequest(string(jsoned))
	return outgoing["ids"].([]interface{})
}

func DeleteCustomerProfile(profileID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := deleteCustomerProfileRequest{authToken, profileID}
	input := deleteCustomerProfile{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func CreateCustomerBillingProfile(profileID string, creditCard CreditCard, address Address) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	paymentProfile := PaymentBillingProfile{Address: address, Payment: Payment{CreditCard:creditCard}}
	request := CreateCustomerBillingProfileRequest{authToken, profileID, paymentProfile, testMode}
	newprofile := NewCustomerBillingProfile{request}
	jsoned, _ := json.Marshal(newprofile)
	outgoing, _ :=SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	var new_paymentID string
	if status {
		new_paymentID = outgoing["customerPaymentProfileId"].(string)
	} else {
		new_paymentID = "0"
	}
	return new_paymentID, status
}

func GetCustomerPaymentProfile(profileID string, paymentID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := CustomerPaymentProfileRequest{authToken, profileID, paymentID}
	input := getCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	fmt.Println(CurrentUser)
	return outgoing["paymentProfile"].(map[string]interface{}), success
}

func UpdateCustomerPaymentProfile(profileID string, paymentID string, creditCard CreditCard, address Address) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	new_billing := UpdatePaymentBillingProfile{Address: address, Payment: Payment{CreditCard:creditCard}, CustomerPaymentProfileId: paymentID}
	profile := updateCustomerPaymentProfileRequest{authToken, profileID, new_billing, testMode}
	input := changeCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func DeleteCustomerPaymentProfile(profileID string, paymentID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	profile := deleteCustomerPaymentProfile{authToken, profileID, paymentID}
	input := deleteCustomerPaymentProfileRequest{profile}
	jsoned, _ := json.Marshal(input)
	outgoing, _ :=SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func SendRequest(input string) (map[string]interface{}, interface{}) {
	req, err := http.NewRequest("POST", api_endpoint, bytes.NewBuffer([]byte(input)))
	req.Header.Set("Content-Type", "application/json")
	errors := false
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	body = bytes.TrimPrefix(body, []byte("\xef\xbb\xbf"))
	var dat map[string]interface{}
	//fmt.Printf(string(body))
	err = json.Unmarshal(body, &dat)
	if err!=nil {
		panic(err)
	}
	return dat, errors
}

func CreateTransaction(profileID string, paymentID string, item LineItem, amount string) (map[string]interface{}, bool, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	items := LineItems{LineItem: item}
	subProfile := SubProfile{CustomerPaymentProfileId: paymentID}
	transProfile := TranProfile{CustomerProfileId: profileID, SubProfile: subProfile}
	transaction := TransactionRequest{TransactionType: "authCaptureTransaction", Amount: amount, TranProfile: transProfile, LineItems: items}
	tranxrequest := CreateTransactionRequest{MerchantAuthentication: authToken, RefID: "none33", TransactionRequest: transaction}
	doTranx := DoCreateTransaction{tranxrequest}
	jsoned, _ := json.Marshal(doTranx)
	outgoing, _ := SendRequest(string(jsoned))
	var status, approved bool
	var response map[string]interface{}
	transxResponse := outgoing["transactionResponse"].(map[string]interface{})
	if transxResponse["responseCode"]!=nil {
		if transxResponse["responseCode"].(string) != "1" {
			approved = false
			status = true
			response = transxResponse
		} else {
			status = FindResultCode(outgoing)
			approved = TransactionApproved(outgoing)
			response = outgoing["transactionResponse"].(map[string]interface{})
		}
	} else {
		approved = false
		status = false
		response = map[string]interface{}{}
	}

	return response, approved, status
}

func TestConnection() bool {
	authToken := AuthenticateTestRequest{MerchantAuthentication{Name: apiName, TransactionKey: apiKey}}
	authnettest := AuthorizeNetTest{AuthenticateTestRequest:authToken}
	jsoned, _ := json.Marshal(authnettest)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func CreateShippingAddress(profileID string, address Address) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := CustomerShippingAddress{authToken,profileID,address}
	customerShippingRequest := CustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	var new_address_id string
	if !success {
		new_address_id = "0"
	} else {
		new_address_id = outgoing["customerAddressId"].(string)
	}
	return new_address_id, success
}

func GetShippingAddress(profileID string, shippingID string) (map[string]interface{}, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := GetCustomerShippingAddress{authToken,profileID,shippingID}
	customerShippingRequest := GetCustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	success := FindResultCode(outgoing)
	return outgoing["address"].(map[string]interface{}), success
}

func DeleteShippingAddress(profileID string, shippingID string) bool {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	customerShipping := GetCustomerShippingAddress{authToken,profileID,shippingID}
	customerShippingRequest := DeleteCustomerShippingAddressRequest{customerShipping}
	jsoned, _ := json.Marshal(customerShippingRequest)
	outgoing, _ := SendRequest(string(jsoned))
	status := FindResultCode(outgoing)
	return status
}

func GetTransactionDetails(tranID string) map[string]interface{} {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	transDetails := TransactionDetails{authToken,tranID}
	transactionRequest := TransactionDetailsRequest{transDetails}
	jsoned, _ := json.Marshal(transactionRequest)
	outgoing, _ := SendRequest(string(jsoned))
	if outgoing["transaction"]!=nil {
		return outgoing["transaction"].(map[string]interface{})
	}
	return map[string]interface{}{}
}

func FindResultCode(incoming map[string]interface{}) bool {
	messages, _ := incoming["messages"].(map[string]interface{})
	if messages!=nil {
		if messages["resultCode"] == "Ok" {
			return true
		}
	}
	return false
}

func TransactionApproved(incoming map[string]interface{}) bool {
	if incoming!=nil {
		messages, _ := incoming["transactionResponse"].(map[string]interface{})
		if messages["responseCode"] == "1" {
			return true
		}
	}
	return false
}

func CreateSubscription(newSubscription Subscription) (string, bool) {
	authToken := MerchantAuthentication{Name: apiName, TransactionKey: apiKey}
	subscriptonSubmit := CreateSubscriptionRequest{ARBCreateSubscription{authToken, newSubscription}}
	jsoned, _ := json.Marshal(subscriptonSubmit)
	outgoing, _ := SendRequest(string(jsoned))
	fmt.Println(outgoing)
	status := FindResultCode(outgoing)
	if status {
		return outgoing["subscriptionId"].(string), status
	}
	return "0", status
}

func RefundTransactions(){

}

func VoidTransaction(){

}

func DeleteSubscription(){

}

func UpdateSubscription(){

}

func GetSubscriptions(){

}

<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/rs/cors"
	"log"
	"net/http"
)

type State struct {
	Users        map[uuid.UUID]User `json:"users"`         // All participators at the student division meeting.
	SpeakerLists [][]User           `json:"speakersLists"` // A list of speakerLists where each index is a list of sessions in queue to speak
}

type User struct {
	Nick    string `json:"nick"`
	IsAdmin bool   `json:"isAdmin"`
	id      uuid.UUID
	session *sessions.Session
}

const SESSION_KEY = "talarlista_session"

var store = sessions.NewCookieStore([]byte("this is the secret stuff"))
var state State

func listHandler(w http.ResponseWriter, req *http.Request) {
	log.Print("Listhandler begin")
	session, err := store.Get(req, SESSION_KEY)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	session.Save(req, w)

	log.Printf("Session is new %v\n", session.IsNew)
	if session.IsNew {
		var id = uuid.New()
		session.Values["UUID"] = id
		log.Printf("New user id: %v\n", id)

		state.addUser(User{"", false, id, session})
		log.Printf("State with new user: %v", state)
	}

	session.Options = &sessions.Options{ // should this be done inside the previous if-statement?
		MaxAge:   86400,
		HttpOnly: true,
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Origin", "*")

	user, err := state.getUserFromSession(session)
	if err != nil {
		log.Printf("listHandler: Could not get user from session %v\n", err)
	}
	log.Printf("User: %v\n", user)
	switch req.Method {
	case http.MethodGet:
		listGet(w)
	case http.MethodPost:
		listPost(w, user)
	case http.MethodDelete:
		listDelete(w, user)
	default:
		w.Write([]byte("List unsupported method.\n"))
		log.Print("Unsupported method")
	}
}

func getUUIDfromSession(session *sessions.Session) (uuid.UUID, error) {
	storedId, ok := session.Values["UUID"]
	if !ok {
		return uuid.UUID{}, errors.New("Could not find user from session-stored UUID")
	}

	id, ok := storedId.(uuid.UUID)
	if !ok {
		return uuid.UUID{}, errors.New("Could not cast storedId to uuid.UUID")
	}

	return id, nil
}

func (s State) getUserFromSession(session *sessions.Session) (User, error) {
	id, err := getUUIDfromSession(session)

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

	return s.getUser(id)
}

func (s State) getUser(id uuid.UUID) (User, error) {
	user, ok := s.Users[id]

	if !ok {
		return User{}, errors.New("Could not find user")
	}
	return user, nil
}

func (s State) addUser(user User) bool {
	_, ok := s.Users[user.id]
	if ok {
		return false
	}
	s.Users[user.id] = user
	return true
}

func (s *State) updateUser(session *sessions.Session, user User) bool {

	id, err := getUUIDfromSession(session)

	if err != nil {
		log.Printf("Could not get UUID from session %v\n", err)
		return false
	}

	user, ok := s.Users[id]
	if ok {
		log.Printf("Could not find user when updating: sessionId: \"%s\"", id)
		return false
	}
	user.Nick = user.Nick

	s.Users[id] = user
	//*(s.Users[session.ID]) = user.Nick
	return true
}

func listGet(w http.ResponseWriter) {
	b, err := json.Marshal(state.SpeakerLists)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(b)
}

func listPost(w http.ResponseWriter, user User) {
	currentSpeakerList := state.SpeakerLists[len(state.SpeakerLists)-1]

	if isRegistered(user, currentSpeakerList) {
		http.Error(w, "{\"status\": \"already registered\"}", http.StatusUnprocessableEntity)
		return
	}
	// TODO check for name. A user needs a unique name to get to participate in a speakerList
	state.SpeakerLists[len(state.SpeakerLists)-1] = append(currentSpeakerList, user)
	w.Write([]byte("{\"status\": \"added\"}"))

}

func listDelete(w http.ResponseWriter, user User) {
	currentSpeakerList := state.SpeakerLists[len(state.SpeakerLists)-1]
	if isRegistered(user, currentSpeakerList) {
		state.SpeakerLists[len(state.SpeakerLists)-1] = removeUserFromList(user, currentSpeakerList)
		w.Write([]byte("{\"status\": \"removed\"}"))
	} else {
		http.Error(w, "{\"status\": \"not in a list\"}", http.StatusUnprocessableEntity)
		return
	}
}

func isRegistered(currentUser User, speakersList []User) bool {
	for _, user := range speakersList {
		if currentUser.id == user.id {
			return true
		}
	}
	return false
}

func removeUserFromList(user User, userList []User) []User {
	userIndex := -1
	for i, s := range userList {
		if user.id == s.id {
			userIndex = i
			break
		}
	}

	if userIndex == -1 {
		return userList
	} else {
		return append(userList[:userIndex], userList[userIndex+1:]...)
	}
}

func adminHandler(w http.ResponseWriter, req *http.Request) {

	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("helo\n"))
}

func userHandler(w http.ResponseWriter, req *http.Request) {
	session, err := store.Get(req, SESSION_KEY)
	fmt.Printf("Session: %s\n", session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if req.Method == http.MethodGet {
		user, err := state.getUserFromSession(session)
		if err != nil {
			log.Printf("Could not get user from session %v\n", err)
			//TODO add http error
			return
		}

		bytes, err := json.Marshal(user)
		w.Header().Set("Content-Type", "application/json")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		} else {
			w.Write(bytes)
		}
	} else if req.Method == http.MethodPost {

		var dat User
		decodeErr := json.NewDecoder(req.Body).Decode(&dat)
		if decodeErr != nil {
			log.Printf("Could not decode data %v\n", decodeErr)
		}

		ok := state.updateUser(session, dat)
		if !ok {
			log.Print("Could not update user data")
			w.Write([]byte("{\"status\":\"fail\"}"))
		} else {
			w.Write([]byte("{\"status\":\"success\"}"))
		}
	}
}

func main() {
	state.SpeakerLists = append(state.SpeakerLists, []User{})
	state.Users = make(map[uuid.UUID]User)

	mux := http.NewServeMux()
	mux.HandleFunc("/", listHandler)
	mux.HandleFunc("/list", listHandler)
	mux.HandleFunc("/admin", adminHandler)
	mux.HandleFunc("/me", userHandler)

	handler := cors.Default().Handler(mux)

	c := cors.New(cors.Options{
		//Debug: true,
		AllowedMethods: []string{"GET", "POST", "DELETE"},
	})
	handler = c.Handler(handler)

	handler = context.ClearHandler(handler)

	log.Print("About to listen on 3001. Go to http://127.0.0.1:3001/")
	//err := http.ListenAndServeTLS(":3001", "cert.pem", "key.pem", nil)
	err := http.ListenAndServe(":3001", handler)
	log.Fatal(err)
}
<commit_msg>Extract UUID to constant<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"github.com/rs/cors"
	"log"
	"net/http"
)

type State struct {
	Users        map[uuid.UUID]User `json:"users"`         // All participators at the student division meeting.
	SpeakerLists [][]User           `json:"speakersLists"` // A list of speakerLists where each index is a list of sessions in queue to speak
}

type User struct {
	Nick    string `json:"nick"`
	IsAdmin bool   `json:"isAdmin"`
	id      uuid.UUID
	session *sessions.Session
}

const SESSION_KEY = "talarlista_session"
const UUID_KEY = "uuid"

var store = sessions.NewCookieStore([]byte("this is the secret stuff"))
var state State

func listHandler(w http.ResponseWriter, req *http.Request) {
	log.Print("Listhandler begin")
	session, err := store.Get(req, SESSION_KEY)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	session.Save(req, w)

	log.Printf("Session is new %v\n", session.IsNew)
	if session.IsNew {
		var id = uuid.New()
		session.Values[UUID_KEY] = id
		log.Printf("New user id: %v\n", id)

		state.addUser(User{"", false, id, session})
		log.Printf("State with new user: %v", state)
	}

	session.Options = &sessions.Options{ // should this be done inside the previous if-statement?
		MaxAge:   86400,
		HttpOnly: true,
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Access-Control-Allow-Origin", "*")

	user, err := state.getUserFromSession(session)
	if err != nil {
		log.Printf("listHandler: Could not get user from session %v\n", err)
	}
	log.Printf("User: %v\n", user)
	switch req.Method {
	case http.MethodGet:
		listGet(w)
	case http.MethodPost:
		listPost(w, user)
	case http.MethodDelete:
		listDelete(w, user)
	default:
		w.Write([]byte("List unsupported method.\n"))
		log.Print("Unsupported method")
	}
}

func getUUIDfromSession(session *sessions.Session) (uuid.UUID, error) {
	storedId, ok := session.Values[UUID_KEY]
	if !ok {
		return uuid.UUID{}, errors.New("Could not find user from session-stored UUID")
	}

	id, ok := storedId.(uuid.UUID)
	if !ok {
		return uuid.UUID{}, errors.New("Could not cast storedId to uuid.UUID")
	}

	return id, nil
}

func (s State) getUserFromSession(session *sessions.Session) (User, error) {
	id, err := getUUIDfromSession(session)

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

	return s.getUser(id)
}

func (s State) getUser(id uuid.UUID) (User, error) {
	user, ok := s.Users[id]

	if !ok {
		return User{}, errors.New("Could not find user")
	}
	return user, nil
}

func (s State) addUser(user User) bool {
	_, ok := s.Users[user.id]
	if ok {
		return false
	}
	s.Users[user.id] = user
	return true
}

func (s *State) updateUser(session *sessions.Session, user User) bool {

	id, err := getUUIDfromSession(session)

	if err != nil {
		log.Printf("Could not get UUID from session %v\n", err)
		return false
	}

	user, ok := s.Users[id]
	if ok {
		log.Printf("Could not find user when updating: sessionId: \"%s\"", id)
		return false
	}
	user.Nick = user.Nick

	s.Users[id] = user
	//*(s.Users[session.ID]) = user.Nick
	return true
}

func listGet(w http.ResponseWriter) {
	b, err := json.Marshal(state.SpeakerLists)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(b)
}

func listPost(w http.ResponseWriter, user User) {
	currentSpeakerList := state.SpeakerLists[len(state.SpeakerLists)-1]

	if isRegistered(user, currentSpeakerList) {
		http.Error(w, "{\"status\": \"already registered\"}", http.StatusUnprocessableEntity)
		return
	}
	// TODO check for name. A user needs a unique name to get to participate in a speakerList
	state.SpeakerLists[len(state.SpeakerLists)-1] = append(currentSpeakerList, user)
	w.Write([]byte("{\"status\": \"added\"}"))

}

func listDelete(w http.ResponseWriter, user User) {
	currentSpeakerList := state.SpeakerLists[len(state.SpeakerLists)-1]
	if isRegistered(user, currentSpeakerList) {
		state.SpeakerLists[len(state.SpeakerLists)-1] = removeUserFromList(user, currentSpeakerList)
		w.Write([]byte("{\"status\": \"removed\"}"))
	} else {
		http.Error(w, "{\"status\": \"not in a list\"}", http.StatusUnprocessableEntity)
		return
	}
}

func isRegistered(currentUser User, speakersList []User) bool {
	for _, user := range speakersList {
		if currentUser.id == user.id {
			return true
		}
	}
	return false
}

func removeUserFromList(user User, userList []User) []User {
	userIndex := -1
	for i, s := range userList {
		if user.id == s.id {
			userIndex = i
			break
		}
	}

	if userIndex == -1 {
		return userList
	} else {
		return append(userList[:userIndex], userList[userIndex+1:]...)
	}
}

func adminHandler(w http.ResponseWriter, req *http.Request) {

	w.Header().Set("Content-Type", "text/plain")
	w.Write([]byte("helo\n"))
}

func userHandler(w http.ResponseWriter, req *http.Request) {
	session, err := store.Get(req, SESSION_KEY)
	fmt.Printf("Session: %s\n", session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if req.Method == http.MethodGet {
		user, err := state.getUserFromSession(session)
		if err != nil {
			log.Printf("Could not get user from session %v\n", err)
			//TODO add http error
			return
		}

		bytes, err := json.Marshal(user)
		w.Header().Set("Content-Type", "application/json")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		} else {
			w.Write(bytes)
		}
	} else if req.Method == http.MethodPost {

		var dat User
		decodeErr := json.NewDecoder(req.Body).Decode(&dat)
		if decodeErr != nil {
			log.Printf("Could not decode data %v\n", decodeErr)
		}

		ok := state.updateUser(session, dat)
		if !ok {
			log.Print("Could not update user data")
			w.Write([]byte("{\"status\":\"fail\"}"))
		} else {
			w.Write([]byte("{\"status\":\"success\"}"))
		}
	}
}

func main() {
	state.SpeakerLists = append(state.SpeakerLists, []User{})
	state.Users = make(map[uuid.UUID]User)

	mux := http.NewServeMux()
	mux.HandleFunc("/", listHandler)
	mux.HandleFunc("/list", listHandler)
	mux.HandleFunc("/admin", adminHandler)
	mux.HandleFunc("/me", userHandler)

	handler := cors.Default().Handler(mux)

	c := cors.New(cors.Options{
		//Debug: true,
		AllowedMethods: []string{"GET", "POST", "DELETE"},
	})
	handler = c.Handler(handler)

	handler = context.ClearHandler(handler)

	log.Print("About to listen on 3001. Go to http://127.0.0.1:3001/")
	//err := http.ListenAndServeTLS(":3001", "cert.pem", "key.pem", nil)
	err := http.ListenAndServe(":3001", handler)
	log.Fatal(err)
}
<|endoftext|>


<commit_before>package app

type Model struct {
	metadata  *Metadata
	index     int
	clipboard map[string]string
	Observable
}

func NewModel() *Model {
	return new(Model)
}

func (m *Model) LoadPath(path string) {
	if m.HaveMetadata() && m.metadata.HasRunningBackup() {
		close(m.metadata.QuitBackup) // Stop old backup routine
	}

	m.metadata = NewMetadata(path)
	m.index = 0
	m.Publish("path", path)
	m.updateGallery()
}

func (m *Model) ImagePath() string {
	return m.metadata.ImagePath(m.index)
}

func (m *Model) Copy(buffer map[string]string) {
	m.clipboard = buffer
}

func (m *Model) Paste() {
	for key, value := range m.clipboard {
		m.Publish("image_"+key, value)
	}
}

func (m *Model) NextImage() {
	m.index += 1
	m.updateGallery()
}

func (m *Model) PreviousImage() {
	m.index -= 1
	m.updateGallery()
}

func (m *Model) HaveMetadata() bool {
	return m.metadata != nil
}

func (m *Model) IsIndexValid(action string) bool {
	index := m.index
	switch action {
	case "previous":
		index -= 1
	case "next":
		index += 1
	}
	return index > -1 && index < m.metadata.NbOfImages()
}

func (m *Model) UpdateAttributes(kind string, value map[string]string) {
	switch kind {
	case "gallery_headers":
		m.metadata.UpdateAttributes(value, -666)
	case "image":
		m.metadata.UpdateAttributes(value, m.index)
	}
}

func (m *Model) Generate() {
	m.metadata.Generate()
}

func (m *Model) updateGallery() {
	for key, value := range m.metadata.GalleryHeaders() {
		m.Publish("gallery_"+key, value)
	}
	for key, value := range m.metadata.Image(m.index) {
		m.Publish("image_"+key, value)
	}
}
<commit_msg>Fix crash when selected directory does not have images<commit_after>package app

type Model struct {
	metadata  *Metadata
	index     int
	clipboard map[string]string
	Observable
}

func NewModel() *Model {
	return new(Model)
}

func (m *Model) LoadPath(path string) {
	if m.HaveMetadata() && m.metadata.HasRunningBackup() {
		close(m.metadata.QuitBackup) // Stop old backup routine
	}

	m.metadata = NewMetadata(path)
	m.index = 0
	m.Publish("path", path)
	if m.metadata.NbOfImages() > 0 {
		m.updateGallery()
	}
}

func (m *Model) ImagePath() string {
	return m.metadata.ImagePath(m.index)
}

func (m *Model) Copy(buffer map[string]string) {
	m.clipboard = buffer
}

func (m *Model) Paste() {
	for key, value := range m.clipboard {
		m.Publish("image_"+key, value)
	}
}

func (m *Model) NextImage() {
	m.index += 1
	m.updateGallery()
}

func (m *Model) PreviousImage() {
	m.index -= 1
	m.updateGallery()
}

func (m *Model) HaveMetadata() bool {
	return m.metadata != nil
}

func (m *Model) IsIndexValid(action string) bool {
	index := m.index
	switch action {
	case "previous":
		index -= 1
	case "next":
		index += 1
	}
	return index > -1 && index < m.metadata.NbOfImages()
}

func (m *Model) UpdateAttributes(kind string, value map[string]string) {
	switch kind {
	case "gallery_headers":
		m.metadata.UpdateAttributes(value, -666)
	case "image":
		m.metadata.UpdateAttributes(value, m.index)
	}
}

func (m *Model) Generate() {
	m.metadata.Generate()
}

func (m *Model) updateGallery() {
	for key, value := range m.metadata.GalleryHeaders() {
		m.Publish("gallery_"+key, value)
	}
	for key, value := range m.metadata.Image(m.index) {
		m.Publish("image_"+key, value)
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"database/sql"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// A Player with some useful data.
type ExtPlayer struct {
	// The Id of the player (uuid).
	Id string

	// The name of the player.
	Name string

	// The minimum rating from the player.
	Min int

	// The maximum rating from the player.
	Max int

	// The average rating from the player.
	Avg string

	// All the ratings from this player.
	Ratings []Rating

	// The date of creation of this player.
	Created_at time.Time
}

// Returns a string containing the creepy SQL statement to be executed in
// order to obtain the stats of a player.
func statsQuery(one bool) string {
	q := `
        SELECT p.id, p.name, min(r.value), max(r.value), avg(r.value),
            array_agg(r.value ORDER BY r.created_at) as values,
            array_agg(r.created_at ORDER BY r.created_at)
        FROM players p
        LEFT JOIN ratings r ON p.id = r.player_id
    `
	if one {
		q += " WHERE p.id = $1"
	}
	q += " GROUP BY p.id, p.name ORDER BY p.name"
	return q
}

// Returns the inner values of a PostgreSQL's array_agg.
func parseAgg(agg string) []string {
	clean := strings.TrimPrefix(agg, "{")
	clean = strings.TrimRight(clean, "}")

	// Left joins might set nil values to "{NULL}".
	if clean == "NULL" {
		return []string{}
	}
	return strings.Split(clean, ",")
}

// Returns three integers that are inside the given string. This given string
// is basically a set of integers separated by the given sep value.
func mustAtoi(str, sep string) (int, int, int) {
	// Left joins might set nil values to "NULL".
	if str == "" || str == "NULL" {
		return -1, -1, -1
	}

	vals := strings.SplitN(str, sep, 3)
	first, _ := strconv.Atoi(vals[0])
	second, _ := strconv.Atoi(vals[1])
	third, _ := strconv.Atoi(vals[2])
	return first, second, third
}

// Parse a date from a PostgreSQL's timestamp. PostgreSQL's timestamps have the
// following format: 2014-05-15 21:41:21.1234
func parseDate(complete string) time.Time {
	// Left joins might set nil values to "NULL".
	if complete == "" || complete == "NULL" {
		return time.Now()
	}

	complete = strings.TrimPrefix(complete, "\"")
	complete = strings.TrimSuffix(complete, "\"")

	spd := strings.SplitN(complete, " ", 2)
	y, mo, d := mustAtoi(spd[0], "-")
	hour := strings.SplitN(spd[1], ".", 2)
	h, m, s := mustAtoi(hour[0], ":")
	n, _ := strconv.Atoi(hour[1])
	return time.Date(y, time.Month(mo), d, h, m, s, n, time.UTC)
}

// Returns a list of ratings that can be extracted from the given values and
// dates. These values and dates are in PostgreSQL's array_agg format.
func parseRatings(values, dates string) []Rating {
	ratings := []Rating{}
	vls := parseAgg(values)
	d := parseAgg(dates)

	for i := 0; i < len(vls); i += 1 {
		v, _ := strconv.Atoi(vls[i])
		t := parseDate(d[i])

		nr := Rating{
			Id:         0, // We don't care.
			Value:      v,
			Player_id:  "", // We don't care.
			Created_at: t,
		}
		ratings = append(ratings, nr)
	}
	return ratings
}

// This function fetches the statistics of the required players. If the "one"
// parameter is set to true, then it's interpreted that the player to be
// fetched has the ID given by the playerId parameter. Otherwise, if the "one"
// parameter is set to false, then the playerId parameter will be ignored and
// all the users that have rated a practice at least once will be fetched.
//
// Returns the list of the fetched players plus an integer value. This integer
// value represents the maximum number of practices that the selected players
// have rated.
func getStats(playerId string, one bool) ([]*ExtPlayer, int) {
	var rows *sql.Rows

	// Prepare the query.
	q := statsQuery(one)
	if one {
		rows, _ = Db.Db.Query(q, playerId)
	} else {
		rows, _ = Db.Db.Query(q)
	}

	// And fetch the players and their ratings.
	rmax := 0
	players := []*ExtPlayer{}
	for rows.Next() {
		var id, name, values, dates string
		var min, max *int
		var avg *float64

		if ed := rows.Scan(&id, &name, &min, &max, &avg, &values, &dates); ed == nil {
			ratings := parseRatings(values, dates)
			p := &ExtPlayer{Id: id, Name: name, Ratings: ratings}

			if l := len(ratings); l > 0 {
				p.Min, p.Max, p.Avg = *min, *max, fmt.Sprintf("%0.2f", *avg)
				if l > rmax {
					rmax = len(ratings)
				}
			}
			players = append(players, p)
		}
	}
	return players, rmax
}
<commit_msg>app: protect from invalid id values.<commit_after>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"database/sql"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// A Player with some useful data.
type ExtPlayer struct {
	// The Id of the player (uuid).
	Id string

	// The name of the player.
	Name string

	// The minimum rating from the player.
	Min int

	// The maximum rating from the player.
	Max int

	// The average rating from the player.
	Avg string

	// All the ratings from this player.
	Ratings []Rating

	// The date of creation of this player.
	Created_at time.Time
}

// Returns a string containing the creepy SQL statement to be executed in
// order to obtain the stats of a player.
func statsQuery(one bool) string {
	q := `
        SELECT p.id, p.name, min(r.value), max(r.value), avg(r.value),
            array_agg(r.value ORDER BY r.created_at) as values,
            array_agg(r.created_at ORDER BY r.created_at)
        FROM players p
        LEFT JOIN ratings r ON p.id = r.player_id
    `
	if one {
		q += " WHERE p.id = $1"
	}
	q += " GROUP BY p.id, p.name ORDER BY p.name"
	return q
}

// Returns the inner values of a PostgreSQL's array_agg.
func parseAgg(agg string) []string {
	clean := strings.TrimPrefix(agg, "{")
	clean = strings.TrimRight(clean, "}")

	// Left joins might set nil values to "{NULL}".
	if clean == "NULL" {
		return []string{}
	}
	return strings.Split(clean, ",")
}

// Returns three integers that are inside the given string. This given string
// is basically a set of integers separated by the given sep value.
func mustAtoi(str, sep string) (int, int, int) {
	// Left joins might set nil values to "NULL".
	if str == "" || str == "NULL" {
		return -1, -1, -1
	}

	vals := strings.SplitN(str, sep, 3)
	first, _ := strconv.Atoi(vals[0])
	second, _ := strconv.Atoi(vals[1])
	third, _ := strconv.Atoi(vals[2])
	return first, second, third
}

// Parse a date from a PostgreSQL's timestamp. PostgreSQL's timestamps have the
// following format: 2014-05-15 21:41:21.1234
func parseDate(complete string) time.Time {
	// Left joins might set nil values to "NULL".
	if complete == "" || complete == "NULL" {
		return time.Now()
	}

	complete = strings.TrimPrefix(complete, "\"")
	complete = strings.TrimSuffix(complete, "\"")

	spd := strings.SplitN(complete, " ", 2)
	y, mo, d := mustAtoi(spd[0], "-")
	hour := strings.SplitN(spd[1], ".", 2)
	h, m, s := mustAtoi(hour[0], ":")
	n, _ := strconv.Atoi(hour[1])
	return time.Date(y, time.Month(mo), d, h, m, s, n, time.UTC)
}

// Returns a list of ratings that can be extracted from the given values and
// dates. These values and dates are in PostgreSQL's array_agg format.
func parseRatings(values, dates string) []Rating {
	ratings := []Rating{}
	vls := parseAgg(values)
	d := parseAgg(dates)

	for i := 0; i < len(vls); i += 1 {
		v, _ := strconv.Atoi(vls[i])
		t := parseDate(d[i])

		nr := Rating{
			Id:         0, // We don't care.
			Value:      v,
			Player_id:  "", // We don't care.
			Created_at: t,
		}
		ratings = append(ratings, nr)
	}
	return ratings
}

// This function fetches the statistics of the required players. If the "one"
// parameter is set to true, then it's interpreted that the player to be
// fetched has the ID given by the playerId parameter. Otherwise, if the "one"
// parameter is set to false, then the playerId parameter will be ignored and
// all the users that have rated a practice at least once will be fetched.
//
// Returns the list of the fetched players plus an integer value. This integer
// value represents the maximum number of practices that the selected players
// have rated.
func getStats(playerId string, one bool) ([]*ExtPlayer, int) {
	var rows *sql.Rows
	var err error

	// Prepare the query.
	q := statsQuery(one)
	if one {
		rows, err = Db.Db.Query(q, playerId)
	} else {
		rows, err = Db.Db.Query(q)
	}
	if err != nil {
		return []*ExtPlayer{}, 0
	}

	// And fetch the players and their ratings.
	rmax := 0
	players := []*ExtPlayer{}
	for rows.Next() {
		var id, name, values, dates string
		var min, max *int
		var avg *float64

		if ed := rows.Scan(&id, &name, &min, &max, &avg, &values, &dates); ed == nil {
			ratings := parseRatings(values, dates)
			p := &ExtPlayer{Id: id, Name: name, Ratings: ratings}

			if l := len(ratings); l > 0 {
				p.Min, p.Max, p.Avg = *min, *max, fmt.Sprintf("%0.2f", *avg)
				if l > rmax {
					rmax = len(ratings)
				}
			}
			players = append(players, p)
		}
	}
	return players, rmax
}
<|endoftext|>


<commit_before>//Copyright 2014 Aaron Goldman. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file

package directhttp

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

	"github.com/AaronGoldman/ccfs/objects"
)

var running bool
var hosts []string

//Instance is the instance of the directhttpservice
var Instance directhttpservice

//Start registers directhttpservice instances
func Start(remotes []string) {
	running = true
	hosts = remotes
}

type directhttpservice struct{}

func (d directhttpservice) GetBlob(h objects.HCID) (objects.Blob, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/b/%s",
			host,
			h.Hex(),
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Blob{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Blob{}, err
		}
		return objects.Blob(body), err
	}
	return objects.Blob{}, fmt.Errorf("No Hosts")
}
func (d directhttpservice) GetCommit(h objects.HKID) (objects.Commit, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/c/%s/",
			host,
			h.Hex(),
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Commit{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Commit{}, err
		}
		//ToDo find and get latests vertion
		commit, err := objects.CommitFromBytes(body)
		if err == nil {
			return commit, err
		}
	}
	return objects.Commit{}, fmt.Errorf("No Hosts")
}

func (d directhttpservice) GetTag(h objects.HKID, namesegment string) (
	objects.Tag, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/t/%s/%s",
			host,
			h.Hex(),
			namesegment,
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Tag{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Tag{}, err
		}
		//ToDo find and get latests vertion
		tag, err := objects.TagFromBytes(body)
		if err == nil {
			return tag, err
		}
	}
	return objects.Tag{}, fmt.Errorf("No Hosts")
}

//ID gets the ID string
func (d directhttpservice) ID() string {
	return "directhttp"
}
<commit_msg>added gittags to directhttp<commit_after>//Copyright 2014 Aaron Goldman. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file

package directhttp

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

	"github.com/AaronGoldman/ccfs/objects"
)

var running bool
var hosts []string

//Instance is the instance of the directhttpservice
var Instance directhttpservice

//Start registers directhttpservice instances
func Start(remotes []string) {
	running = true
	hosts = remotes
}

type directhttpservice struct{}

func (d directhttpservice) GetBlob(h objects.HCID) (objects.Blob, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/b/%s",
			host,
			h.Hex(),
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Blob{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Blob{}, err
		}
		return objects.Blob(body), err
	}
	return objects.Blob{}, fmt.Errorf("No Hosts")
}
func (d directhttpservice) GetCommit(h objects.HKID) (objects.Commit, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/c/%s/",
			host,
			h.Hex(),
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Commit{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Commit{}, err
		}
		//ToDo find and get latests vertion
		commit, err := objects.CommitFromBytes(body)
		if err == nil {
			return commit, err
		}
	}
	return objects.Commit{}, fmt.Errorf("No Hosts")
}

func (d directhttpservice) GetTag(h objects.HKID, namesegment string) (
	objects.Tag, error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/t/%s/%s",
			host,
			h.Hex(),
			namesegment,
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return objects.Tag{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return objects.Tag{}, err
		}
		//ToDo find and get latests vertion
		tag, err := objects.TagFromBytes(body)
		if err == nil {
			return tag, err
		}
	}
	return objects.Tag{}, fmt.Errorf("No Hosts")
}

func (d directhttpservice) GetTags(h objects.HKID) (
	tags []objects.Tag, err error) {
	for host := range hosts {
		quarryurl := fmt.Sprintf(
			"https://%s/t/%s/",
			host,
			h.Hex(),
		)
		resp, err := http.Get(quarryurl)
		if err != nil {
			return []objects.Tag{}, err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return []objects.Tag{}, err
		}
		//ToDo find and get latests vertion of all labels
		tag, err := objects.TagFromBytes(body)
		if err == nil {
			return []objects.Tag{tag}, err
		}
	}
	return []objects.Tag{}, fmt.Errorf("No Hosts")
}

//ID gets the ID string
func (d directhttpservice) ID() string {
	return "directhttp"
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"bytes"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"path"
	"time"

	mpath "github.com/mssola/go-utils/path"
)

// TODO: we can do something nicer with these structs...

type Options struct {
	Id       string
	Name     string
	LoggedIn bool
	Error    bool
	JS       bool
	Stats    *Statistics
}

type ExtendedHome struct {
	Players  []*ExtendedPlayer
	Values   []int
	LoggedIn bool
	JS       bool
}

type Home struct {
	Players  []Player
	LoggedIn bool
	JS       bool
}

const (
	layout   = "application/layout"
	viewsDir = "views"
	viewsExt = "tpl"
)

func view(name string) string {
	base := mpath.FindRoot("vendrell", ".")
	return path.Join(base, viewsDir, name+"."+viewsExt)
}

func render(res http.ResponseWriter, name string, data interface{}) {
	b, e := ioutil.ReadFile(view(layout))
	if e != nil {
		panic("Could not read layout file!")
	}
	t, e := template.New("l").Funcs(LayoutHelpers(name, data)).Parse(string(b))
	if e != nil {
		panic("Could not parse layout file!")
	}
	t.Execute(res, data)
}

func LayoutHelpers(name string, data interface{}) template.FuncMap {
	return template.FuncMap{
		"yield": func() template.HTML {
			var buffer bytes.Buffer

			b, e := ioutil.ReadFile(view(name))
			if e != nil {
				panic(fmt.Sprintf("Could not read: %v", name))
			}
			t := template.New(name).Funcs(newViewHelpers())
			t, e = t.Parse(string(b))
			if e != nil {
				panic(fmt.Sprintf("Could not parse: %v", name))
			}
			t.Execute(&buffer, data)
			return template.HTML(buffer.String())
		},
	}
}

func newViewHelpers() template.FuncMap {
	return template.FuncMap{
		"fmtDate": fmtDate,
		"inc": func(n int) int {
			return n + 1
		},
	}
}

// Returns the view helpers for this application.
// TODO: do not export.
func ViewHelpers() []template.FuncMap {
	return []template.FuncMap{
		{
			"fmtDate": fmtDate,
			"inc": func(n int) int {
				return n + 1
			},
		},
	}
}

// Returns a date formatted in an nicer way.
func fmtDate(t time.Time) string {
	return fmt.Sprintf("%02d/%02d/%04d", t.Day(), t.Month(), t.Year())
}
<commit_msg>debug.<commit_after>// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.

package app

import (
	"bytes"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"path"
	"time"

	mpath "github.com/mssola/go-utils/path"
)

// TODO: we can do something nicer with these structs...

type Options struct {
	Id       string
	Name     string
	LoggedIn bool
	Error    bool
	JS       bool
	Stats    *Statistics
}

type ExtendedHome struct {
	Players  []*ExtendedPlayer
	Values   []int
	LoggedIn bool
	JS       bool
}

type Home struct {
	Players  []Player
	LoggedIn bool
	JS       bool
}

const (
	layout   = "application/layout"
	viewsDir = "views"
	viewsExt = "tpl"
)

func view(name string) string {
	base := mpath.FindRoot("vendrell", ".")
	return path.Join(base, viewsDir, name+"."+viewsExt)
}

func render(res http.ResponseWriter, name string, data interface{}) {
	b, e := ioutil.ReadFile(view(layout))
	fmt.Printf("Read file: %v\n", view(layout))
	if e != nil {
		panic("Could not read layout file!")
	}
	t, e := template.New("l").Funcs(LayoutHelpers(name, data)).Parse(string(b))
	if e != nil {
		panic("Could not parse layout file!")
	}
	t.Execute(res, data)
}

func LayoutHelpers(name string, data interface{}) template.FuncMap {
	return template.FuncMap{
		"yield": func() template.HTML {
			var buffer bytes.Buffer

			b, e := ioutil.ReadFile(view(name))
			if e != nil {
				panic(fmt.Sprintf("Could not read: %v", name))
			}
			t := template.New(name).Funcs(newViewHelpers())
			t, e = t.Parse(string(b))
			if e != nil {
				panic(fmt.Sprintf("Could not parse: %v", name))
			}
			t.Execute(&buffer, data)
			return template.HTML(buffer.String())
		},
	}
}

func newViewHelpers() template.FuncMap {
	return template.FuncMap{
		"fmtDate": fmtDate,
		"inc": func(n int) int {
			return n + 1
		},
	}
}

// Returns the view helpers for this application.
// TODO: do not export.
func ViewHelpers() []template.FuncMap {
	return []template.FuncMap{
		{
			"fmtDate": fmtDate,
			"inc": func(n int) int {
				return n + 1
			},
		},
	}
}

// Returns a date formatted in an nicer way.
func fmtDate(t time.Time) string {
	return fmt.Sprintf("%02d/%02d/%04d", t.Day(), t.Month(), t.Year())
}
<|endoftext|>