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

package v1beta1

import (
	"fmt"
	"strings"
	"testing"
	"time"

	habv1beta1 "github.com/habitat-sh/habitat-operator/pkg/apis/habitat/v1beta1"
	utils "github.com/habitat-sh/habitat-operator/test/e2e/v1beta1/framework"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	serviceStartupWaitTime = 1 * time.Minute
	secretUpdateTimeout    = 2 * time.Minute
	secretUpdateQueryTime  = 10 * time.Second

	configMapName = "peer-watch-file"
)

// TestBind tests that the operator correctly created two Habitat Services and bound them together.
func TestBind(t *testing.T) {
	// Get Habitat object from Habitat go example.
	web, err := utils.ConvertHabitat("resources/bind-config/webapp.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(web); err != nil {
		t.Fatal(err)
	}

	// Get Habitat object from Habitat db example.
	db, err := utils.ConvertHabitat("resources/bind-config/db.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(db); err != nil {
		t.Fatal(err)
	}

	// Get Service object from example file.
	svc, err := utils.ConvertService("resources/bind-config/service.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Service.
	_, err = framework.KubeClient.CoreV1().Services(utils.TestNs).Create(svc)
	if err != nil {
		t.Fatal(err)
	}
	// Delete Service so it doesn't interfere with other tests.
	defer (func(name string) {
		if err := framework.DeleteService(name); err != nil {
			t.Fatal(err)
		}
	})(svc.Name)

	// Get Secret object from example file.
	sec, err := utils.ConvertSecret("resources/bind-config/secret.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Secret.
	sec, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Create(sec)
	if err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, web.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, db.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Wait until endpoints are ready.
	if err := framework.WaitForEndpoints(svc.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	time.Sleep(serviceStartupWaitTime)

	// Get response from Habitat Service.
	url := fmt.Sprintf("http://%s:30001/", framework.ExternalIP)

	body, err := utils.QueryService(url)
	if err != nil {
		t.Fatal(err)
	}

	// This msg is set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg := "hello from port: 4444"
	actualMsg := body
	// actualMsg can contain whitespace and newlines or different formatting,
	// the only thing we need to check is it contains the expectedMsg.
	if !strings.Contains(actualMsg, expectedMsg) {
		t.Fatalf("Habitat Service msg does not match one in default.toml. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
	}

	// Test `user.toml` updates.

	// Update secret.
	newPort := "port = 6333"

	sec.Data["user.toml"] = []byte(newPort)
	if _, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Update(sec); err != nil {
		t.Fatalf("Could not update Secret: \"%s\"", err)
	}

	// Wait for SecretVolume to be updated.
	ticker := time.NewTicker(secretUpdateQueryTime)
	defer ticker.Stop()
	timer := time.NewTimer(secretUpdateTimeout)
	defer timer.Stop()

	// Update the message set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg = fmt.Sprintf("hello from port: %v", 6333)
	for {
		// Check that the port differs after the update.
		actualMsg, err := utils.QueryService(url)
		if err != nil {
			t.Fatal(err)
		}

		// actualMsg can contain whitespace and newlines or different formatting,
		// the only thing we need to check is it contains the expectedMsg.
		if strings.Contains(actualMsg, expectedMsg) {
			break
		}

		fail := func() {
			t.Fatalf("Configuration update did not go through. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
		}

		select {
		case <-timer.C:
			fail()
		case <-ticker.C:
			// This is to avoid infinite loops when go
			// decides to always pick the ticker channel,
			// even when timer channel is ready too.
			select {
			case <-timer.C:
				fail()
			default:
			}
		}
	}
}

// TestHabitatDelete tests Habitat deletion.
func TestHabitatDelete(t *testing.T) {
	// Get Habitat object from Habitat go example.
	habitat, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(habitat); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Delete Habitat.
	if err := framework.DeleteHabitat(habitat.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be deleted.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 0); err != nil {
		t.Fatal(err)
	}

	// Check if all the resources the operator creates are deleted.
	// We do not care about secrets being deleted, as the user needs to delete those manually.
	d, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(habitat.ObjectMeta.Name, metav1.GetOptions{})
	if err == nil && d != nil {
		t.Fatal("Deployment was not deleted.")
	}

	// The CM with the peer IP should still be alive, despite the Habitat being deleted as it was created outside of the scope of a Habitat.
	_, err = framework.KubeClient.CoreV1().ConfigMaps(utils.TestNs).Get(configMapName, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}
}

func TestPersistentStorage(t *testing.T) {
	// We run minikube in a VM on Travis. In that environment, we cannot create PersistentVolumes.
	t.Skip("This test cannot be run successfully in our current testing setup")

	ephemeral, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	persisted, err := utils.ConvertHabitat("resources/persisted/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(ephemeral); err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(persisted); err != nil {
		t.Fatal(err)
	}

	// Delete all PVCs at the end of the test.
	// For dynamically provisioned PVs (as is the case on minikube), this will
	// also delete the PVs.
	defer (func(name string) {
		ls := labels.SelectorFromSet(labels.Set(map[string]string{
			habv1beta1.HabitatNameLabel: name,
		}))

		lo := metav1.ListOptions{
			LabelSelector: ls.String(),
		}

		err := framework.KubeClient.CoreV1().PersistentVolumeClaims(utils.TestNs).DeleteCollection(&metav1.DeleteOptions{}, lo)
		if err != nil {
			t.Fatal(err)
		}
	})(persisted.Name)

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, persisted.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Test that persistence is only enabled if requested
	ephemeralSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(ephemeral.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(ephemeralSTS.Spec.VolumeClaimTemplates) != 0 {
		t.Fatal("PersistentVolumeClaims created for ephemeral StatefulSet")
	}

	persistedSTS, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(persisted.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(persistedSTS.Spec.VolumeClaimTemplates) == 0 {
		t.Fatal("No PersistentVolumeClaims created for persistent StatefulSet")
	}
}

func TestV1beta1(t *testing.T) {
	h, err := utils.ConvertHabitat("resources/v1beta1/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(h); err != nil {
		t.Fatal(err)
	}

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, h.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Check that a `Deployment` has been created, rather than a `StatefulSet`.
	if _, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(h.Name, metav1.GetOptions{}); err != nil {
		t.Fatal("Could not retrieve Deployment")
	}

	if _, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(h.Name, metav1.GetOptions{}); err == nil {
		t.Fatal("StatefulSet found where there shouldn't have been one")
	}
}
<commit_msg>e2e/v1beta1: Get StatefulSets from v1beta2<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1beta1

import (
	"fmt"
	"strings"
	"testing"
	"time"

	habv1beta1 "github.com/habitat-sh/habitat-operator/pkg/apis/habitat/v1beta1"
	utils "github.com/habitat-sh/habitat-operator/test/e2e/v1beta1/framework"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	serviceStartupWaitTime = 1 * time.Minute
	secretUpdateTimeout    = 2 * time.Minute
	secretUpdateQueryTime  = 10 * time.Second

	configMapName = "peer-watch-file"
)

// TestBind tests that the operator correctly created two Habitat Services and bound them together.
func TestBind(t *testing.T) {
	// Get Habitat object from Habitat go example.
	web, err := utils.ConvertHabitat("resources/bind-config/webapp.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(web); err != nil {
		t.Fatal(err)
	}

	// Get Habitat object from Habitat db example.
	db, err := utils.ConvertHabitat("resources/bind-config/db.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(db); err != nil {
		t.Fatal(err)
	}

	// Get Service object from example file.
	svc, err := utils.ConvertService("resources/bind-config/service.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Service.
	_, err = framework.KubeClient.CoreV1().Services(utils.TestNs).Create(svc)
	if err != nil {
		t.Fatal(err)
	}
	// Delete Service so it doesn't interfere with other tests.
	defer (func(name string) {
		if err := framework.DeleteService(name); err != nil {
			t.Fatal(err)
		}
	})(svc.Name)

	// Get Secret object from example file.
	sec, err := utils.ConvertSecret("resources/bind-config/secret.yml")
	if err != nil {
		t.Fatal(err)
	}

	// Create Secret.
	sec, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Create(sec)
	if err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, web.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, db.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Wait until endpoints are ready.
	if err := framework.WaitForEndpoints(svc.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	time.Sleep(serviceStartupWaitTime)

	// Get response from Habitat Service.
	url := fmt.Sprintf("http://%s:30001/", framework.ExternalIP)

	body, err := utils.QueryService(url)
	if err != nil {
		t.Fatal(err)
	}

	// This msg is set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg := "hello from port: 4444"
	actualMsg := body
	// actualMsg can contain whitespace and newlines or different formatting,
	// the only thing we need to check is it contains the expectedMsg.
	if !strings.Contains(actualMsg, expectedMsg) {
		t.Fatalf("Habitat Service msg does not match one in default.toml. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
	}

	// Test `user.toml` updates.

	// Update secret.
	newPort := "port = 6333"

	sec.Data["user.toml"] = []byte(newPort)
	if _, err = framework.KubeClient.CoreV1().Secrets(utils.TestNs).Update(sec); err != nil {
		t.Fatalf("Could not update Secret: \"%s\"", err)
	}

	// Wait for SecretVolume to be updated.
	ticker := time.NewTicker(secretUpdateQueryTime)
	defer ticker.Stop()
	timer := time.NewTimer(secretUpdateTimeout)
	defer timer.Stop()

	// Update the message set in the config of the habitat/bindgo-hab Go Habitat Service.
	expectedMsg = fmt.Sprintf("hello from port: %v", 6333)
	for {
		// Check that the port differs after the update.
		actualMsg, err := utils.QueryService(url)
		if err != nil {
			t.Fatal(err)
		}

		// actualMsg can contain whitespace and newlines or different formatting,
		// the only thing we need to check is it contains the expectedMsg.
		if strings.Contains(actualMsg, expectedMsg) {
			break
		}

		fail := func() {
			t.Fatalf("Configuration update did not go through. Expected: \"%s\", got: \"%s\"", expectedMsg, actualMsg)
		}

		select {
		case <-timer.C:
			fail()
		case <-ticker.C:
			// This is to avoid infinite loops when go
			// decides to always pick the ticker channel,
			// even when timer channel is ready too.
			select {
			case <-timer.C:
				fail()
			default:
			}
		}
	}
}

// TestHabitatDelete tests Habitat deletion.
func TestHabitatDelete(t *testing.T) {
	// Get Habitat object from Habitat go example.
	habitat, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(habitat); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be ready.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Delete Habitat.
	if err := framework.DeleteHabitat(habitat.ObjectMeta.Name); err != nil {
		t.Fatal(err)
	}

	// Wait for resources to be deleted.
	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, habitat.ObjectMeta.Name, 0); err != nil {
		t.Fatal(err)
	}

	// Check if all the resources the operator creates are deleted.
	// We do not care about secrets being deleted, as the user needs to delete those manually.
	d, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(habitat.ObjectMeta.Name, metav1.GetOptions{})
	if err == nil && d != nil {
		t.Fatal("Deployment was not deleted.")
	}

	// The CM with the peer IP should still be alive, despite the Habitat being deleted as it was created outside of the scope of a Habitat.
	_, err = framework.KubeClient.CoreV1().ConfigMaps(utils.TestNs).Get(configMapName, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}
}

func TestPersistentStorage(t *testing.T) {
	// We run minikube in a VM on Travis. In that environment, we cannot create PersistentVolumes.
	t.Skip("This test cannot be run successfully in our current testing setup")

	ephemeral, err := utils.ConvertHabitat("resources/standalone/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	persisted, err := utils.ConvertHabitat("resources/persisted/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(ephemeral); err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(persisted); err != nil {
		t.Fatal(err)
	}

	// Delete all PVCs at the end of the test.
	// For dynamically provisioned PVs (as is the case on minikube), this will
	// also delete the PVs.
	defer (func(name string) {
		ls := labels.SelectorFromSet(labels.Set(map[string]string{
			habv1beta1.HabitatNameLabel: name,
		}))

		lo := metav1.ListOptions{
			LabelSelector: ls.String(),
		}

		err := framework.KubeClient.CoreV1().PersistentVolumeClaims(utils.TestNs).DeleteCollection(&metav1.DeleteOptions{}, lo)
		if err != nil {
			t.Fatal(err)
		}
	})(persisted.Name)

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, persisted.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Test that persistence is only enabled if requested
	ephemeralSTS, err := framework.KubeClient.AppsV1beta2().StatefulSets(utils.TestNs).Get(ephemeral.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(ephemeralSTS.Spec.VolumeClaimTemplates) != 0 {
		t.Fatal("PersistentVolumeClaims created for ephemeral StatefulSet")
	}

	persistedSTS, err := framework.KubeClient.AppsV1beta2().StatefulSets(utils.TestNs).Get(persisted.Name, metav1.GetOptions{})
	if err != nil {
		t.Fatal(err)
	}

	if len(persistedSTS.Spec.VolumeClaimTemplates) == 0 {
		t.Fatal("No PersistentVolumeClaims created for persistent StatefulSet")
	}
}

func TestV1beta1(t *testing.T) {
	h, err := utils.ConvertHabitat("resources/v1beta1/habitat.yml")
	if err != nil {
		t.Fatal(err)
	}

	if err := framework.CreateHabitat(h); err != nil {
		t.Fatal(err)
	}

	if err := framework.WaitForResources(habv1beta1.HabitatNameLabel, h.Name, 1); err != nil {
		t.Fatal(err)
	}

	// Check that a `Deployment` has been created, rather than a `StatefulSet`.
	if _, err := framework.KubeClient.AppsV1beta1().Deployments(utils.TestNs).Get(h.Name, metav1.GetOptions{}); err != nil {
		t.Fatal("Could not retrieve Deployment")
	}

	if _, err := framework.KubeClient.AppsV1beta1().StatefulSets(utils.TestNs).Get(h.Name, metav1.GetOptions{}); err == nil {
		t.Fatal("StatefulSet found where there shouldn't have been one")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	"github.com/42wim/matterbridge/gateway/samechannel"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"strings"
)

var (
	version = "0.16.2"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)

	g := gateway.New(cfg)
	sgw := samechannelgateway.New(cfg)
	gwconfigs := sgw.GetConfig()
	for _, gw := range append(gwconfigs, cfg.Gateway...) {
		if !gw.Enable {
			continue
		}
		err := g.AddConfig(&gw)
		if err != nil {
			log.Fatalf("Starting gateway failed: %s", err)
		}
	}
	err := g.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<commit_msg>Bump version<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	"github.com/42wim/matterbridge/gateway/samechannel"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"strings"
)

var (
	version = "0.16.3-dev"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)

	g := gateway.New(cfg)
	sgw := samechannelgateway.New(cfg)
	gwconfigs := sgw.GetConfig()
	for _, gw := range append(gwconfigs, cfg.Gateway...) {
		if !gw.Enable {
			continue
		}
		err := g.AddConfig(&gw)
		if err != nil {
			log.Fatalf("Starting gateway failed: %s", err)
		}
	}
	err := g.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"
	"text/scanner"

	"github.com/crgimenes/goConfig"
)

type config struct {
	InputFile  string `json:"i" cfg:"i"`
	OutputFile string `json:"o" cfg:"o"`
}

type fileInfo struct {
	Version     string
	PackageName string
	ObjectName  string
	Height      int
	Width       int
}

const alert = "/* Automatically generated, do not change manually. */"

func main() {

	cfg := config{}

	goConfig.PrefixEnv = "BMV"
	err := goConfig.Parse(&cfg)
	if err != nil {
		os.Exit(1)
	}

	if cfg.InputFile == "" {
		goConfig.Usage()
		os.Exit(1)
	}

	err = parse(cfg.InputFile)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}

}

func parse(fileName string) (err error) {

	var out string

	out = alert + "\n\n"

	var iFile *os.File
	//var oFile *os.File

	iFile, err = os.Open(fileName)
	if err != nil {
		return
	}
	defer func() {
		err = iFile.Close()
		if err != nil {
			println(err.Error())
			os.Exit(1)
		}
	}()

	fi := fileInfo{}

	var s scanner.Scanner
	s.Init(iFile)
	s.Filename = fileName
	s.Mode = scanner.ScanIdents |
		scanner.ScanFloats |
		scanner.ScanChars |
		scanner.ScanStrings |
		scanner.ScanRawStrings |
		scanner.ScanComments
	var tok rune

	ntok := 0
	for tok != scanner.EOF {
		tok = s.Scan()
		if tok == scanner.Comment {
			out += s.TokenText() + "\n"
		} else {

			switch ntok {
			case 0:
				fi.Version = s.TokenText()
			case 1:
				fi.PackageName = s.TokenText()
				out += "\npackage " + fi.PackageName + "\n\n"
			case 2:
				fi.ObjectName = s.TokenText()
				out += "var " + fi.PackageName + " [][]byte" + "\n\n"
				out += "func Load" + fi.PackageName + "() {\n\n"
			case 3:
				var h int
				h, err = strconv.Atoi(s.TokenText())
				if err != nil {
					return
				}
				fi.Height = h
			case 4:
				var w int
				w, err = strconv.Atoi(s.TokenText())
				if err != nil {
					return
				}
				fi.Width = w
			default:
				//fmt.Println("At position", s.Pos(), ":", s.TokenText(), ntok)
				bs := s.TokenText()
				if bs == "" {
					continue
				}
				var r int64
				r, err = strconv.ParseInt(bs, 2, 8)
				if err != nil {
					println(err.Error())
					return
				}
				out += fmt.Sprintf("0x%02X,\t// %v\n", r, bs)
			}

			ntok++
		}
	}
	out += "}\n"

	println(out)

	return
}
<commit_msg>update errors<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"
	"text/scanner"

	"github.com/crgimenes/goConfig"
)

type config struct {
	InputFile  string `json:"i" cfg:"i"`
	OutputFile string `json:"o" cfg:"o"`
}

type fileInfo struct {
	Version     string
	PackageName string
	ObjectName  string
	Height      int
	Width       int
}

const alert = "/* Automatically generated, do not change manually. */"

func main() {

	cfg := config{}

	goConfig.PrefixEnv = "BMV"
	err := goConfig.Parse(&cfg)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}

	if cfg.InputFile == "" {
		goConfig.Usage()
		os.Exit(1)
	}

	err = parse(cfg.InputFile)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}

}

func parse(fileName string) (err error) {

	var out string
	var iFile *os.File

	out = alert + "\n\n"
	//var oFile *os.File

	iFile, err = os.Open(fileName)
	if err != nil {
		return
	}
	defer func() {
		if e := iFile.Close(); e != nil {
			err = e
			return
		}
	}()

	fi := fileInfo{}

	var s scanner.Scanner
	s.Init(iFile)
	s.Filename = fileName
	s.Mode = scanner.ScanIdents |
		scanner.ScanFloats |
		scanner.ScanChars |
		scanner.ScanStrings |
		scanner.ScanRawStrings |
		scanner.ScanComments
	var tok rune

	ntok := 0
	for tok != scanner.EOF {
		tok = s.Scan()
		if tok == scanner.Comment {
			out += s.TokenText() + "\n"
		} else {

			switch ntok {
			case 0:
				fi.Version = s.TokenText()
			case 1:
				fi.PackageName = s.TokenText()
				out += "\npackage " + fi.PackageName + "\n\n"
			case 2:
				fi.ObjectName = s.TokenText()
				out += "var " + fi.PackageName + " [][]byte" + "\n\n"
				out += "func Load" + fi.PackageName + "() {\n\n"
			case 3:
				var h int
				h, err = strconv.Atoi(s.TokenText())
				if err != nil {
					return
				}
				fi.Height = h
			case 4:
				var w int
				w, err = strconv.Atoi(s.TokenText())
				if err != nil {
					return
				}
				fi.Width = w
			default:
				//fmt.Println("At position", s.Pos(), ":", s.TokenText(), ntok)
				bs := s.TokenText()
				if bs == "" {
					continue
				}

				if len(bs) > fi.Width {
					err = fmt.Errorf("Error at %v", s.Pos())
					println(err.Error())
					return
				}

				var r int64
				r, err = strconv.ParseInt(bs, 2, 64)
				if err != nil {
					println(err.Error())
					return
				}
				out += fmt.Sprintf("0x%02X,\t// %v\n", r, bs)
			}

			ntok++
		}
	}
	out += "}\n"

	println(out)

	return
}
<|endoftext|>


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

package search

import (
	"sort"

	"github.com/gonum/graph"
	"github.com/gonum/graph/internal"
)

// johnson implements Johnson's "Finding all the elementary
// circuits of a directed graph" algorithm. SIAM J. Comput. 4(1):1975.
//
// Comments in the johnson methods are kept in sync with the comments
// and labels from the paper.
type johnson struct {
	adjacent johnsonGraph      // SCC adjacency list.
	b        []internal.IntSet // Johnson's "B-list".
	blocked  []bool
	s        int

	stack []graph.Node

	result [][]graph.Node
}

// CyclesIn returns the set of elementary cycles in the graph g.
func CyclesIn(g graph.DirectedGraph) [][]graph.Node {
	jg := johnsonGraphFrom(g)
	j := johnson{
		adjacent: jg,
		b:        make([]internal.IntSet, len(jg.orig)),
		blocked:  make([]bool, len(jg.orig)),
	}

	// len(j.nodes) is the order of g.
	for j.s < len(j.adjacent.orig)-1 {
		// We use the previous SCC adjacency to reduce the work needed.
		sccs := TarjanSCC(j.adjacent.subgraph(j.s))
		// A_k = adjacency structure of strong component K with least
		//       vertex in subgraph of G induced by {s, s+1, ... ,n}.
		j.adjacent = j.adjacent.sccSubGraph(sccs, 2) // Only allow SCCs with >= 2 vertices.
		if j.adjacent.order() == 0 {
			break
		}

		// s = least vertex in V_k
		if s := j.adjacent.leastVertexIndex(); s < j.s {
			j.s = s
		}
		for i, v := range j.adjacent.orig {
			if !j.adjacent.nodes.Has(v.ID()) {
				continue
			}
			if len(j.adjacent.succ[v.ID()]) > 0 {
				j.blocked[i] = false
				j.b[i] = make(internal.IntSet)
			}
		}
		//L3:
		_ = j.circuit(j.s)
		j.s++
	}

	return j.result
}

// circuit is the CIRCUIT sub-procedure in the paper.
func (j *johnson) circuit(v int) bool {
	f := false
	n := j.adjacent.orig[v]
	j.stack = append(j.stack, n)
	j.blocked[v] = true

	//L1:
	for w := range j.adjacent.succ[n.ID()] {
		w = j.adjacent.indexOf(w)
		if w == j.s {
			// Output circuit composed of stack followed by s.
			r := make([]graph.Node, len(j.stack)+1)
			copy(r, j.stack)
			r[len(r)-1] = j.adjacent.orig[j.s]
			j.result = append(j.result, r)
			f = true
		} else if !j.blocked[w] {
			if j.circuit(w) {
				f = true
			}
		}
	}

	//L2:
	if f {
		j.unblock(v)
	} else {
		for w := range j.adjacent.succ[n.ID()] {
			j.b[j.adjacent.indexOf(w)].Add(v)
		}
	}
	j.stack = j.stack[:len(j.stack)-1]

	return f
}

// unblock is the UNBLOCK sub-procedure in the paper.
func (j *johnson) unblock(u int) {
	j.blocked[u] = false
	for w := range j.b[u] {
		j.b[u].Remove(w)
		if j.blocked[w] {
			j.unblock(w)
		}
	}
}

// johnsonGraph is an edge list representation of a graph with helpers
// necessary for Johnson's algorithm
type johnsonGraph struct {
	// Keep the original graph nodes and a
	// look-up to into the non-sparse
	// collection of potentially sparse IDs.
	orig  []graph.Node
	index map[int]int

	nodes internal.IntSet
	succ  map[int]internal.IntSet
}

// johnsonGraphFrom returns a deep copy of the graph g.
func johnsonGraphFrom(g graph.DirectedGraph) johnsonGraph {
	nodes := g.NodeList()
	sort.Sort(byID(nodes))
	c := johnsonGraph{
		orig:  nodes,
		index: make(map[int]int, len(nodes)),

		nodes: make(internal.IntSet, len(nodes)),
		succ:  make(map[int]internal.IntSet),
	}
	for i, u := range nodes {
		c.index[u.ID()] = i
		for _, v := range g.Successors(u) {
			if c.succ[u.ID()] == nil {
				c.succ[u.ID()] = make(internal.IntSet)
				c.nodes.Add(u.ID())
			}
			c.nodes.Add(v.ID())
			c.succ[u.ID()].Add(v.ID())
		}
	}
	return c
}

type byID []graph.Node

func (n byID) Len() int           { return len(n) }
func (n byID) Less(i, j int) bool { return n[i].ID() < n[j].ID() }
func (n byID) Swap(i, j int)      { n[i], n[j] = n[j], n[i] }

// order returns the order of the graph.
func (g johnsonGraph) order() int { return g.nodes.Count() }

// indexOf returns the index of the retained node for the given node ID.
func (g johnsonGraph) indexOf(id int) int {
	return g.index[id]
}

// leastVertexIndex returns the index into orig of the least vertex.
func (g johnsonGraph) leastVertexIndex() int {
	for _, v := range g.orig {
		if g.nodes.Has(v.ID()) {
			return g.indexOf(v.ID())
		}
	}
	panic("johnsonCycles: empty set")
}

// subgraph returns a subgraph of g induced by {s, s+1, ... , n}. The
// subgraph is destructively generated in g.
func (g johnsonGraph) subgraph(s int) johnsonGraph {
	sn := g.orig[s].ID()
	for u, e := range g.succ {
		if u < sn {
			g.nodes.Remove(u)
			delete(g.succ, u)
			continue
		}
		for v := range e {
			if v < sn {
				g.succ[u].Remove(v)
			}
		}
	}
	return g
}

// sccSubGraph returns the graph of the tarjan's strongly connected
// components with each SCC containing at least min vertices.
// sccSubGraph returns nil if there is no SCC with at least min
// members.
func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph {
	if len(g.nodes) == 0 {
		g.nodes = nil
		g.succ = nil
		return g
	}
	sub := johnsonGraph{
		orig:  g.orig,
		index: g.index,
		nodes: make(internal.IntSet),
		succ:  make(map[int]internal.IntSet),
	}

	var n int
	for _, scc := range sccs {
		if len(scc) < min {
			continue
		}
		n++
		for _, u := range scc {
			for _, v := range scc {
				if _, ok := g.succ[u.ID()][v.ID()]; ok {
					if sub.succ[u.ID()] == nil {
						sub.succ[u.ID()] = make(internal.IntSet)
						sub.nodes.Add(u.ID())
					}
					sub.nodes.Add(v.ID())
					sub.succ[u.ID()].Add(v.ID())
				}
			}
		}
	}
	if n == 0 {
		g.nodes = nil
		g.succ = nil
		return g
	}

	return sub
}

// NodeList is required to satisfy Tarjan.
func (g johnsonGraph) NodeList() []graph.Node {
	n := make([]graph.Node, 0, len(g.nodes))
	for id := range g.nodes {
		n = append(n, johnsonGraphNode(id))
	}
	return n
}

// Successors is required to satisfy Tarjan.
func (g johnsonGraph) Successors(n graph.Node) []graph.Node {
	adj := g.succ[n.ID()]
	if len(adj) == 0 {
		return nil
	}
	succ := make([]graph.Node, 0, len(adj))
	for n := range adj {
		succ = append(succ, johnsonGraphNode(n))
	}
	return succ
}

// The following methods are purely here to satisfy graph.DirectedGraph.
// Use of this type for anything except Tarjan or CyclesIn is likely to result in
// incorrect results.
func (johnsonGraph) NodeExists(n graph.Node) bool           { return false }
func (johnsonGraph) Neighbors(n graph.Node) []graph.Node    { return nil }
func (johnsonGraph) EdgeBetween(u, v graph.Node) graph.Edge { return nil }
func (johnsonGraph) EdgeTo(u, v graph.Node) graph.Edge      { return nil }
func (johnsonGraph) Predecessors(v graph.Node) []graph.Node { return nil }

type johnsonGraphNode int

func (n johnsonGraphNode) ID() int { return int(n) }
<commit_msg>search: replace comment about misuse with panics<commit_after>// Copyright ©2015 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package search

import (
	"sort"

	"github.com/gonum/graph"
	"github.com/gonum/graph/internal"
)

// johnson implements Johnson's "Finding all the elementary
// circuits of a directed graph" algorithm. SIAM J. Comput. 4(1):1975.
//
// Comments in the johnson methods are kept in sync with the comments
// and labels from the paper.
type johnson struct {
	adjacent johnsonGraph      // SCC adjacency list.
	b        []internal.IntSet // Johnson's "B-list".
	blocked  []bool
	s        int

	stack []graph.Node

	result [][]graph.Node
}

// CyclesIn returns the set of elementary cycles in the graph g.
func CyclesIn(g graph.DirectedGraph) [][]graph.Node {
	jg := johnsonGraphFrom(g)
	j := johnson{
		adjacent: jg,
		b:        make([]internal.IntSet, len(jg.orig)),
		blocked:  make([]bool, len(jg.orig)),
	}

	// len(j.nodes) is the order of g.
	for j.s < len(j.adjacent.orig)-1 {
		// We use the previous SCC adjacency to reduce the work needed.
		sccs := TarjanSCC(j.adjacent.subgraph(j.s))
		// A_k = adjacency structure of strong component K with least
		//       vertex in subgraph of G induced by {s, s+1, ... ,n}.
		j.adjacent = j.adjacent.sccSubGraph(sccs, 2) // Only allow SCCs with >= 2 vertices.
		if j.adjacent.order() == 0 {
			break
		}

		// s = least vertex in V_k
		if s := j.adjacent.leastVertexIndex(); s < j.s {
			j.s = s
		}
		for i, v := range j.adjacent.orig {
			if !j.adjacent.nodes.Has(v.ID()) {
				continue
			}
			if len(j.adjacent.succ[v.ID()]) > 0 {
				j.blocked[i] = false
				j.b[i] = make(internal.IntSet)
			}
		}
		//L3:
		_ = j.circuit(j.s)
		j.s++
	}

	return j.result
}

// circuit is the CIRCUIT sub-procedure in the paper.
func (j *johnson) circuit(v int) bool {
	f := false
	n := j.adjacent.orig[v]
	j.stack = append(j.stack, n)
	j.blocked[v] = true

	//L1:
	for w := range j.adjacent.succ[n.ID()] {
		w = j.adjacent.indexOf(w)
		if w == j.s {
			// Output circuit composed of stack followed by s.
			r := make([]graph.Node, len(j.stack)+1)
			copy(r, j.stack)
			r[len(r)-1] = j.adjacent.orig[j.s]
			j.result = append(j.result, r)
			f = true
		} else if !j.blocked[w] {
			if j.circuit(w) {
				f = true
			}
		}
	}

	//L2:
	if f {
		j.unblock(v)
	} else {
		for w := range j.adjacent.succ[n.ID()] {
			j.b[j.adjacent.indexOf(w)].Add(v)
		}
	}
	j.stack = j.stack[:len(j.stack)-1]

	return f
}

// unblock is the UNBLOCK sub-procedure in the paper.
func (j *johnson) unblock(u int) {
	j.blocked[u] = false
	for w := range j.b[u] {
		j.b[u].Remove(w)
		if j.blocked[w] {
			j.unblock(w)
		}
	}
}

// johnsonGraph is an edge list representation of a graph with helpers
// necessary for Johnson's algorithm
type johnsonGraph struct {
	// Keep the original graph nodes and a
	// look-up to into the non-sparse
	// collection of potentially sparse IDs.
	orig  []graph.Node
	index map[int]int

	nodes internal.IntSet
	succ  map[int]internal.IntSet
}

// johnsonGraphFrom returns a deep copy of the graph g.
func johnsonGraphFrom(g graph.DirectedGraph) johnsonGraph {
	nodes := g.NodeList()
	sort.Sort(byID(nodes))
	c := johnsonGraph{
		orig:  nodes,
		index: make(map[int]int, len(nodes)),

		nodes: make(internal.IntSet, len(nodes)),
		succ:  make(map[int]internal.IntSet),
	}
	for i, u := range nodes {
		c.index[u.ID()] = i
		for _, v := range g.Successors(u) {
			if c.succ[u.ID()] == nil {
				c.succ[u.ID()] = make(internal.IntSet)
				c.nodes.Add(u.ID())
			}
			c.nodes.Add(v.ID())
			c.succ[u.ID()].Add(v.ID())
		}
	}
	return c
}

type byID []graph.Node

func (n byID) Len() int           { return len(n) }
func (n byID) Less(i, j int) bool { return n[i].ID() < n[j].ID() }
func (n byID) Swap(i, j int)      { n[i], n[j] = n[j], n[i] }

// order returns the order of the graph.
func (g johnsonGraph) order() int { return g.nodes.Count() }

// indexOf returns the index of the retained node for the given node ID.
func (g johnsonGraph) indexOf(id int) int {
	return g.index[id]
}

// leastVertexIndex returns the index into orig of the least vertex.
func (g johnsonGraph) leastVertexIndex() int {
	for _, v := range g.orig {
		if g.nodes.Has(v.ID()) {
			return g.indexOf(v.ID())
		}
	}
	panic("johnsonCycles: empty set")
}

// subgraph returns a subgraph of g induced by {s, s+1, ... , n}. The
// subgraph is destructively generated in g.
func (g johnsonGraph) subgraph(s int) johnsonGraph {
	sn := g.orig[s].ID()
	for u, e := range g.succ {
		if u < sn {
			g.nodes.Remove(u)
			delete(g.succ, u)
			continue
		}
		for v := range e {
			if v < sn {
				g.succ[u].Remove(v)
			}
		}
	}
	return g
}

// sccSubGraph returns the graph of the tarjan's strongly connected
// components with each SCC containing at least min vertices.
// sccSubGraph returns nil if there is no SCC with at least min
// members.
func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph {
	if len(g.nodes) == 0 {
		g.nodes = nil
		g.succ = nil
		return g
	}
	sub := johnsonGraph{
		orig:  g.orig,
		index: g.index,
		nodes: make(internal.IntSet),
		succ:  make(map[int]internal.IntSet),
	}

	var n int
	for _, scc := range sccs {
		if len(scc) < min {
			continue
		}
		n++
		for _, u := range scc {
			for _, v := range scc {
				if _, ok := g.succ[u.ID()][v.ID()]; ok {
					if sub.succ[u.ID()] == nil {
						sub.succ[u.ID()] = make(internal.IntSet)
						sub.nodes.Add(u.ID())
					}
					sub.nodes.Add(v.ID())
					sub.succ[u.ID()].Add(v.ID())
				}
			}
		}
	}
	if n == 0 {
		g.nodes = nil
		g.succ = nil
		return g
	}

	return sub
}

// NodeList is required to satisfy Tarjan.
func (g johnsonGraph) NodeList() []graph.Node {
	n := make([]graph.Node, 0, len(g.nodes))
	for id := range g.nodes {
		n = append(n, johnsonGraphNode(id))
	}
	return n
}

// Successors is required to satisfy Tarjan.
func (g johnsonGraph) Successors(n graph.Node) []graph.Node {
	adj := g.succ[n.ID()]
	if len(adj) == 0 {
		return nil
	}
	succ := make([]graph.Node, 0, len(adj))
	for n := range adj {
		succ = append(succ, johnsonGraphNode(n))
	}
	return succ
}

func (johnsonGraph) NodeExists(graph.Node) bool {
	panic("search: unintended use of johnsonGraph")
}
func (johnsonGraph) Neighbors(graph.Node) []graph.Node {
	panic("search: unintended use of johnsonGraph")
}
func (johnsonGraph) EdgeBetween(_, _ graph.Node) graph.Edge {
	panic("search: unintended use of johnsonGraph")
}
func (johnsonGraph) EdgeTo(_, _ graph.Node) graph.Edge {
	panic("search: unintended use of johnsonGraph")
}
func (johnsonGraph) Predecessors(graph.Node) []graph.Node {
	panic("search: unintended use of johnsonGraph")
}

type johnsonGraphNode int

func (n johnsonGraphNode) ID() int { return int(n) }
<|endoftext|>


<commit_before>package db

import (
  "encoding/json"
  "fmt"
  "github.com/nu7hatch/gouuid"
  "io/ioutil"
  "os"
  "path"
  "runtime"
  "strings"
  "time"
)

const VERSION = "v1"

var DIR = func() string {
  _, filename, _, _ := runtime.Caller(1)
  return path.Join(path.Dir(filename), "../../data")
}()

func ReadFile(args ...string) ([]byte, error) {
  return ioutil.ReadFile(path.Join(args...))
}

func ReadDir(args ...string) ([]os.FileInfo, error) {
  return ioutil.ReadDir(path.Join(args...))
}

func Create(args ...string) (*os.File, error) {
  return os.Create(path.Join(args...))
}

/**
 * Posts
 */

type Post struct {
  Uuid    string `json:"uuid"`
  Title   string `json:"title"`
  User    string `json:"user"`
  Created int64  `json:"created"`
}

type PostContainer struct {
  Post Post `json:"post"`
}

type PostCollection struct {
  Posts []Post `json:"posts"`
}

func (post *Post) Save() error {
  if post.Uuid == "" {
    uuid, _ := uuid.NewV4()
    post.Uuid = fmt.Sprintf("%s", uuid)
  }

  if post.Created == 0 {
    post.Created = time.Now().UnixNano()
  }

  rawJson, err := json.Marshal(*post)
  if err != nil {
    return err
  }

  file, err := Create(DIR, "users", post.User, VERSION, "posts", post.FileName())
  if err != nil {
    return err
  }

  file.Write(rawJson)
  return nil
}

func (post *Post) FileName() string {
  return fmt.Sprintf("%d-post-%s", post.Created, post.Uuid)
}

func PostFromJson(rawJson []byte) *Post {
  var post Post
  json.Unmarshal(rawJson, &post)
  return &post
}

func PostContainerFromJson(rawJson []byte) *PostContainer {
  var container PostContainer
  json.Unmarshal(rawJson, &container)
  return &container
}

func NewPost(title string, user string) *Post {
  return &Post{
    Title: title,
    User:  user,
  }
}

func NewPostContainer(post *Post) *PostContainer {
  return &PostContainer{Post: *post}
}

func NewPostCollection(posts []Post) *PostCollection {
  return &PostCollection{Posts: posts}
}

func GetPosts() (*PostCollection, error) {
  posts := make([]Post, 0)

  users, _ := ReadDir(DIR, "users")

  for _, user := range users {
    dir := path.Join(DIR, "users", user.Name(), VERSION, "posts")

    files, err := ReadDir(dir)
    if err != nil {
      continue
    }

    for _, post := range files {
      data, err := ReadFile(dir, post.Name())

      if err != nil {
        continue
      }

      posts = append(posts, *PostFromJson(data))
    }
  }

  return &PostCollection{posts}, nil
}

/**
 * Users
 */

type User struct {
  Key         string `json:"key"`
  Hash        string `json:"hash"`
  User        string `json:"user"`
  DisplayName string `json:"display_name"`
}

type UserCollection struct {
  Users []User `json:"users"`
}

type UserContainer struct {
  User User `json:"user"`
}

func UserFromJson(rawJson []byte) *User {
  var user User
  json.Unmarshal(rawJson, &user)
  return &user
}

func NewUser(user string, displayName string) *User {
  return &User{
    User:        user,
    DisplayName: displayName,
  }
}

func NewUserContainer(user *User) *UserContainer {
  return &UserContainer{User: *user}
}

func NewUserCollection(users []User) *UserCollection {
  return &UserCollection{Users: users}
}

func CurrentUser() (*User, error) {
  rawName, err := ReadFile(DIR, "my_user")
  if err != nil {
    return nil, err
  }

  name := strings.TrimSpace(string(rawName))

  data, err := ReadFile(DIR, "users", name, VERSION, "user", name)
  if err != nil {
    return nil, err
  }

  return UserFromJson(data), nil
}
<commit_msg>Modifying for our path<commit_after>package db

import (
  "encoding/json"
  "fmt"
  "github.com/vole/gouuid"
  "io/ioutil"
  "os"
  "path"
  "runtime"
  "strings"
  "time"
)

const VERSION = "v1"

var DIR = func() string {
  _, filename, _, _ := runtime.Caller(1)
  return path.Join(path.Dir(filename), "../../data")
}()

func ReadFile(args ...string) ([]byte, error) {
  return ioutil.ReadFile(path.Join(args...))
}

func ReadDir(args ...string) ([]os.FileInfo, error) {
  return ioutil.ReadDir(path.Join(args...))
}

func Create(args ...string) (*os.File, error) {
  return os.Create(path.Join(args...))
}

/**
 * Posts
 */

type Post struct {
  Uuid    string `json:"uuid"`
  Title   string `json:"title"`
  User    string `json:"user"`
  Created int64  `json:"created"`
}

type PostContainer struct {
  Post Post `json:"post"`
}

type PostCollection struct {
  Posts []Post `json:"posts"`
}

func (post *Post) Save() error {
  if post.Uuid == "" {
    uuid, _ := uuid.NewV4()
    post.Uuid = fmt.Sprintf("%s", uuid)
  }

  if post.Created == 0 {
    post.Created = time.Now().UnixNano()
  }

  rawJson, err := json.Marshal(*post)
  if err != nil {
    return err
  }

  file, err := Create(DIR, "users", post.User, VERSION, "posts", post.FileName())
  if err != nil {
    return err
  }

  file.Write(rawJson)
  return nil
}

func (post *Post) FileName() string {
  return fmt.Sprintf("%d-post-%s", post.Created, post.Uuid)
}

func PostFromJson(rawJson []byte) *Post {
  var post Post
  json.Unmarshal(rawJson, &post)
  return &post
}

func PostContainerFromJson(rawJson []byte) *PostContainer {
  var container PostContainer
  json.Unmarshal(rawJson, &container)
  return &container
}

func NewPost(title string, user string) *Post {
  return &Post{
    Title: title,
    User:  user,
  }
}

func NewPostContainer(post *Post) *PostContainer {
  return &PostContainer{Post: *post}
}

func NewPostCollection(posts []Post) *PostCollection {
  return &PostCollection{Posts: posts}
}

func GetPosts() (*PostCollection, error) {
  posts := make([]Post, 0)

  users, _ := ReadDir(DIR, "users")

  for _, user := range users {
    dir := path.Join(DIR, "users", user.Name(), VERSION, "posts")

    files, err := ReadDir(dir)
    if err != nil {
      continue
    }

    for _, post := range files {
      data, err := ReadFile(dir, post.Name())

      if err != nil {
        continue
      }

      posts = append(posts, *PostFromJson(data))
    }
  }

  return &PostCollection{posts}, nil
}

/**
 * Users
 */

type User struct {
  Key         string `json:"key"`
  Hash        string `json:"hash"`
  User        string `json:"user"`
  DisplayName string `json:"display_name"`
}

type UserCollection struct {
  Users []User `json:"users"`
}

type UserContainer struct {
  User User `json:"user"`
}

func UserFromJson(rawJson []byte) *User {
  var user User
  json.Unmarshal(rawJson, &user)
  return &user
}

func NewUser(user string, displayName string) *User {
  return &User{
    User:        user,
    DisplayName: displayName,
  }
}

func NewUserContainer(user *User) *UserContainer {
  return &UserContainer{User: *user}
}

func NewUserCollection(users []User) *UserCollection {
  return &UserCollection{Users: users}
}

func CurrentUser() (*User, error) {
  rawName, err := ReadFile(DIR, "my_user")
  if err != nil {
    return nil, err
  }

  name := strings.TrimSpace(string(rawName))

  data, err := ReadFile(DIR, "users", name, VERSION, "user", name)
  if err != nil {
    return nil, err
  }

  return UserFromJson(data), nil
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"database/sql"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/geek1011/koboutils/kobo"

	"github.com/beevik/etree"
	"github.com/mattn/go-zglob"
	"golang.org/x/tools/godoc/vfs/zipfs"

	"github.com/spf13/pflag"

	_ "github.com/mattn/go-sqlite3"
)

var version = "dev"

func helpExit() {
	fmt.Fprintf(os.Stderr, "Usage: seriesmeta [OPTIONS] [KOBO_PATH]\n\nVersion:\n  seriesmeta %s\n\nOptions:\n", version)
	pflag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nArguments:\n  KOBO_PATH is the path to the Kobo eReader. If not specified, seriesmeta will try to automatically detect the Kobo.\n")
	if runtime.GOOS == "windows" {
		time.Sleep(time.Second * 2)
	}
	os.Exit(1)
}

func errExit() {
	if runtime.GOOS == "windows" {
		time.Sleep(time.Second * 2)
	}
	os.Exit(1)
}

func copyFile(src, dst string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, in)
	if err != nil {
		return err
	}
	return out.Close()
}

// pathToContentID gets the content ID for a book. The path needs to be relative to the root of the kobo.
func pathToContentID(relpath string) string {
	return fmt.Sprintf("file:///mnt/onboard/%s", filepath.ToSlash(relpath))
}

func contentIDToImageID(contentID string) string {
	imageID := contentID

	imageID = strings.Replace(imageID, " ", "_", -1)
	imageID = strings.Replace(imageID, "/", "_", -1)
	imageID = strings.Replace(imageID, ":", "_", -1)
	imageID = strings.Replace(imageID, ".", "_", -1)

	return imageID
}

func getMeta(path string) (string, float64, error) {
	zr, err := zip.OpenReader(path)
	if err != nil {
		return "", 0, err
	}

	zfs := zipfs.New(zr, "epub")
	rsk, err := zfs.Open("/META-INF/container.xml")
	if err != nil {
		return "", 0, err
	}
	defer rsk.Close()

	container := etree.NewDocument()
	_, err = container.ReadFrom(rsk)
	if err != nil {
		return "", 0, err
	}

	rootfile := ""
	for _, e := range container.FindElements("//rootfiles/rootfile[@full-path]") {
		rootfile = e.SelectAttrValue("full-path", "")
	}

	if rootfile == "" {
		return "", 0, errors.New("Cannot parse container")
	}

	rrsk, err := zfs.Open("/" + rootfile)
	if err != nil {
		return "", 0, err
	}
	defer rrsk.Close()

	opf := etree.NewDocument()
	_, err = opf.ReadFrom(rrsk)
	if err != nil {
		return "", 0, err
	}

	var series string
	for _, e := range opf.FindElements("//meta[@name='calibre:series']") {
		series = e.SelectAttrValue("content", "")
		break
	}

	var seriesNumber float64
	for _, e := range opf.FindElements("//meta[@name='calibre:series_index']") {
		i, err := strconv.ParseFloat(e.SelectAttrValue("content", "0"), 64)
		if err == nil {
			seriesNumber = i
			break
		}
	}

	return series, seriesNumber, nil
}

func main() {
	help := pflag.BoolP("help", "h", false, "Show this help message")
	pflag.Parse()

	if *help || pflag.NArg() > 1 {
		helpExit()
	}

	log := func(format string, a ...interface{}) {
		fmt.Printf(format, a...)
	}

	logE := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, format, a...)
	}

	var kpath string
	if pflag.NArg() == 1 {
		kpath = strings.Replace(pflag.Arg(0), ".kobo", "", 1)
	} else {
		log("No kobo specified, attempting to detect one\n")
		kobos, err := kobo.Find()
		if err != nil {
			logE("Fatal: could not automatically detect a kobo: %v\n", err)
			errExit()
		} else if len(kobos) < 1 {
			logE("Fatal: could not automatically detect a kobo\n")
			errExit()
		}
		kpath = kobos[0]
	}

	log("Checking kobo at '%s'\n", kpath)
	if !kobo.IsKobo(kpath) {
		logE("Fatal: '%s' is not a valid kobo\n", kpath)
	}

	kpath, err := filepath.Abs(kpath)
	if err != nil {
		logE("Fatal: Could not resolve path to kobo\n")
		errExit()
	}

	dbpath := filepath.Join(kpath, ".kobo", "KoboReader.sqlite")

	log("Making backup of KoboReader.sqlite\n")
	err = copyFile(dbpath, dbpath+".bak")
	if err != nil {
		logE("Fatal: Could not make copy of KoboReader.sqlite: %v\n", err)
		errExit()
	}

	log("Opening KoboReader.sqlite\n")
	db, err := sql.Open("sqlite3", dbpath)
	if err != nil {
		logE("Fatal: Could not open KoboReader.sqlite: %v\n", err)
		errExit()
	}

	log("Searching for sideloaded epubs and kepubs\n")
	epubs, err := zglob.Glob(filepath.Join(kpath, "**", "*.epub"))
	if err != nil {
		logE("Fatal: Could not search for epubs: %v\n", err)
		errExit()
	}

	log("\nUpdating metadata for %d books\n", len(epubs))
	var updated, nometa, errcount int
	digits := len(fmt.Sprint(len(epubs)))
	numFmt, spFmt := fmt.Sprintf("[%%%dd/%d] ", digits, len(epubs)), strings.Repeat(" ", (digits*2)+4)
	for i, epub := range epubs {
		rpath, err := filepath.Rel(kpath, epub)
		if err != nil {
			log(numFmt+"%s\n", i+1, epub)
			logE(spFmt+"Error: could not resolve path: %v\n", err)
			errcount++
			continue
		}

		log(numFmt+"%s\n", i+1, rpath)
		series, seriesNumber, err := getMeta(epub)
		if err != nil {
			logE(spFmt+"Error: could not read metadata: %v\n", err)
			errcount++
			continue
		}

		if series == "" && seriesNumber == 0 {
			nometa++
			continue
		}

		log(spFmt+"(%s, %v)\n", series, seriesNumber)

		iid := contentIDToImageID(pathToContentID(rpath))

		res, err := db.Exec("UPDATE content SET Series=?, SeriesNumber=? WHERE ImageID=?", sql.NullString{
			String: series,
			Valid:  series != "",
		}, sql.NullString{
			String: fmt.Sprintf("%v", seriesNumber),
			Valid:  seriesNumber > 0,
		}, iid)
		if err != nil {
			logE(spFmt+"Error: could not update database: %v\n", err)
			errcount++
			continue
		}

		ra, err := res.RowsAffected()
		if err != nil {
			logE(spFmt+"Error: could not update database: %v\n", err)
			errcount++
			continue
		}

		if ra > 1 {
			logE(spFmt + "Warn: more than one match in database for ImageID\n")
		} else if ra < 1 {
			logE(spFmt + "Error: could not update database: no entry in database for book (the kobo may still need to import the book)\n")
			errcount++
			continue
		}

		updated++
	}

	time.Sleep(time.Second)
	log("\nFinished updating metadata. %d updated, %d without metadata, %d errored.\n", updated, nometa, errcount)
}
<commit_msg>Delayed exit on windows for seriesmeta<commit_after>package main

import (
	"archive/zip"
	"database/sql"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/geek1011/koboutils/kobo"

	"github.com/beevik/etree"
	"github.com/mattn/go-zglob"
	"golang.org/x/tools/godoc/vfs/zipfs"

	"github.com/spf13/pflag"

	_ "github.com/mattn/go-sqlite3"
)

var version = "dev"

func helpExit() {
	fmt.Fprintf(os.Stderr, "Usage: seriesmeta [OPTIONS] [KOBO_PATH]\n\nVersion:\n  seriesmeta %s\n\nOptions:\n", version)
	pflag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nArguments:\n  KOBO_PATH is the path to the Kobo eReader. If not specified, seriesmeta will try to automatically detect the Kobo.\n")
	if runtime.GOOS == "windows" {
		time.Sleep(time.Second * 2)
	}
	os.Exit(1)
}

func errExit() {
	if runtime.GOOS == "windows" {
		time.Sleep(time.Second * 2)
	}
	os.Exit(1)
}

func copyFile(src, dst string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, in)
	if err != nil {
		return err
	}
	return out.Close()
}

// pathToContentID gets the content ID for a book. The path needs to be relative to the root of the kobo.
func pathToContentID(relpath string) string {
	return fmt.Sprintf("file:///mnt/onboard/%s", filepath.ToSlash(relpath))
}

func contentIDToImageID(contentID string) string {
	imageID := contentID

	imageID = strings.Replace(imageID, " ", "_", -1)
	imageID = strings.Replace(imageID, "/", "_", -1)
	imageID = strings.Replace(imageID, ":", "_", -1)
	imageID = strings.Replace(imageID, ".", "_", -1)

	return imageID
}

func getMeta(path string) (string, float64, error) {
	zr, err := zip.OpenReader(path)
	if err != nil {
		return "", 0, err
	}

	zfs := zipfs.New(zr, "epub")
	rsk, err := zfs.Open("/META-INF/container.xml")
	if err != nil {
		return "", 0, err
	}
	defer rsk.Close()

	container := etree.NewDocument()
	_, err = container.ReadFrom(rsk)
	if err != nil {
		return "", 0, err
	}

	rootfile := ""
	for _, e := range container.FindElements("//rootfiles/rootfile[@full-path]") {
		rootfile = e.SelectAttrValue("full-path", "")
	}

	if rootfile == "" {
		return "", 0, errors.New("Cannot parse container")
	}

	rrsk, err := zfs.Open("/" + rootfile)
	if err != nil {
		return "", 0, err
	}
	defer rrsk.Close()

	opf := etree.NewDocument()
	_, err = opf.ReadFrom(rrsk)
	if err != nil {
		return "", 0, err
	}

	var series string
	for _, e := range opf.FindElements("//meta[@name='calibre:series']") {
		series = e.SelectAttrValue("content", "")
		break
	}

	var seriesNumber float64
	for _, e := range opf.FindElements("//meta[@name='calibre:series_index']") {
		i, err := strconv.ParseFloat(e.SelectAttrValue("content", "0"), 64)
		if err == nil {
			seriesNumber = i
			break
		}
	}

	return series, seriesNumber, nil
}

func main() {
	help := pflag.BoolP("help", "h", false, "Show this help message")
	pflag.Parse()

	if *help || pflag.NArg() > 1 {
		helpExit()
	}

	log := func(format string, a ...interface{}) {
		fmt.Printf(format, a...)
	}

	logE := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, format, a...)
	}

	var kpath string
	if pflag.NArg() == 1 {
		kpath = strings.Replace(pflag.Arg(0), ".kobo", "", 1)
	} else {
		log("No kobo specified, attempting to detect one\n")
		kobos, err := kobo.Find()
		if err != nil {
			logE("Fatal: could not automatically detect a kobo: %v\n", err)
			errExit()
		} else if len(kobos) < 1 {
			logE("Fatal: could not automatically detect a kobo\n")
			errExit()
		}
		kpath = kobos[0]
	}

	log("Checking kobo at '%s'\n", kpath)
	if !kobo.IsKobo(kpath) {
		logE("Fatal: '%s' is not a valid kobo\n", kpath)
	}

	kpath, err := filepath.Abs(kpath)
	if err != nil {
		logE("Fatal: Could not resolve path to kobo\n")
		errExit()
	}

	dbpath := filepath.Join(kpath, ".kobo", "KoboReader.sqlite")

	log("Making backup of KoboReader.sqlite\n")
	err = copyFile(dbpath, dbpath+".bak")
	if err != nil {
		logE("Fatal: Could not make copy of KoboReader.sqlite: %v\n", err)
		errExit()
	}

	log("Opening KoboReader.sqlite\n")
	db, err := sql.Open("sqlite3", dbpath)
	if err != nil {
		logE("Fatal: Could not open KoboReader.sqlite: %v\n", err)
		errExit()
	}

	log("Searching for sideloaded epubs and kepubs\n")
	epubs, err := zglob.Glob(filepath.Join(kpath, "**", "*.epub"))
	if err != nil {
		logE("Fatal: Could not search for epubs: %v\n", err)
		errExit()
	}

	log("\nUpdating metadata for %d books\n", len(epubs))
	var updated, nometa, errcount int
	digits := len(fmt.Sprint(len(epubs)))
	numFmt, spFmt := fmt.Sprintf("[%%%dd/%d] ", digits, len(epubs)), strings.Repeat(" ", (digits*2)+4)
	for i, epub := range epubs {
		rpath, err := filepath.Rel(kpath, epub)
		if err != nil {
			log(numFmt+"%s\n", i+1, epub)
			logE(spFmt+"Error: could not resolve path: %v\n", err)
			errcount++
			continue
		}

		log(numFmt+"%s\n", i+1, rpath)
		series, seriesNumber, err := getMeta(epub)
		if err != nil {
			logE(spFmt+"Error: could not read metadata: %v\n", err)
			errcount++
			continue
		}

		if series == "" && seriesNumber == 0 {
			nometa++
			continue
		}

		log(spFmt+"(%s, %v)\n", series, seriesNumber)

		iid := contentIDToImageID(pathToContentID(rpath))

		res, err := db.Exec("UPDATE content SET Series=?, SeriesNumber=? WHERE ImageID=?", sql.NullString{
			String: series,
			Valid:  series != "",
		}, sql.NullString{
			String: fmt.Sprintf("%v", seriesNumber),
			Valid:  seriesNumber > 0,
		}, iid)
		if err != nil {
			logE(spFmt+"Error: could not update database: %v\n", err)
			errcount++
			continue
		}

		ra, err := res.RowsAffected()
		if err != nil {
			logE(spFmt+"Error: could not update database: %v\n", err)
			errcount++
			continue
		}

		if ra > 1 {
			logE(spFmt + "Warn: more than one match in database for ImageID\n")
		} else if ra < 1 {
			logE(spFmt + "Error: could not update database: no entry in database for book (the kobo may still need to import the book)\n")
			errcount++
			continue
		}

		updated++
	}

	time.Sleep(time.Second)
	log("\nFinished updating metadata. %d updated, %d without metadata, %d errored.\n", updated, nometa, errcount)

	if runtime.GOOS == "windows" {
		time.Sleep(time.Second * 2)
	}
}
<|endoftext|>


<commit_before>package server

import (
	"github.com/talbor49/HoneyBee/beehive"
	"github.com/talbor49/HoneyBee/grammar"
	"log"
	"math/rand"
)

// in the background, clean "cold" (unused) records from RAM

// RULE OF THUMB - UPDATE LOGS WHATEVER YOU
// current decision - don't compress keys, only compress values

func processDeleteRequest(req DeleteRequest) (response grammar.Response) {
	response.Type = grammar.DELETE_RESPONSE
	status, err := beehive.DeleteFromHardDriveBucket(req.Object, req.ObjectType, req.Conn.Bucket)
	response.Status = status
	response.Data = err.Error()
	return
}

func processGetRequest(req GetRequest) (response grammar.Response) {
	/*
		if IS IN RAM {
			return FROM RAM
		} ELSE IF IS IN HARD DISK {
			// calculate if record is hot enough to be put in RAM
			return FROM HARD DISK
		} else {
			return NOT FOUND
		}
	*/
	response.Type = grammar.GET_RESPONSE
	if req.Conn.Bucket == "" {
		response.Status = grammar.RESP_STATUS_ERR_UNAUTHORIZED
		return
	}

	data, err := beehive.ReadFromHardDriveBucket(req.Key, req.Conn.Bucket)
	if err != nil {
		response.Status = grammar.RESP_STATUS_ERR_KEY_NOT_FOUND
		return
	}
	response.Status = grammar.RESP_STATUS_SUCCESS
	response.Data = data
	return
}

func processSetRequest(req SetRequest) (response grammar.Response) {
	/*
		FIRST:
			// DECIDE IF TO KEEP A POINTER TO THE VALUE IN MEMORY OR THE VALUE OF ITSELF
			PUT IN RAM
			REMOVE FROM INCONSISTENTKEYS
		THEN:
			// COMPRESS VALUE WHEN WRITING TO HARD DISK
			PUT IN HARD DISK
			UPDATE CACHED MEMORY
		}
	*/

	response.Type = grammar.SET_RESPONSE
	if req.Conn.Bucket == "" {
		response.Status = grammar.RESP_STATUS_ERR_UNAUTHORIZED
		return
	}

	log.Printf("Setting %s->%s in bucket %s", req.Key, req.Value, req.Conn.Bucket)
	// Write to hard disk
	status, err := beehive.WriteToHardDriveBucket(req.Key, req.Value, req.Conn.Bucket)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processUseRequest(req UseRequest) (response grammar.Response) {
	response.Type = grammar.USE_RESPONSE
	log.Printf("Checking if there is a database at path: %s", req.BucketName)
	// If the bucket does not exist - create it.
	if beehive.BucketExists(req.BucketName) {
		req.Conn.Bucket = req.BucketName
		response.Status = grammar.RESP_STATUS_SUCCESS
	} else {
		response.Status = grammar.RESP_STATUS_ERR_NO_SUCH_BUCKET
		log.Printf("Error - no bucket named %s found on disk.", req.BucketName)
	}
	return
}

func processCreateBucketRequest(req CreateBucketRequest) (response grammar.Response) {
	response.Type = grammar.CREATE_RESPONSE

	if beehive.BucketExists(req.BucketName) {
		response.Status = grammar.RESP_STATUS_ERR_BUCKET_ALREADY_EXISTS
		return
	}

	status, err := beehive.CreateHardDriveBucket(req.BucketName)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processCreateUserRequest(req CreateUserRequest) (response grammar.Response) {
	response.Type = grammar.CREATE_RESPONSE

	saltBuffer := make([]byte, 64)
	rand.Read(saltBuffer)
	salt := string(saltBuffer)
	saltedPassword := req.Password + string(salt)
	hashedAndSaltedPassword := hash(saltedPassword)

	status, err := beehive.WriteToHardDriveBucket(req.Username, string(salt), SALTS_BUCKET)
	if err != nil {
		response.Status = status
		response.Data = err.Error()
		return
	}
	status, err = beehive.WriteToHardDriveBucket(req.Username, hashedAndSaltedPassword, USERS_BUCKET)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processAuthRequest(req AuthRequest) (response grammar.Response) {
	response.Type = grammar.AUTHORIZE_RESPONSE
	if credentialsValid(req.Username, req.Password) {
		req.Conn.Username = req.Username
		log.Printf("User logged in as: %s", req.Username)
		response.Status = grammar.RESP_STATUS_SUCCESS
	} else {
		response.Status = grammar.RESP_STATUS_ERR_WRONG_CREDENTIALS
	}
	return
}
<commit_msg>Create salt and user buckets if not exist<commit_after>package server

import (
	"github.com/talbor49/HoneyBee/beehive"
	"github.com/talbor49/HoneyBee/grammar"
	"log"
	"math/rand"
)

// in the background, clean "cold" (unused) records from RAM

// RULE OF THUMB - UPDATE LOGS WHATEVER YOU
// current decision - don't compress keys, only compress values

func processDeleteRequest(req DeleteRequest) (response grammar.Response) {
	response.Type = grammar.DELETE_RESPONSE
	status, err := beehive.DeleteFromHardDriveBucket(req.Object, req.ObjectType, req.Conn.Bucket)
	response.Status = status
	response.Data = err.Error()
	return
}

func processGetRequest(req GetRequest) (response grammar.Response) {
	/*
		if IS IN RAM {
			return FROM RAM
		} ELSE IF IS IN HARD DISK {
			// calculate if record is hot enough to be put in RAM
			return FROM HARD DISK
		} else {
			return NOT FOUND
		}
	*/
	response.Type = grammar.GET_RESPONSE
	if req.Conn.Bucket == "" {
		response.Status = grammar.RESP_STATUS_ERR_UNAUTHORIZED
		return
	}

	data, err := beehive.ReadFromHardDriveBucket(req.Key, req.Conn.Bucket)
	if err != nil {
		response.Status = grammar.RESP_STATUS_ERR_KEY_NOT_FOUND
		return
	}
	response.Status = grammar.RESP_STATUS_SUCCESS
	response.Data = data
	return
}

func processSetRequest(req SetRequest) (response grammar.Response) {
	/*
		FIRST:
			// DECIDE IF TO KEEP A POINTER TO THE VALUE IN MEMORY OR THE VALUE OF ITSELF
			PUT IN RAM
			REMOVE FROM INCONSISTENTKEYS
		THEN:
			// COMPRESS VALUE WHEN WRITING TO HARD DISK
			PUT IN HARD DISK
			UPDATE CACHED MEMORY
		}
	*/

	response.Type = grammar.SET_RESPONSE
	if req.Conn.Bucket == "" {
		response.Status = grammar.RESP_STATUS_ERR_UNAUTHORIZED
		return
	}

	log.Printf("Setting %s->%s in bucket %s", req.Key, req.Value, req.Conn.Bucket)
	// Write to hard disk
	status, err := beehive.WriteToHardDriveBucket(req.Key, req.Value, req.Conn.Bucket)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processUseRequest(req UseRequest) (response grammar.Response) {
	response.Type = grammar.USE_RESPONSE
	log.Printf("Checking if there is a database at path: %s", req.BucketName)
	// If the bucket does not exist - create it.
	if beehive.BucketExists(req.BucketName) {
		req.Conn.Bucket = req.BucketName
		response.Status = grammar.RESP_STATUS_SUCCESS
	} else {
		response.Status = grammar.RESP_STATUS_ERR_NO_SUCH_BUCKET
		log.Printf("Error - no bucket named %s found on disk.", req.BucketName)
	}
	return
}

func processCreateBucketRequest(req CreateBucketRequest) (response grammar.Response) {
	response.Type = grammar.CREATE_RESPONSE

	if beehive.BucketExists(req.BucketName) {
		response.Status = grammar.RESP_STATUS_ERR_BUCKET_ALREADY_EXISTS
		return
	}

	status, err := beehive.CreateHardDriveBucket(req.BucketName)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processCreateUserRequest(req CreateUserRequest) (response grammar.Response) {
	response.Type = grammar.CREATE_RESPONSE

	if !beehive.BucketExists(SALTS_BUCKET) {
		beehive.CreateHardDriveBucket(SALTS_BUCKET)
	}
	if !beehive.BucketExists(USERS_BUCKET) {
		beehive.CreateHardDriveBucket(USERS_BUCKET)
	}

	saltBuffer := make([]byte, 64)
	rand.Read(saltBuffer)
	salt := string(saltBuffer)
	saltedPassword := req.Password + string(salt)
	hashedAndSaltedPassword := hash(saltedPassword)

	status, err := beehive.WriteToHardDriveBucket(req.Username, string(salt), SALTS_BUCKET)
	if err != nil {
		response.Status = status
		response.Data = err.Error()
		return
	}
	status, err = beehive.WriteToHardDriveBucket(req.Username, hashedAndSaltedPassword, USERS_BUCKET)
	response.Status = status
	if err != nil {
		response.Data = err.Error()
	}
	return
}

func processAuthRequest(req AuthRequest) (response grammar.Response) {
	response.Type = grammar.AUTHORIZE_RESPONSE
	if credentialsValid(req.Username, req.Password) {
		req.Conn.Username = req.Username
		log.Printf("User logged in as: %s", req.Username)
		response.Status = grammar.RESP_STATUS_SUCCESS
	} else {
		response.Status = grammar.RESP_STATUS_ERR_WRONG_CREDENTIALS
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"math"
	"crypto/rand"
	"strings"
	"sync"
	"log"
	"strconv"

	"golang.org/x/crypto/scrypt"
)

//Some constants
var MaxInt int64 = int64(math.Pow(2, 62))

//Some global variables
var salt []byte = []byte("")
var tokenMap map[string]Token = make(map[string]Token)
var authMutex sync.RWMutex = sync.RWMutex{}

//Toke structure
type Token struct {
	Identifier     string   `json:"identifier"`
	Hash           []byte   `json:"hash"`
	ReadPermission []string `json:"readPermission"`
	UploadNumber   int64    `json:"uploadNumber"`
	UploadSize     int64    `json:"uploadSize"`
	OwnedFiles     []string `json:"ownedFiles"`
	GrantToken     bool     `json"grantToken"`
	Readers        []string `json:"readers"`
	Equals         []string `json:equals`
	sessionIdHash  []byte
}

//SerializeTokenMap serializez the global token map
func SerializeTokenMap() []byte {
	var serialization string
	var stringifiedTokens []string = []string{}
	for _, token := range tokenMap {
		stringifiedTokens = append(stringifiedTokens, string(token.Serialize()))
	}
	serialization = strings.Join(stringifiedTokens, "#|#")
	return []byte(serialization)
}

//DeserializeToken deserializez a byte array into a token map
func DeserializeTokenMap(serialization []byte) {
	tokenArr := strings.Split(string(serialization), "#|#")
	for _, serializedToken := range tokenArr {
		token := DeserializeToken([]byte(serializedToken))
		tokenMap[token.Identifier] = token
	}
}

//IsOwner
func (token *Token) IsOwner(filename string) bool {
	for _, file := range token.OwnedFiles {
		if file == filename {
			return true
		}
	}

	for _, equal := range token.Equals {
		for _, file := range tokenMap[equal].OwnedFiles {
			if file == filename {
				return true
			}
		}
	}

	for _, reader := range token.Readers {
		for _, file := range tokenMap[reader].OwnedFiles {
			if file == filename {
				return true
			}
		}
	}

	return false
}

//IsReader
func (token *Token) IsReader(filename string) bool {
	if token.IsOwner(filename) {
		return true
	}

	for _, equal := range token.Equals {
		for _, file := range tokenMap[equal].ReadPermission {
			if file == filename {
				return true
			}
		}
	}

	for _, reader := range token.Readers {
		for _, file := range tokenMap[reader].ReadPermission {
			if file == filename {
				return true
			}
		}
	}

	for _, file := range token.ReadPermission {
		if file == filename {
			return true
		}
	}

	//Finally check if its public
	return IsPublic(filename)
}

//Serialize gives a string (as a byte slice) represntation of a Token struct
func (token *Token) Serialize() []byte {
	serialization, err := json.Marshal(token)
	if err != nil {
		log.Printf("There was a serialization error for a token %s", err)
	}
	return serialization
}

//DeserializeFileModel takes a byte slice and create a Token
func DeserializeToken(serialization []byte) Token {
	var newToken Token
	err := json.Unmarshal(serialization, &newToken)
	if err != nil {

	}
	return newToken
}

//MakeToken is the function that can be called to create a token
func MakeToken(identifier string, credentials string, readPermission []string, uploadSize int64, uploadNumber int64, ownedFiles []string, grantToken bool, readers []string, equals []string) Token {
	return Token{Identifier: identifier, Hash: hashCredentials(credentials), ReadPermission: readPermission, UploadNumber: uploadNumber, UploadSize: uploadSize,
		OwnedFiles: ownedFiles, GrantToken: grantToken, Readers: readers, Equals: equals}
}

func RunUnderAuthWMutex(task func(*map[string]Token) interface{}) interface{} {
	authMutex.Lock()
	result := task(&tokenMap)
	authMutex.Unlock()
	return result
}

func RunUnderAuthRMutex(task func(*map[string]Token) interface{}) interface{} {
	authMutex.RLock()
	result := task(&tokenMap)
	authMutex.RUnlock()
	return result
}

//ValidateSession checks the validty of a token and return the correspondent structure if the token is valid
func ValidateSession(identifier string, sessionId string) (bool, Token) {
	requestedToken := tokenMap[identifier]
	if bytes.Equal(hashCredentials(sessionId), requestedToken.sessionIdHash) {
		return true, requestedToken
	}
	log.Println("Someone used identifier '" + identifier + "' in order to try accessing a token for which he didn't have credentials")
	return false, requestedToken
}

//ValidateToke validates an ongoing session
func ValidateToke(identifier string, credentials string, cheat bool) (bool, string) {
	requestedToken := tokenMap[identifier]
	if bytes.Equal(hashCredentials(credentials), requestedToken.Hash) || cheat {
		// Previous random seed: random := rand.New(rand.NewSource(time.Now().Unix() - time.Now().UnixNano()))
		sessionIdBytes := make([]byte, 32)
		_, err := rand.Read(sessionIdBytes)
		if err != nil {
			panic(err)
			panic("This is a standard lib failure, thsi shouldn't happen, I am confused, help!, Trying again !")
			_, err := rand.Read(sessionIdBytes)
			if err != nil {
				log.Fatal("Random session id generation not working, something is terribly wrong, crashing!")
			}
		}
		//Converting directly to string => invalid cookie value
		//Converting each byte to an int should be 'random enough'
		sessionId := ""
		for _, b := range sessionIdBytes {
			sessionId += strconv.Itoa(int(b))
		}
		requestedToken.sessionIdHash = hashCredentials(sessionId)
		tokenMap[identifier] = requestedToken
		return true, sessionId
	}
	log.Println("Someone used identifier '" + identifier + "' in order to try accessing a token for which he didn't have credentials")
	return false, ""
}

//IsPublic tells us if a file is public once the token map has been initialized
func IsPublic(filename string) bool {
	publicToken := tokenMap["public"]
	for _, val := range publicToken.ReadPermission {
		if filename == val {
			return true
		}
	}
	return false
}

//UploadToken uploads the token map

//hashCredentials is a function used for hashing a string
//It will be used internally for storing of all tokens and/or passwords until the need arises for better security
func hashCredentials(credentials string) []byte {
	//Using values recommended on https://godoc.org/golang.org/x/crypto/scrypt  for N, r,p
	//Generating a 32-byte hash key (again, since that's the example)
	hash, err := scrypt.Key([]byte(credentials), salt, 16384, 8, 1, 32)
	//Hashing of credentials fails, this shouldn't happen and I don't know how to handle it, crashing app
	if err != nil {
		log.Fatal(err)
	}
	return hash
}

func InitializeAuthentication(theSalt []byte) {
	salt = theSalt
}

//InitializeAdmin is a function to be used for debuging, creates the user admin - admin
func InitializeAdmin(theSalt []byte, name string, password string) {
	adminToken := MakeToken(name, password, []string{}, MaxInt, MaxInt, []string{}, true, []string{}, []string{})
	publicToken := MakeToken("public", "", []string{}, 0, 0, []string{}, false, []string{}, []string{})
	if _, ok := tokenMap[adminToken.Identifier]; !ok {
		tokenMap[adminToken.Identifier] = adminToken
	}
	if _, ok := tokenMap[publicToken.Identifier]; !ok {
		tokenMap[publicToken.Identifier] = publicToken
	}
}
<commit_msg>just making sure all is comitted<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"math"
	"crypto/rand"
	"strings"
	"sync"
	"log"
	"strconv"
	"encoding/hex"

	"golang.org/x/crypto/scrypt"
)

//Some constants
var MaxInt int64 = int64(math.Pow(2, 62))

//Some global variables
var salt []byte = []byte("")
var tokenMap map[string]Token = make(map[string]Token)
var authMutex sync.RWMutex = sync.RWMutex{}

//Toke structure
type Token struct {
	Identifier     string   `json:"identifier"`
	Hash           []byte   `json:"hash"`
	ReadPermission []string `json:"readPermission"`
	UploadNumber   int64    `json:"uploadNumber"`
	UploadSize     int64    `json:"uploadSize"`
	OwnedFiles     []string `json:"ownedFiles"`
	GrantToken     bool     `json"grantToken"`
	Readers        []string `json:"readers"`
	Equals         []string `json:equals`
	sessionIdHash  []byte
}

//SerializeTokenMap serializez the global token map
func SerializeTokenMap() []byte {
	var serialization string
	var stringifiedTokens []string = []string{}
	for _, token := range tokenMap {
		stringifiedTokens = append(stringifiedTokens, string(token.Serialize()))
	}
	serialization = strings.Join(stringifiedTokens, "#|#")
	return []byte(serialization)
}

//DeserializeToken deserializez a byte array into a token map
func DeserializeTokenMap(serialization []byte) {
	tokenArr := strings.Split(string(serialization), "#|#")
	for _, serializedToken := range tokenArr {
		token := DeserializeToken([]byte(serializedToken))
		tokenMap[token.Identifier] = token
	}
}

//IsOwner
func (token *Token) IsOwner(filename string) bool {
	for _, file := range token.OwnedFiles {
		if file == filename {
			return true
		}
	}

	for _, equal := range token.Equals {
		for _, file := range tokenMap[equal].OwnedFiles {
			if file == filename {
				return true
			}
		}
	}

	for _, reader := range token.Readers {
		for _, file := range tokenMap[reader].OwnedFiles {
			if file == filename {
				return true
			}
		}
	}

	return false
}

//IsReader
func (token *Token) IsReader(filename string) bool {
	if token.IsOwner(filename) {
		return true
	}

	for _, equal := range token.Equals {
		for _, file := range tokenMap[equal].ReadPermission {
			if file == filename {
				return true
			}
		}
	}

	for _, reader := range token.Readers {
		for _, file := range tokenMap[reader].ReadPermission {
			if file == filename {
				return true
			}
		}
	}

	for _, file := range token.ReadPermission {
		if file == filename {
			return true
		}
	}

	//Finally check if its public
	return IsPublic(filename)
}

//Serialize gives a string (as a byte slice) represntation of a Token struct
func (token *Token) Serialize() []byte {
	serialization, err := json.Marshal(token)
	if err != nil {
		log.Printf("There was a serialization error for a token %s", err)
	}
	return serialization
}

//DeserializeFileModel takes a byte slice and create a Token
func DeserializeToken(serialization []byte) Token {
	var newToken Token
	err := json.Unmarshal(serialization, &newToken)
	if err != nil {

	}
	return newToken
}

//MakeToken is the function that can be called to create a token
func MakeToken(identifier string, credentials string, readPermission []string, uploadSize int64, uploadNumber int64, ownedFiles []string, grantToken bool, readers []string, equals []string) Token {
	return Token{Identifier: identifier, Hash: hashCredentials(credentials), ReadPermission: readPermission, UploadNumber: uploadNumber, UploadSize: uploadSize,
		OwnedFiles: ownedFiles, GrantToken: grantToken, Readers: readers, Equals: equals}
}

func RunUnderAuthWMutex(task func(*map[string]Token) interface{}) interface{} {
	authMutex.Lock()
	result := task(&tokenMap)
	authMutex.Unlock()
	return result
}

func RunUnderAuthRMutex(task func(*map[string]Token) interface{}) interface{} {
	authMutex.RLock()
	result := task(&tokenMap)
	authMutex.RUnlock()
	return result
}

//ValidateSession checks the validty of a token and return the correspondent structure if the token is valid
func ValidateSession(identifier string, sessionId string) (bool, Token) {
	requestedToken := tokenMap[identifier]
	if bytes.Equal(hashCredentials(sessionId), requestedToken.sessionIdHash) {
		return true, requestedToken
	}
	log.Println("Someone used identifier '" + identifier + "' in order to try accessing a token for which he didn't have credentials")
	return false, requestedToken
}

//ValidateToke validates an ongoing session
func ValidateToke(identifier string, credentials string, cheat bool) (bool, string) {
	requestedToken := tokenMap[identifier]
	if bytes.Equal(hashCredentials(credentials), requestedToken.Hash) || cheat {
		// Previous random seed: random := rand.New(rand.NewSource(time.Now().Unix() - time.Now().UnixNano()))
		sessionIdBytes := make([]byte, 32)
		_, err := rand.Read(sessionIdBytes)
		if err != nil {
			panic(err)
			panic("This is a standard lib failure, thsi shouldn't happen, I am confused, help!, Trying again !")
			_, err := rand.Read(sessionIdBytes)
			if err != nil {
				log.Fatal("Random session id generation not working, something is terribly wrong, crashing!")
			}
		}
		//Converting directly to string => invalid cookie value
		//Converting each byte to an int should be 'random enough'
		sessionId := hex.EncodeToString(sessionIdBytes)
		requestedToken.sessionIdHash = hashCredentials(sessionId)
		tokenMap[identifier] = requestedToken
		return true, sessionId
	}
	log.Println("Someone used identifier '" + identifier + "' in order to try accessing a token for which he didn't have credentials")
	return false, ""
}

//IsPublic tells us if a file is public once the token map has been initialized
func IsPublic(filename string) bool {
	publicToken := tokenMap["public"]
	for _, val := range publicToken.ReadPermission {
		if filename == val {
			return true
		}
	}
	return false
}

//UploadToken uploads the token map

//hashCredentials is a function used for hashing a string
//It will be used internally for storing of all tokens and/or passwords until the need arises for better security
func hashCredentials(credentials string) []byte {
	//Using values recommended on https://godoc.org/golang.org/x/crypto/scrypt  for N, r,p
	//Generating a 32-byte hash key (again, since that's the example)
	hash, err := scrypt.Key([]byte(credentials), salt, 16384, 8, 1, 32)
	//Hashing of credentials fails, this shouldn't happen and I don't know how to handle it, crashing app
	if err != nil {
		log.Fatal(err)
	}
	return hash
}

func InitializeAuthentication(theSalt []byte) {
	salt = theSalt
}

//InitializeAdmin is a function to be used for debuging, creates the user admin - admin
func InitializeAdmin(theSalt []byte, name string, password string) {
	adminToken := MakeToken(name, password, []string{}, MaxInt, MaxInt, []string{}, true, []string{}, []string{})
	publicToken := MakeToken("public", "", []string{}, 0, 0, []string{}, false, []string{}, []string{})
	if _, ok := tokenMap[adminToken.Identifier]; !ok {
		tokenMap[adminToken.Identifier] = adminToken
	}
	if _, ok := tokenMap[publicToken.Identifier]; !ok {
		tokenMap[publicToken.Identifier] = publicToken
	}
}
<|endoftext|>