<commit_before>// tagfile_test
package bagins_test

import (
	"fmt"
	"github.com/APTrust/bagins"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"
)

// Field TESTS

func TestNewField(t *testing.T) {
	exp_label := "test-field"
	exp_value := "this is my test"
	f := bagins.NewTagField(exp_label, exp_value)

	if f == nil { // This should test type but for the life of me I can't figure out how.
		t.Error("Tag Field object not returned")
	}
	if f.Label() != exp_label {
		t.Error("Tag Field label not created properly!")
	}
	if f.Value() != exp_value {
		t.Error("Tag Field value not created properly!")
	}
}

// Using a single test for set and get labels since they rely on one another.
func TestLabel(t *testing.T) {
	f := bagins.NewTagField("label", "value")
	if f.Label() != "label" {
		t.Error("Tag Field label not created properly!")
	}

	f.SetLabel("new-label")
	if f.Label() != "new-label" {
		t.Error("Tag Field label not reset properly!")
	}

	if f.Value() != "value" {
		t.Error("Tag Field value not set or retained properly when label changed!")
	}
}

// Using single test for set and get values since they rely on one another.
func TestValue(t *testing.T) {
	f := bagins.NewTagField("label", "value")
	if f.Value() != "value" {
		t.Error("Tag Field value not created properly!")
	}

	f.SetValue("new value")
	if f.Value() != "new value" {
		t.Error("Tag Field value not set or read properly!")
	}

	if f.Label() != "label" {
		t.Error("Tag Field label value not retained when value set!")
	}
}

// FieldList TESTS

func TestNewTagFieldList(t *testing.T) {
	var tfl interface{} = bagins.NewTagFieldList()
	if _, ok := tfl.(*bagins.TagFieldList); !ok {
		t.Error("TagFieldList not returned!")
	}
}

// Doing a unified test for Fields and SetFields
func TestFields(t *testing.T) {

	fl := bagins.NewTagFieldList()
	test_len := func(l int) { // DRY!
		if len(fl.Fields()) != l {
			t.Error("Expected TagField length of", l, "but", len(fl.Fields()), "was returned!")
		}
	}

	test_len(0)

	newFields := []bagins.TagField{
		*bagins.NewTagField("label1", "value1"),
		*bagins.NewTagField("label2", "value2"),
		*bagins.NewTagField("label3", "value3"),
	}
	fl.SetFields(newFields)
	test_len(3)

	for i := 0; i < 3; i++ {
		exp := fmt.Sprintf("label%d", i+1)
		act := fl.Fields()[i].Label()
		if exp != act {
			t.Error("Expected", exp, "but returned", act)
		}
	}
}

func TestAddField(t *testing.T) {
	fl := bagins.NewTagFieldList()
	exp_len := 100
	for i := 0; i < exp_len; i++ {
		tmp := strconv.Itoa(i)
		fl.AddField(*bagins.NewTagField(tmp, tmp))
	}

	if len(fl.Fields()) != exp_len {
		t.Error("Expected", exp_len, "fields but returned", len(fl.Fields()), "!")
	}

	for i, f := range fl.Fields() {
		if f.Value() != strconv.Itoa(i) {
			t.Error("Expected field value of", strconv.Itoa(i), "but returned", f.Value(), "!")
		}
	}
}

func TestRemoveField(t *testing.T) {
	fl := bagins.NewTagFieldList()
	test_len := func(l int) { // DRY again!
		if len(fl.Fields()) != l {
			t.Error("Expected TagField length of", l, "but", len(fl.Fields()), "was returned!")
		}
	}

	for i := 0; i < 100; i++ {
		tmp := strconv.Itoa(i)
		fl.AddField(*bagins.NewTagField(tmp, tmp))
	}
	test_len(100)

	// Should error if removing out of range.
	if err := fl.RemoveField(-6); err == nil {
		t.Error("Trying to remove negative index does not produce expected error!")
	}
	if err := fl.RemoveField(100); err == nil {
		t.Error("Trying to remove out of bound index does not produce expected error!")
	}
	test_len(100)

	// Remove every other one of the first 25 and test
	for i := 0; i < 50; i++ {
		if i%2 == 0 {
			fl.RemoveField(i)
		}
	}
	test_len(75)

}

// TagFile TESTS

func TestNewTagFile(t *testing.T) {
	_, err := bagins.NewTagFile("tagfile.txt")
	if err != nil {
		t.Error("Tagfile raised an error incorrectly!")
	}
	_, err = bagins.NewTagFile(".tagfile")
	if err == nil {
		t.Error("Bag tagfile name did not raise error as expected.")
	}
}

func TestReadTagFile(t *testing.T) {
	// Expected Data
	exp_list := [][]string{
		[]string{"description", strings.Repeat("test ", 40)},
		[]string{"title", "This is my title"},
		[]string{"description", strings.Repeat("more ", 80)},
	}

	// Prep the test file
	testPath := filepath.Join(os.TempDir(), "_GOTEST_READTAGFILE_bagit.txt")
	fmt.Println(testPath)
	tagFile, _ := bagins.NewTagFile(testPath)
	for _, exp := range exp_list {
		tagFile.Data.AddField(*bagins.NewTagField(exp[0], exp[1]))
	}
	tagFile.Create()
	defer os.Remove(testPath)

	// Open and test parsing the file.
	tf, errs := bagins.ReadTagFile(testPath)
	for _, err := range errs {
		t.Error(err)
	}
	if len(tf.Data.Fields()) != 3 {
		t.Error("Expected 3 but returned", len(tf.Data.Fields()), "fields!")
	}

	fields := tagFile.Data.Fields()
	for idx, exp := range exp_list {
		if fields[idx].Label() != exp[0] {
			t.Error("Tag field", idx, "label", fields[idx].Label(), "is not expected value of", exp[0])
		}
		if fields[idx].Value() != exp[1] {
			t.Error("Tag field", idx, "value", fields[idx].Value(), "is not expected value of", exp[1])
		}
	}
}

func TestTagFileCreate(t *testing.T) {
	testPath := filepath.Join(os.TempDir(), "golang_test_tagfiles/_GOTEST_bagit.txt")
	tagFile, _ := bagins.NewTagFile(testPath)
	tagFile.Data.AddField(*bagins.NewTagField("BagIt-Version", "A metadata element MUST consist of a label, a colon, and a value, each separated by optional whitespace.  It is RECOMMENDED that lines not exceed 79 characters in length.  Long values may be continued onto the next line by inserting a newline (LF), a carriage return (CR), or carriage return plus newline (CRLF) and indenting the next line with linear white space (spaces or tabs)."))
	tagFile.Data.AddField(*bagins.NewTagField("Tag-File-Character-Encodeing", "UTF-8"))

	err := tagFile.Create()
	if err != nil {
		t.Error(err)
	}
	if _, err := os.Stat(testPath); err != nil {
		t.Error("File and path", testPath, "not created!")
	}
	os.RemoveAll(filepath.Dir(testPath))
}

func TestFormatField(t *testing.T) {
	resultString, err := bagins.FormatField("tst", strings.Repeat("test ", 20))
	if err != nil {
		t.Error(err)
	}
	exp := 80
	act := strings.Index(resultString, "\n")
	if exp != act {
		t.Errorf("Found newline at %d but expected %d", act, exp)
	}
}
<commit_msg>Removed bad print statement.<commit_after>// tagfile_test
package bagins_test

import (
	"fmt"
	"github.com/APTrust/bagins"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"
)

// Field TESTS

func TestNewField(t *testing.T) {
	exp_label := "test-field"
	exp_value := "this is my test"
	f := bagins.NewTagField(exp_label, exp_value)

	if f == nil { // This should test type but for the life of me I can't figure out how.
		t.Error("Tag Field object not returned")
	}
	if f.Label() != exp_label {
		t.Error("Tag Field label not created properly!")
	}
	if f.Value() != exp_value {
		t.Error("Tag Field value not created properly!")
	}
}

// Using a single test for set and get labels since they rely on one another.
func TestLabel(t *testing.T) {
	f := bagins.NewTagField("label", "value")
	if f.Label() != "label" {
		t.Error("Tag Field label not created properly!")
	}

	f.SetLabel("new-label")
	if f.Label() != "new-label" {
		t.Error("Tag Field label not reset properly!")
	}

	if f.Value() != "value" {
		t.Error("Tag Field value not set or retained properly when label changed!")
	}
}

// Using single test for set and get values since they rely on one another.
func TestValue(t *testing.T) {
	f := bagins.NewTagField("label", "value")
	if f.Value() != "value" {
		t.Error("Tag Field value not created properly!")
	}

	f.SetValue("new value")
	if f.Value() != "new value" {
		t.Error("Tag Field value not set or read properly!")
	}

	if f.Label() != "label" {
		t.Error("Tag Field label value not retained when value set!")
	}
}

// FieldList TESTS

func TestNewTagFieldList(t *testing.T) {
	var tfl interface{} = bagins.NewTagFieldList()
	if _, ok := tfl.(*bagins.TagFieldList); !ok {
		t.Error("TagFieldList not returned!")
	}
}

// Doing a unified test for Fields and SetFields
func TestFields(t *testing.T) {

	fl := bagins.NewTagFieldList()
	test_len := func(l int) { // DRY!
		if len(fl.Fields()) != l {
			t.Error("Expected TagField length of", l, "but", len(fl.Fields()), "was returned!")
		}
	}

	test_len(0)

	newFields := []bagins.TagField{
		*bagins.NewTagField("label1", "value1"),
		*bagins.NewTagField("label2", "value2"),
		*bagins.NewTagField("label3", "value3"),
	}
	fl.SetFields(newFields)
	test_len(3)

	for i := 0; i < 3; i++ {
		exp := fmt.Sprintf("label%d", i+1)
		act := fl.Fields()[i].Label()
		if exp != act {
			t.Error("Expected", exp, "but returned", act)
		}
	}
}

func TestAddField(t *testing.T) {
	fl := bagins.NewTagFieldList()
	exp_len := 100
	for i := 0; i < exp_len; i++ {
		tmp := strconv.Itoa(i)
		fl.AddField(*bagins.NewTagField(tmp, tmp))
	}

	if len(fl.Fields()) != exp_len {
		t.Error("Expected", exp_len, "fields but returned", len(fl.Fields()), "!")
	}

	for i, f := range fl.Fields() {
		if f.Value() != strconv.Itoa(i) {
			t.Error("Expected field value of", strconv.Itoa(i), "but returned", f.Value(), "!")
		}
	}
}

func TestRemoveField(t *testing.T) {
	fl := bagins.NewTagFieldList()
	test_len := func(l int) { // DRY again!
		if len(fl.Fields()) != l {
			t.Error("Expected TagField length of", l, "but", len(fl.Fields()), "was returned!")
		}
	}

	for i := 0; i < 100; i++ {
		tmp := strconv.Itoa(i)
		fl.AddField(*bagins.NewTagField(tmp, tmp))
	}
	test_len(100)

	// Should error if removing out of range.
	if err := fl.RemoveField(-6); err == nil {
		t.Error("Trying to remove negative index does not produce expected error!")
	}
	if err := fl.RemoveField(100); err == nil {
		t.Error("Trying to remove out of bound index does not produce expected error!")
	}
	test_len(100)

	// Remove every other one of the first 25 and test
	for i := 0; i < 50; i++ {
		if i%2 == 0 {
			fl.RemoveField(i)
		}
	}
	test_len(75)

}

// TagFile TESTS

func TestNewTagFile(t *testing.T) {
	_, err := bagins.NewTagFile("tagfile.txt")
	if err != nil {
		t.Error("Tagfile raised an error incorrectly!")
	}
	_, err = bagins.NewTagFile(".tagfile")
	if err == nil {
		t.Error("Bag tagfile name did not raise error as expected.")
	}
}

func TestReadTagFile(t *testing.T) {
	// Expected Data
	exp_list := [][]string{
		[]string{"description", strings.Repeat("test ", 40)},
		[]string{"title", "This is my title"},
		[]string{"description", strings.Repeat("more ", 80)},
	}

	// Prep the test file
	testPath := filepath.Join(os.TempDir(), "_GOTEST_READTAGFILE_bagit.txt")
	tagFile, _ := bagins.NewTagFile(testPath)
	for _, exp := range exp_list {
		tagFile.Data.AddField(*bagins.NewTagField(exp[0], exp[1]))
	}
	tagFile.Create()
	defer os.Remove(testPath)

	// Open and test parsing the file.
	tf, errs := bagins.ReadTagFile(testPath)
	for _, err := range errs {
		t.Error(err)
	}
	if len(tf.Data.Fields()) != 3 {
		t.Error("Expected 3 but returned", len(tf.Data.Fields()), "fields!")
	}

	fields := tagFile.Data.Fields()
	for idx, exp := range exp_list {
		if fields[idx].Label() != exp[0] {
			t.Error("Tag field", idx, "label", fields[idx].Label(), "is not expected value of", exp[0])
		}
		if fields[idx].Value() != exp[1] {
			t.Error("Tag field", idx, "value", fields[idx].Value(), "is not expected value of", exp[1])
		}
	}
}

func TestTagFileCreate(t *testing.T) {
	testPath := filepath.Join(os.TempDir(), "golang_test_tagfiles/_GOTEST_bagit.txt")
	tagFile, _ := bagins.NewTagFile(testPath)
	tagFile.Data.AddField(*bagins.NewTagField("BagIt-Version", "A metadata element MUST consist of a label, a colon, and a value, each separated by optional whitespace.  It is RECOMMENDED that lines not exceed 79 characters in length.  Long values may be continued onto the next line by inserting a newline (LF), a carriage return (CR), or carriage return plus newline (CRLF) and indenting the next line with linear white space (spaces or tabs)."))
	tagFile.Data.AddField(*bagins.NewTagField("Tag-File-Character-Encodeing", "UTF-8"))

	err := tagFile.Create()
	if err != nil {
		t.Error(err)
	}
	if _, err := os.Stat(testPath); err != nil {
		t.Error("File and path", testPath, "not created!")
	}
	os.RemoveAll(filepath.Dir(testPath))
}

func TestFormatField(t *testing.T) {
	resultString, err := bagins.FormatField("tst", strings.Repeat("test ", 20))
	if err != nil {
		t.Error(err)
	}
	exp := 80
	act := strings.Index(resultString, "\n")
	if exp != act {
		t.Errorf("Found newline at %d but expected %d", act, exp)
	}
}
<|endoftext|>


<commit_before>package robots

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"time"
)

type BijinBot struct {
}

type BijinConfiguration struct {
	Timezone string `json:"timezone"`
}

var BijinConfig = new(BijinConfiguration)

func init() {
	flag.Parse()
	configFile := filepath.Join(*ConfigDirectory, "bijin.json")
	if _, err := os.Stat(configFile); err == nil {
		config, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Printf("ERROR: Error opening bijin config: %s", err)
			return
		}
		err = json.Unmarshal(config, BijinConfig)
		if err != nil {
			log.Printf("ERROR: Error parsing bijin config: %s", err)
			return
		}
	} else {
		log.Printf("WARNING: Could not find configuration file bijin.json in %s", *ConfigDirectory)
	}
	RegisterRobot("/bijin", func() (robot Robot) { return new(BijinBot) })
}

func (r BijinBot) Run(command *SlashCommand) (slashCommandImmediateReturn string) {
	go r.DeferredAction(command)
	return ""
}

func (r BijinBot) DeferredAction(command *SlashCommand) {
	response := new(IncomingWebhook)
	response.Channel = command.Channel_ID
	response.Username = "Bijin Bot"
	response.Icon_Emoji = ":ghost:"
	response.Unfurl_Links = true

	rand.Seed(time.Now().UTC().UnixNano())
	t := time.Now()
	if BijinConfig.Timezone != "" {
		loc, err := time.LoadLocation(BijinConfig.Timezone)
		if err == nil {
			t = t.In(loc)
		} else {
			response.Text = fmt.Sprintf("ERROR: Unknown timezone (%s) - Serving UTC", BijinConfig.Timezone)
			MakeIncomingWebhookCall(response)
		}
	} else {
		response.Text = fmt.Sprintf("WARNING: No timezone set - Serving UTC")
		MakeIncomingWebhookCall(response)
	}
	hours := fmt.Sprintf("%02d", t.Hour())
	minutes := fmt.Sprintf("%02d", t.Minute())
	links := []string{"http://www.bijint.com/jp/tokei_images/", "http://www.bijint.com/jp/img/clk/"}
	response.Text = fmt.Sprintf("<@%s|%s> Here's your <%s%s%s.jpg|%s:%s 美人>", command.User_ID, command.User_Name, links[rand.Intn(len(links))], hours, minutes, hours, minutes)
	MakeIncomingWebhookCall(response)
}

func (r BijinBot) Description() (description string) {
	return "Displays the current time's 美人 (hope bijint.com doesn't get mad me)\n\tUsage: /bijin\n\tExpected Response: (beautiful woman)"
}
<commit_msg>Added more bijin<commit_after>package robots

import (
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "math/rand"
    "os"
    "path/filepath"
    "strings"
    "time"
)

type BijinBot struct {
}

type BijinConfiguration struct {
    Timezone string `json:"timezone"`
}

var BijinConfig = new(BijinConfiguration)

func init() {
    flag.Parse()
    configFile := filepath.Join(*ConfigDirectory, "bijin.json")
    if _, err := os.Stat(configFile); err == nil {
        config, err := ioutil.ReadFile(configFile)
        if err != nil {
            log.Printf("ERROR: Error opening bijin config: %s", err)
            return
        }
        err = json.Unmarshal(config, BijinConfig)
        if err != nil {
            log.Printf("ERROR: Error parsing bijin config: %s", err)
            return
        }
    } else {
        log.Printf("WARNING: Could not find configuration file bijin.json in %s", *ConfigDirectory)
    }
    RegisterRobot("/bijin", func() (robot Robot) { return new(BijinBot) })
}

func (r BijinBot) Run(command *SlashCommand) (slashCommandImmediateReturn string) {
    go r.DeferredAction(command)
    return ""
}

func (r BijinBot) DeferredAction(command *SlashCommand) {
    response := new(IncomingWebhook)
    response.Channel = command.Channel_ID
    response.Username = "Bijin Bot"
    response.Icon_Emoji = ":ghost:"
    response.Unfurl_Links = true

    rand.Seed(time.Now().UTC().UnixNano())
    t := time.Now()
    if BijinConfig.Timezone != "" {
        loc, err := time.LoadLocation(BijinConfig.Timezone)
        if err == nil {
            t = t.In(loc)
        } else {
            response.Text = fmt.Sprintf("ERROR: Unknown timezone (%s) - Serving UTC", BijinConfig.Timezone)
            MakeIncomingWebhookCall(response)
        }
    } else {
        response.Text = fmt.Sprintf("WARNING: No timezone set - Serving UTC")
        MakeIncomingWebhookCall(response)
    }
    hours := fmt.Sprintf("%02d", t.Hour())
    minutes := fmt.Sprintf("%02d", t.Minute())
    region, link := GetLink(strings.ToLower(strings.TrimSpace(command.Text)))
    response.Text = fmt.Sprintf("<@%s|%s> Here's your (%s) <%s%s%s.jpg|%s:%s 美人> ", command.User_ID, command.User_Name, strings.ToTitle(region), link, hours, minutes, hours, minutes)
    MakeIncomingWebhookCall(response)
}

func GetLink(region string) (string, string) {
    links := map[string]string{"japan": "http://www.bijint.com/jp/tokei_images/",
                            "clk": "http://www.bijint.com/jp/img/clk/",
                            "2012": "http://www.bijint.com/2012jp/",
                            "2011": "http://www.bijint.com/2011jp/",
                            "tokyo": "http://www.bijint.com/tokyo/tokei_images/",
                            "hokkaido": "http://www.bijint.com/hokkaido/tokei_images/",
                            "sendai": "http://www.bijint.com/sendai/tokei_images/",
                            "akita": "http://www.bijint.com/akita/tokei_images/",
                            "gunma": "http://www.bijint.com/gunma/tokei_images/",
                            "niigata": "http://www.bijint.com/niiagata/tokei_images/",
                            "kanazawa": "http://www.bijint.com/kanazawa/tokei_images/",
                            "fukui": "http://www.bijint.com/fukui/tokei_images/",
                            "nagoya": "http://www.bijint.com/nagoya/tokei_images/",
                            "kyoto": "http://www.bijint.com/kyoto/tokei_images/",
                            "osaka": "http://www.bijint.com/osaka/tokei_images/",
                            "kobe": "http://www.bijint.com/kobe/tokei_images/",
                            "okayama": "http://www.bijint.com/okayama/tokei_images/",
                            "kagawa": "http://www.bijint.com/kagawa/tokei_images/",
                            "fukuoka": "http://www.bijint.com/fukuoka/tokei_images/",
                            "kagoshima": "http://www.bijint.com/kagoshima/tokei_images/",
                            "okinawa": "http://www.bijint.com/okinawa/tokei_images/",
                            "kumamoto": "http://www.bijint.com/kumamoto/tokei_images/",
                            "saitama": "http://www.bijint.com/saitama/tokei_images/",
                            "hiroshima": "http://www.bijint.com/hiroshima/tokei_images/",
                            "chiba": "http://www.bijint.com/chiba/tokei_images/",
                            "nara": "http://www.bijint.com/nara/tokei_images/",
                            "yamaguchi": "http://www.bijint.com/yamaguchi/tokei_images/",
                            "nagano": "http://www.bijint.com/nagano/tokei_images/",
                            "shizuoka": "http://www.bijint.com/shizuoka/tokei_images/",
                            "miyazaki": "http://www.bijint.com/miyazaki/tokei_images/",
                            "tottori": "http://www.bijint.com/tottori/tokei_images/",
                            "iwate": "http://www.bijint.com/iwate/tokei_images/",
                            "ibaraki": "http://www.bijint.com/ibaraki/tokei_images/",
                            "tochigi": "http://www.bijint.com/tochigi/tokei_images/",
                            "taiwan": "http://www.bijint.com/taiwan/tokei_images/",
                            "hawaii": "http://www.bijint.com/hawaii/tokei_images/",
                            "seifuku": "http://www.bijint.com/seifuku/tokei_images/",
                            "megane": "http://www.bijint.com/megane/tokei_images/",
                            "sara": "http://www.bijint.com/sara/tokei_images/",
                            "hairstyle": "http://www.bijint.com/hairstyle/tokei_images/",
                            "asahi": "http://www.bijint.com/tv-asahi/tokei_images/",
                            "circuit": "http://www.bijint.com/cc/tokei_images/",
                            "hanayome": "http://www.bijint.com/hanayome/tokei_images/",
                            "waseda": "http://www.bijint.com/waseda/tokei_images/",
                            }
    if link, ok := links[region]; ok {
        return region, link
    } else {
        for region, link := range links {
            return region, link
        }
    }
    return "japan", links["japan"]
}

func (r BijinBot) Description() (description string) {
    return "Displays the current time's 美人 (hope bijint.com doesn't get mad me)\n\tUsage: /bijin\n\tExpected Response: (beautiful woman)"
}
<|endoftext|>


<commit_before>package storage

import (
	"fmt"
	"github.com/viant/endly/model/msg"
	"strings"
)

/*
Message events control runner reporter and stdout
*/

//Items returns tag messages
func (r *RemoveRequest) Messages() []*msg.Message {
	if len(r.Assets) == 0 {
		return []*msg.Message{}
	}
	var fragments = make([]*msg.Styled, 0)
	for _, resource := range r.Assets {
		fragments = append(fragments, msg.NewStyled(fmt.Sprintf("SourceURL: %v", resource.URL), msg.MessageStyleInput))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Remove", msg.MessageStyleGeneric),
		fragments...),
	}
}

//Items returns event messages
func (r *UploadRequest) Messages() []*msg.Message {
	if r.Dest == nil {
		return []*msg.Message{}
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Upload", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("SourcKey: %v", r.SourceKey), msg.MessageStyleInput),
		msg.NewStyled(fmt.Sprintf("DestURL: %v", r.Dest.URL), msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *DownloadRequest) Messages() []*msg.Message {
	if r.Source == nil {
		return []*msg.Message{}
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Upload", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("Source: %v", r.Source.URL), msg.MessageStyleInput),
		msg.NewStyled(fmt.Sprintf("DestKey: %v", r.DestKey), msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *CopyRequest) Messages() []*msg.Message {
	_ = r.Init()
	if len(r.Transfers) == 0 {
		return []*msg.Message{}
	}
	var result = make([]*msg.Message, 0)
	for _, transfer := range r.Transfers {
		if transfer.Source == nil || transfer.Dest == nil {
			continue
		}
		result = append(result, msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
			msg.NewStyled("Copy", msg.MessageStyleGeneric),
			msg.NewStyled(fmt.Sprintf("compress: %v, expand: %v", transfer.Compress, transfer.Expand), msg.MessageStyleGeneric),
			msg.NewStyled(fmt.Sprintf("SourceURL: %v", transfer.Source.URL), msg.MessageStyleInput),
			msg.NewStyled(fmt.Sprintf("DestURL: %v", transfer.Dest.URL), msg.MessageStyleOutput),
		))
	}
	return result
}

//Items returns event messages
func (r *ListResponse) Messages() []*msg.Message {
	if r.Assets == nil {
		return []*msg.Message{}
	}
	assets := make([]string, 0)
	for i := range r.Assets {
		content := ""
		if len(r.Assets[i].Data) > 0 {
			content = fmt.Sprintf("\n%v\n\n", string(r.Assets[i].Data))
		}
		assets = append(assets, fmt.Sprintf("%s %v%v", r.Assets[i].Mode.String(), r.Assets[i].Name, content))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("List", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("Source: %v", r.URL), msg.MessageStyleInput),
		msg.NewStyled(strings.Join(assets, "\n")+"\n", msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *ExistsResponse) Messages() []*msg.Message {
	if r.Exists == nil {
		return []*msg.Message{}
	}
	assets := make([]string, 0)
	for URL, exists := range r.Exists {
		assets = append(assets, fmt.Sprintf("%s: %v", URL, exists))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Exists", msg.MessageStyleGeneric),
		msg.NewStyled(strings.Join(assets, "\n")+"\n", msg.MessageStyleOutput),
	)}
}
<commit_msg>added generation output<commit_after>package storage

import (
	"fmt"
	"github.com/viant/endly/model/msg"
	"strings"
)

/*
Message events control runner reporter and stdout
*/

//Items returns tag messages
func (r *RemoveRequest) Messages() []*msg.Message {
	if len(r.Assets) == 0 {
		return []*msg.Message{}
	}
	var fragments = make([]*msg.Styled, 0)
	for _, resource := range r.Assets {
		fragments = append(fragments, msg.NewStyled(fmt.Sprintf("SourceURL: %v", resource.URL), msg.MessageStyleInput))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Remove", msg.MessageStyleGeneric),
		fragments...),
	}
}

//Items returns event messages
func (r *UploadRequest) Messages() []*msg.Message {
	if r.Dest == nil {
		return []*msg.Message{}
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Upload", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("SourcKey: %v", r.SourceKey), msg.MessageStyleInput),
		msg.NewStyled(fmt.Sprintf("DestURL: %v", r.Dest.URL), msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *DownloadRequest) Messages() []*msg.Message {
	if r.Source == nil {
		return []*msg.Message{}
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Upload", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("Source: %v", r.Source.URL), msg.MessageStyleInput),
		msg.NewStyled(fmt.Sprintf("DestKey: %v", r.DestKey), msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *CopyRequest) Messages() []*msg.Message {
	_ = r.Init()
	if len(r.Transfers) == 0 {
		return []*msg.Message{}
	}
	var result = make([]*msg.Message, 0)
	for _, transfer := range r.Transfers {
		if transfer.Source == nil || transfer.Dest == nil {
			continue
		}
		result = append(result, msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
			msg.NewStyled("Copy", msg.MessageStyleGeneric),
			msg.NewStyled(fmt.Sprintf("compress: %v, expand: %v", transfer.Compress, transfer.Expand), msg.MessageStyleGeneric),
			msg.NewStyled(fmt.Sprintf("SourceURL: %v", transfer.Source.URL), msg.MessageStyleInput),
			msg.NewStyled(fmt.Sprintf("DestURL: %v", transfer.Dest.URL), msg.MessageStyleOutput),
		))
	}
	return result
}

//Items returns event messages
func (r *GenerateRequest) Messages() []*msg.Message {
	_ = r.Init()

	if r.Dest == nil {
		return []*msg.Message{}
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Generate", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("Size: %v", r.Size), msg.MessageStyleInput),
		msg.NewStyled(fmt.Sprintf("DestURL: %v", r.Dest.URL), msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *ListResponse) Messages() []*msg.Message {
	if r.Assets == nil {
		return []*msg.Message{}
	}
	assets := make([]string, 0)
	for i := range r.Assets {
		content := ""
		if len(r.Assets[i].Data) > 0 {
			content = fmt.Sprintf("\n%v\n\n", string(r.Assets[i].Data))
		}
		assets = append(assets, fmt.Sprintf("%s %v%v", r.Assets[i].Mode.String(), r.Assets[i].Name, content))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("List", msg.MessageStyleGeneric),
		msg.NewStyled(fmt.Sprintf("Source: %v", r.URL), msg.MessageStyleInput),
		msg.NewStyled(strings.Join(assets, "\n")+"\n", msg.MessageStyleOutput),
	)}
}

//Items returns event messages
func (r *ExistsResponse) Messages() []*msg.Message {
	if r.Exists == nil {
		return []*msg.Message{}
	}
	assets := make([]string, 0)
	for URL, exists := range r.Exists {
		assets = append(assets, fmt.Sprintf("%s: %v", URL, exists))
	}
	return []*msg.Message{msg.NewMessage(msg.NewStyled("", msg.MessageStyleGeneric),
		msg.NewStyled("Exists", msg.MessageStyleGeneric),
		msg.NewStyled(strings.Join(assets, "\n")+"\n", msg.MessageStyleOutput),
	)}
}
<|endoftext|>


<commit_before>package client

import (
	"net/http"
	"testing"

	"golang.org/x/net/context"
)

func TestContainerStatsError(t *testing.T) {
	client := &Client{
		transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
	}
	_, err := client.ContainerStats(context.Background(), "nothing", false)
	if err == nil || err.Error() != "Error response from daemon: Server error" {
		t.Fatalf("expected a Server Error, got %v", err)
	}
}
<commit_msg>Add happy path test on ContainerStats<commit_after>package client

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"

	"golang.org/x/net/context"
)

func TestContainerStatsError(t *testing.T) {
	client := &Client{
		transport: newMockClient(nil, errorMock(http.StatusInternalServerError, "Server error")),
	}
	_, err := client.ContainerStats(context.Background(), "nothing", false)
	if err == nil || err.Error() != "Error response from daemon: Server error" {
		t.Fatalf("expected a Server Error, got %v", err)
	}
}

func TestContainerStats(t *testing.T) {
	expectedURL := "/containers/container_id/stats"
	cases := []struct {
		stream         bool
		expectedStream string
	}{
		{
			expectedStream: "0",
		},
		{
			stream:         true,
			expectedStream: "1",
		},
	}
	for _, c := range cases {
		client := &Client{
			transport: newMockClient(nil, func(r *http.Request) (*http.Response, error) {
				if !strings.HasPrefix(r.URL.Path, expectedURL) {
					return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL)
				}

				query := r.URL.Query()
				stream := query.Get("stream")
				if stream != c.expectedStream {
					return nil, fmt.Errorf("stream not set in URL query properly. Expected '%s', got %s", c.expectedStream, stream)
				}

				return &http.Response{
					StatusCode: http.StatusOK,
					Body:       ioutil.NopCloser(bytes.NewReader([]byte("response"))),
				}, nil
			}),
		}
		body, err := client.ContainerStats(context.Background(), "container_id", c.stream)
		if err != nil {
			t.Fatal(err)
		}
		defer body.Close()
		content, err := ioutil.ReadAll(body)
		if err != nil {
			t.Fatal(err)
		}
		if string(content) != "response" {
			t.Fatalf("expected response to contain 'response', got %s", string(content))
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Brian J. Downs
//
// 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 openweathermap

const unitError = "unit unavailable"
const langError = "language unavailable"

// DataUnits represents the character chosen to represent the temperature notation
var DataUnits = map[string]string{"C": "metric", "F": "imperial", "K": "internal"}
var (
	baseURL      = "http://api.openweathermap.org/data/2.5/weather?%s"
	iconURL      = "http://openweathermap.org/img/w/%s"
	stationURL   = "http://api.openweathermap.org/data/2.5/station?id=%d"
	forecastBase = "http://api.openweathermap.org/data/2.5/forecast/daily?%s=%s&mode=json&units=%s&lang=%s&cnt=%d"
	historyURL   = "http://api.openweathermap.org/data/2.5/history/%s"
	dataPostURL  = "http://openweathermap.org/data/post"
)

// LangCodes holds all supported languages to be used
// inspried and sourced from @bambocher (github.com/bambocher)
var LangCodes = map[string]string{
	"EN":    "English",
	"RU":    "Russian",
	"IT":    "Italian",
	"ES":    "Spanish",
	"SP":    "Spanish",
	"UK":    "Ukrainian",
	"UA":    "Ukrainian",
	"DE":    "German",
	"PT":    "Portuguese",
	"RO":    "Romanian",
	"PL":    "Polish",
	"FI":    "Finnish",
	"NL":    "Dutch",
	"FR":    "French",
	"BG":    "Bulgarian",
	"SV":    "Swedish",
	"SE":    "Swedish",
	"TR":    "Turkish",
	"HR":    "Croatian",
	"CA":    "Catalan",
	"ZH_TW": "Chinese Traditional",
	"ZH":    "Chinese Simplified",
	"ZH_CN": "Chinese Simplified",
}

// Config will hold default settings to be passed into the
// "NewCurrent, NewForecast, etc}" functions.
type Config struct {
	Mode     string // user choice of JSON or XML
	Unit     string // measurement for results to be displayed.  F, C, or K
	Lang     string // should reference a key in the LangCodes map
	APIKey   string // API Key for connecting to the OWM
	Username string // Username for posting data
	Password string // Pasword for posting data
}

// APIError returned on failed API calls.
type APIError struct {
	Message string `json:"message"`
	COD     string `json:"cod"`
}

// Coordinates struct holds longitude and latitude data in returned
// JSON or as parameter data for requests using longitude and latitude.
type Coordinates struct {
	Longitude float64 `json:"lon"`
	Latitude  float64 `json:"lat"`
}

// Sys struct contains general information about the request
// and the surrounding area for where the request was made.
type Sys struct {
	Type    int     `json:"type"`
	ID      int     `json:"id"`
	Message float64 `json:"message"`
	Country string  `json:"country"`
	Sunrise int     `json:"sunrise"`
	Sunset  int     `json:"sunset"`
}

// Wind struct contains the speed and degree of the wind.
type Wind struct {
	Speed float64 `json:"speed"`
	Deg   float64 `json:"deg"`
}

// Weather struct holds high-level, basic info on the returned
// data.
type Weather struct {
	ID          int    `json:"id"`
	Main        string `json:"main"`
	Description string `json:"description"`
	Icon        string `json:"icon"`
}

// Main struct contains the temperates, humidity, pressure for the request.
type Main struct {
	Temp       float64 `json:"temp"`
	TempMin    float64 `json:"temp_min"`
	TempMax    float64 `json:"temp_max"`
	Pressure   float64 `json:"pressure"`
	Sea_level  float64 `json:"sea_level"`
	Grnd_level float64 `json:"grnd_level"`
	Humidity   int     `json:"humidity"`
}

// Clouds struct holds data regarding cloud cover.
type Clouds struct {
	All int `json:"all"`
}

// ValidDataUnit makes sure the string passed in is an accepted
// unit of measure to be used for the return data.
func ValidDataUnit(u string) bool {
	for d := range DataUnits {
		if u == d {
			return true
		}
	}
	return false
}

// ValidLangCode makes sure the string passed in is an
// acceptable lang code.
func ValidLangCode(c string) bool {
	for d := range LangCodes {
		if c == d {
			return true
		}
	}
	return false
}

// ValidDataUnitSymbol makes sure the string passed in is an
// acceptable data unit symbol.
func ValidDataUnitSymbol(u string) bool {
	for _, d := range DataUnits {
		if u == d {
			return true
		}
	}
	return false
}

// CheckAPIKeyExists will see if an API key has been set.
func (c *Config) CheckAPIKeyExists() bool { return len(c.APIKey) > 1 }
<commit_msg>removed underscore and made struct field camelcase for linter<commit_after>// Copyright 2015 Brian J. Downs
//
// 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 openweathermap

const unitError = "unit unavailable"
const langError = "language unavailable"

// DataUnits represents the character chosen to represent the temperature notation
var DataUnits = map[string]string{"C": "metric", "F": "imperial", "K": "internal"}
var (
	baseURL      = "http://api.openweathermap.org/data/2.5/weather?%s"
	iconURL      = "http://openweathermap.org/img/w/%s"
	stationURL   = "http://api.openweathermap.org/data/2.5/station?id=%d"
	forecastBase = "http://api.openweathermap.org/data/2.5/forecast/daily?%s=%s&mode=json&units=%s&lang=%s&cnt=%d"
	historyURL   = "http://api.openweathermap.org/data/2.5/history/%s"
	dataPostURL  = "http://openweathermap.org/data/post"
)

// LangCodes holds all supported languages to be used
// inspried and sourced from @bambocher (github.com/bambocher)
var LangCodes = map[string]string{
	"EN":    "English",
	"RU":    "Russian",
	"IT":    "Italian",
	"ES":    "Spanish",
	"SP":    "Spanish",
	"UK":    "Ukrainian",
	"UA":    "Ukrainian",
	"DE":    "German",
	"PT":    "Portuguese",
	"RO":    "Romanian",
	"PL":    "Polish",
	"FI":    "Finnish",
	"NL":    "Dutch",
	"FR":    "French",
	"BG":    "Bulgarian",
	"SV":    "Swedish",
	"SE":    "Swedish",
	"TR":    "Turkish",
	"HR":    "Croatian",
	"CA":    "Catalan",
	"ZH_TW": "Chinese Traditional",
	"ZH":    "Chinese Simplified",
	"ZH_CN": "Chinese Simplified",
}

// Config will hold default settings to be passed into the
// "NewCurrent, NewForecast, etc}" functions.
type Config struct {
	Mode     string // user choice of JSON or XML
	Unit     string // measurement for results to be displayed.  F, C, or K
	Lang     string // should reference a key in the LangCodes map
	APIKey   string // API Key for connecting to the OWM
	Username string // Username for posting data
	Password string // Pasword for posting data
}

// APIError returned on failed API calls.
type APIError struct {
	Message string `json:"message"`
	COD     string `json:"cod"`
}

// Coordinates struct holds longitude and latitude data in returned
// JSON or as parameter data for requests using longitude and latitude.
type Coordinates struct {
	Longitude float64 `json:"lon"`
	Latitude  float64 `json:"lat"`
}

// Sys struct contains general information about the request
// and the surrounding area for where the request was made.
type Sys struct {
	Type    int     `json:"type"`
	ID      int     `json:"id"`
	Message float64 `json:"message"`
	Country string  `json:"country"`
	Sunrise int     `json:"sunrise"`
	Sunset  int     `json:"sunset"`
}

// Wind struct contains the speed and degree of the wind.
type Wind struct {
	Speed float64 `json:"speed"`
	Deg   float64 `json:"deg"`
}

// Weather struct holds high-level, basic info on the returned
// data.
type Weather struct {
	ID          int    `json:"id"`
	Main        string `json:"main"`
	Description string `json:"description"`
	Icon        string `json:"icon"`
}

// Main struct contains the temperates, humidity, pressure for the request.
type Main struct {
	Temp      float64 `json:"temp"`
	TempMin   float64 `json:"temp_min"`
	TempMax   float64 `json:"temp_max"`
	Pressure  float64 `json:"pressure"`
	SeaLevel  float64 `json:"sea_level"`
	GrndLevel float64 `json:"grnd_level"`
	Humidity  int     `json:"humidity"`
}

// Clouds struct holds data regarding cloud cover.
type Clouds struct {
	All int `json:"all"`
}

// ValidDataUnit makes sure the string passed in is an accepted
// unit of measure to be used for the return data.
func ValidDataUnit(u string) bool {
	for d := range DataUnits {
		if u == d {
			return true
		}
	}
	return false
}

// ValidLangCode makes sure the string passed in is an
// acceptable lang code.
func ValidLangCode(c string) bool {
	for d := range LangCodes {
		if c == d {
			return true
		}
	}
	return false
}

// ValidDataUnitSymbol makes sure the string passed in is an
// acceptable data unit symbol.
func ValidDataUnitSymbol(u string) bool {
	for _, d := range DataUnits {
		if u == d {
			return true
		}
	}
	return false
}

// CheckAPIKeyExists will see if an API key has been set.
func (c *Config) CheckAPIKeyExists() bool { return len(c.APIKey) > 1 }
<|endoftext|>


<commit_before>package common

import (
	"encoding/base64"
	"net/http"
	"net/http/httputil"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func ValidBarcode8(s string) bool {
	re := regexp.MustCompile("^[A-Z0-9]{8,8}$")
	return re.MatchString(s)
}

func ValidBarcode7(s string) bool {
	re := regexp.MustCompile("^[A-Z0-9]{7,7}$")
	return re.MatchString(s)
}

func ValidCarton20(s string) bool {
	re := regexp.MustCompile("^[0-9]{20,20}$")
	return re.MatchString(s)
}

func ReverseProxy(proxyPort string, pathMap map[string]string) {

	for urlPath, targetPort := range pathMap {
		u, _ := url.Parse("http://127.0.0.1:" + targetPort)
		http.Handle(urlPath, httputil.NewSingleHostReverseProxy(u))
	}

	http.ListenAndServe(":"+proxyPort, nil)

}

func TimeNowString() string {
	//return fmt.Sprintf("%v", time.Unix(0, time.Now().UnixNano()/(int64(time.Millisecond)/int64(time.Nanosecond))*int64(time.Millisecond)))[:23]
	return time.Now().Format("2006-01-02 15:04:05.000")
}

func EscapeLatex(s string) string {
	s2 := strings.Replace(s, "\\", "\\textbackslash", -1)
	s2 = strings.Replace(s2, "&", "\\&", -1)
	s2 = strings.Replace(s2, "%", "\\%", -1)
	s2 = strings.Replace(s2, "$", "\\$", -1)
	s2 = strings.Replace(s2, "#", "\\#", -1)
	s2 = strings.Replace(s2, "_", "\\_", -1)
	s2 = strings.Replace(s2, "{", "\\{", -1)
	s2 = strings.Replace(s2, "}", "\\}", -1)
	s2 = strings.Replace(s2, "~", "\\textasciitilde", -1)
	return strings.Replace(s2, "^", "\\textasciicircum", -1)

}

func PadZero(s string) string {
	if s[0] == '.' {
		return "0" + s
	} else {
		return s
	}
}

type TmpRow7 struct {
	Str1   string
	Str2   string
	Str3   string
	Str4   string
	Str5   string
	Str6   string
	Str7   string
	Int1   int64
	Int2   int64
	Int3   int64
	Int4   int64
	Int5   int64
	Int6   int64
	Int7   int64
	Float1 float64
	Float2 float64
	Float3 float64
	Float4 float64
	Float5 float64
	Float6 float64
	Float7 float64
}

func IndexOf(target int, intSlice []int) int {
	for i, v := range intSlice {
		if v == target {
			return i
		}
	}
	return -1
}

func StringToRows7(data string, config []string) []TmpRow7 {
	var translate [21]int
	strPosition := 1
	intPosition := 8
	floatPosition := 15
	var result []TmpRow7

	for j, t := range config {
		if t == "string" {
			translate[j] = strPosition
			strPosition++
		} else if t == "int64" {
			translate[j] = intPosition
			intPosition++

		} else if t == "float64" {
			translate[j] = floatPosition
			floatPosition++
		}

	}

	lines := strings.Split(data, "\n")
	for _, v := range lines {
		if v == "" {
			continue
		}
		columns := strings.Split(v, "\t")
		row := TmpRow7{}
		index := 0
		for j, col := range columns {
			index = translate[j]
			switch {
			case index == 1:
				row.Str1 = col
			case index == 2:
				row.Str2 = col
			case index == 3:
				row.Str3 = col
			case index == 4:
				row.Str4 = col
			case index == 5:
				row.Str5 = col
			case index == 6:
				row.Str6 = col
			case index == 7:
				row.Str7 = col
			case index >= 7 && index <= 14:
				tmpInt, err := strconv.ParseInt(col, 10, 64)
				if err != nil {
					tmpInt = 0
				}
				switch {
				case index == 8:
					row.Int1 = tmpInt
				case index == 9:
					row.Int2 = tmpInt
				case index == 10:
					row.Int3 = tmpInt
				case index == 11:
					row.Int4 = tmpInt
				case index == 12:
					row.Int5 = tmpInt
				case index == 13:
					row.Int6 = tmpInt
				case index == 14:
					row.Int7 = tmpInt
				}
			case index >= 15 && index <= 21:
				tmpFloat, err := strconv.ParseFloat(col, 64)
				if err != nil {
					tmpFloat = 0
				}
				switch {
				case index == 15:
					row.Float1 = tmpFloat
				case index == 16:
					row.Float2 = tmpFloat
				case index == 17:
					row.Float3 = tmpFloat
				case index == 18:
					row.Float4 = tmpFloat
				case index == 19:
					row.Float5 = tmpFloat
				case index == 20:
					row.Float6 = tmpFloat
				case index == 21:
					row.Float7 = tmpFloat
				}

			}
		}

		result = append(result, row)
	}
	return result
}

func Base64Encode(msg string) string {
	return base64.StdEncoding.EncodeToString([]byte(msg))
}

func Base64Decode(encoded string) string {
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		return ""
	}
	return string(decoded)

}
<commit_msg>ExcelDateNumber<commit_after>package common

import (
	"encoding/base64"
	"net/http"
	"net/http/httputil"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func ValidBarcode8(s string) bool {
	re := regexp.MustCompile("^[A-Z0-9]{8,8}$")
	return re.MatchString(s)
}

func ValidBarcode7(s string) bool {
	re := regexp.MustCompile("^[A-Z0-9]{7,7}$")
	return re.MatchString(s)
}

func ValidCarton20(s string) bool {
	re := regexp.MustCompile("^[0-9]{20,20}$")
	return re.MatchString(s)
}

func ReverseProxy(proxyPort string, pathMap map[string]string) {

	for urlPath, targetPort := range pathMap {
		u, _ := url.Parse("http://127.0.0.1:" + targetPort)
		http.Handle(urlPath, httputil.NewSingleHostReverseProxy(u))
	}

	http.ListenAndServe(":"+proxyPort, nil)

}

func TimeNowString() string {
	//return fmt.Sprintf("%v", time.Unix(0, time.Now().UnixNano()/(int64(time.Millisecond)/int64(time.Nanosecond))*int64(time.Millisecond)))[:23]
	return time.Now().Format("2006-01-02 15:04:05.000")
}

func EscapeLatex(s string) string {
	s2 := strings.Replace(s, "\\", "\\textbackslash", -1)
	s2 = strings.Replace(s2, "&", "\\&", -1)
	s2 = strings.Replace(s2, "%", "\\%", -1)
	s2 = strings.Replace(s2, "$", "\\$", -1)
	s2 = strings.Replace(s2, "#", "\\#", -1)
	s2 = strings.Replace(s2, "_", "\\_", -1)
	s2 = strings.Replace(s2, "{", "\\{", -1)
	s2 = strings.Replace(s2, "}", "\\}", -1)
	s2 = strings.Replace(s2, "~", "\\textasciitilde", -1)
	return strings.Replace(s2, "^", "\\textasciicircum", -1)

}

func PadZero(s string) string {
	if s[0] == '.' {
		return "0" + s
	} else {
		return s
	}
}

type TmpRow7 struct {
	Str1   string
	Str2   string
	Str3   string
	Str4   string
	Str5   string
	Str6   string
	Str7   string
	Int1   int64
	Int2   int64
	Int3   int64
	Int4   int64
	Int5   int64
	Int6   int64
	Int7   int64
	Float1 float64
	Float2 float64
	Float3 float64
	Float4 float64
	Float5 float64
	Float6 float64
	Float7 float64
}

func IndexOf(target int, intSlice []int) int {
	for i, v := range intSlice {
		if v == target {
			return i
		}
	}
	return -1
}

func StringToRows7(data string, config []string) []TmpRow7 {
	var translate [21]int
	strPosition := 1
	intPosition := 8
	floatPosition := 15
	var result []TmpRow7

	for j, t := range config {
		if t == "string" {
			translate[j] = strPosition
			strPosition++
		} else if t == "int64" {
			translate[j] = intPosition
			intPosition++

		} else if t == "float64" {
			translate[j] = floatPosition
			floatPosition++
		}

	}

	lines := strings.Split(data, "\n")
	for _, v := range lines {
		if v == "" {
			continue
		}
		columns := strings.Split(v, "\t")
		row := TmpRow7{}
		index := 0
		for j, col := range columns {
			index = translate[j]
			switch {
			case index == 1:
				row.Str1 = col
			case index == 2:
				row.Str2 = col
			case index == 3:
				row.Str3 = col
			case index == 4:
				row.Str4 = col
			case index == 5:
				row.Str5 = col
			case index == 6:
				row.Str6 = col
			case index == 7:
				row.Str7 = col
			case index >= 7 && index <= 14:
				tmpInt, err := strconv.ParseInt(col, 10, 64)
				if err != nil {
					tmpInt = 0
				}
				switch {
				case index == 8:
					row.Int1 = tmpInt
				case index == 9:
					row.Int2 = tmpInt
				case index == 10:
					row.Int3 = tmpInt
				case index == 11:
					row.Int4 = tmpInt
				case index == 12:
					row.Int5 = tmpInt
				case index == 13:
					row.Int6 = tmpInt
				case index == 14:
					row.Int7 = tmpInt
				}
			case index >= 15 && index <= 21:
				tmpFloat, err := strconv.ParseFloat(col, 64)
				if err != nil {
					tmpFloat = 0
				}
				switch {
				case index == 15:
					row.Float1 = tmpFloat
				case index == 16:
					row.Float2 = tmpFloat
				case index == 17:
					row.Float3 = tmpFloat
				case index == 18:
					row.Float4 = tmpFloat
				case index == 19:
					row.Float5 = tmpFloat
				case index == 20:
					row.Float6 = tmpFloat
				case index == 21:
					row.Float7 = tmpFloat
				}

			}
		}

		result = append(result, row)
	}
	return result
}

func Base64Encode(msg string) string {
	return base64.StdEncoding.EncodeToString([]byte(msg))
}

func Base64Decode(encoded string) string {
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		return ""
	}
	return string(decoded)

}

func ExcelDateNumber(s string) int {
	var duration time.Duration
	then, err := time.Parse("2006-01-02", s)
	ref, err := time.Parse("2006-01-02", "1970-01-01")

	if err == nil {
		duration = then.Sub(ref)
	}
	return int(duration.Hours()/24) + 25569

}
<|endoftext|>


<commit_before>/*
 * Minio Go Library for Amazon S3 Legacy v2 Signature Compatible Cloud Storage (C) 2015 Minio, Inc.
 *
 * 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 minio

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"encoding/xml"
	"errors"
	"io"
	"regexp"
	"strings"
	"unicode/utf8"
)

// decoder provides a unified decoding method interface
type decoder interface {
	Decode(v interface{}) error
}

// acceptTypeDecoder provide decoded value in given acceptType
func acceptTypeDecoder(body io.Reader, acceptType string, v interface{}) error {
	var d decoder
	switch {
	case acceptType == "application/xml":
		d = xml.NewDecoder(body)
	case acceptType == "application/json":
		d = json.NewDecoder(body)
	default:
		d = xml.NewDecoder(body)
	}
	return d.Decode(v)
}

// urlEncodedName encode the strings from UTF-8 byte representations to HTML hex escape sequences
//
// This is necessary since regular url.Parse() and url.Encode() functions do not support UTF-8
// non english characters cannot be parsed due to the nature in which url.Encode() is written
//
// This function on the other hand is a direct replacement for url.Encode() technique to support
// pretty much every UTF-8 character.
func urlEncodeName(name string) (string, error) {
	// if object matches reserved string, no need to encode them
	reservedNames := regexp.MustCompile("^[a-zA-Z0-9-_.~/]+$")
	if reservedNames.MatchString(name) {
		return name, nil
	}
	var encodedName string
	for _, s := range name {
		if 'A' <= s && s <= 'Z' || 'a' <= s && s <= 'z' || '0' <= s && s <= '9' { // §2.3 Unreserved characters (mark)
			encodedName = encodedName + string(s)
			continue
		}
		switch s {
		case '-', '_', '.', '~', '/': // §2.3 Unreserved characters (mark)
			encodedName = encodedName + string(s)
			continue
		default:
			len := utf8.RuneLen(s)
			if len < 0 {
				return "", errors.New("invalid utf-8")
			}
			u := make([]byte, len)
			utf8.EncodeRune(u, s)
			for _, r := range u {
				hex := hex.EncodeToString([]byte{r})
				encodedName = encodedName + "%" + strings.ToUpper(hex)
			}
		}
	}
	return encodedName, nil
}

// sum256Reader calculate sha256 sum for an input read seeker
func sum256Reader(reader io.ReadSeeker) ([]byte, error) {
	h := sha256.New()
	var err error

	start, _ := reader.Seek(0, 1)
	defer reader.Seek(start, 0)

	for err == nil {
		length := 0
		byteBuffer := make([]byte, 1024*1024)
		length, err = reader.Read(byteBuffer)
		byteBuffer = byteBuffer[0:length]
		h.Write(byteBuffer)
	}

	if err != io.EOF {
		return nil, err
	}

	return h.Sum(nil), nil
}

// sum256 calculate sha256 sum for an input byte array
func sum256(data []byte) []byte {
	hash := sha256.New()
	hash.Write(data)
	return hash.Sum(nil)
}

// sumHMAC calculate hmac between two input byte array
func sumHMAC(key []byte, data []byte) []byte {
	hash := hmac.New(sha256.New, key)
	hash.Write(data)
	return hash.Sum(nil)
}
<commit_msg>Remove dead code<commit_after>/*
 * Minio Go Library for Amazon S3 Legacy v2 Signature Compatible Cloud Storage (C) 2015 Minio, Inc.
 *
 * 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 minio

import (
	"encoding/hex"
	"encoding/json"
	"encoding/xml"
	"errors"
	"io"
	"regexp"
	"strings"
	"unicode/utf8"
)

// decoder provides a unified decoding method interface
type decoder interface {
	Decode(v interface{}) error
}

// acceptTypeDecoder provide decoded value in given acceptType
func acceptTypeDecoder(body io.Reader, acceptType string, v interface{}) error {
	var d decoder
	switch {
	case acceptType == "application/xml":
		d = xml.NewDecoder(body)
	case acceptType == "application/json":
		d = json.NewDecoder(body)
	default:
		d = xml.NewDecoder(body)
	}
	return d.Decode(v)
}

// urlEncodedName encode the strings from UTF-8 byte representations to HTML hex escape sequences
//
// This is necessary since regular url.Parse() and url.Encode() functions do not support UTF-8
// non english characters cannot be parsed due to the nature in which url.Encode() is written
//
// This function on the other hand is a direct replacement for url.Encode() technique to support
// pretty much every UTF-8 character.
func urlEncodeName(name string) (string, error) {
	// if object matches reserved string, no need to encode them
	reservedNames := regexp.MustCompile("^[a-zA-Z0-9-_.~/]+$")
	if reservedNames.MatchString(name) {
		return name, nil
	}
	var encodedName string
	for _, s := range name {
		if 'A' <= s && s <= 'Z' || 'a' <= s && s <= 'z' || '0' <= s && s <= '9' { // §2.3 Unreserved characters (mark)
			encodedName = encodedName + string(s)
			continue
		}
		switch s {
		case '-', '_', '.', '~', '/': // §2.3 Unreserved characters (mark)
			encodedName = encodedName + string(s)
			continue
		default:
			len := utf8.RuneLen(s)
			if len < 0 {
				return "", errors.New("invalid utf-8")
			}
			u := make([]byte, len)
			utf8.EncodeRune(u, s)
			for _, r := range u {
				hex := hex.EncodeToString([]byte{r})
				encodedName = encodedName + "%" + strings.ToUpper(hex)
			}
		}
	}
	return encodedName, nil
}
<|endoftext|>


<commit_before><commit_msg>shiny/driver/jsdriver: add some missing keys (shift, delete)<commit_after><|endoftext|>


<commit_before>package irc

import (
	"strings"
	"fmt"
	"time"
	"strconv"
)

func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		// TODO: Grow this dynamically
		event = event[0 : len(event)+1]
		event[len(event)-1] = callback
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) ReplaceCallback(i uint8, eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		event[i] = callback;
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) RunCallbacks(event *IRCEvent) {
	if event.Code == "PRIVMSG" && event.Message[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP
		if i := strings.LastIndex(event.Message, "\x01"); i > -1 {
			event.Message = event.Message[1:i]
		}
		if event.Message == "VERSION" {
			event.Code = "CTCP_VERSION"
		} else if event.Message == "TIME" {
			event.Code = "CTCP_TIME"
		} else if event.Message[0:4] == "PING" {
			event.Code = "CTCP_PING"
		} else if event.Message == "USERINFO" {
			event.Code = "CTCP_USERINFO"
		} else if event.Message == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"
		}
	}
	if callbacks, ok := irc.events[event.Code]; ok {
		for _, callback := range callbacks {
			go callback(event)
		}
	} else {
		fmt.Printf("No callback for: %#v\n", event)
	}
}

func (irc *IRCConnection) setupCallbacks() {
	irc.events = make(map[string][]func(*IRCEvent))

	//Handle ping events
	irc.AddCallback("PING", func(e *IRCEvent) { irc.SendRaw("PONG :" + e.Message) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", e.Nick, VERSION))
	})

	irc.AddCallback("CTCP_USERINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user))
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick))
	})

	irc.AddCallback("CTCP_TIME", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick, time.LocalTime().Format("ANSIC")))
	})

	irc.AddCallback("CTCP_PING", func(e *IRCEvent) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) })

	irc.AddCallback("437", func(e *IRCEvent) {
		irc.nick = irc.nick + "_"
		irc.SendRaw(fmt.Sprintf("NICK %s", irc.nick))
	})

	irc.AddCallback("PONG", func(e *IRCEvent) {
		ns, _ := strconv.Atoi64(e.Message)
		fmt.Printf("Lag: %fs\n", float((time.Nanoseconds()-ns))/1000/1000/1000)
	})
}
<commit_msg>Nick already in use callback<commit_after>package irc

import (
	"strings"
	"fmt"
	"time"
	"strconv"
)

func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		// TODO: Grow this dynamically
		event = event[0 : len(event)+1]
		event[len(event)-1] = callback
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) ReplaceCallback(i uint8, eventcode string, callback func(*IRCEvent)) {
	eventcode = strings.ToUpper(eventcode)
	if event, ok := irc.events[eventcode]; ok {
		event[i] = callback
	} else {
		event = make([]func(*IRCEvent), 1, 20)
		event[0] = callback
		irc.events[eventcode] = event
	}
}

func (irc *IRCConnection) RunCallbacks(event *IRCEvent) {
	if event.Code == "PRIVMSG" && event.Message[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP
		if i := strings.LastIndex(event.Message, "\x01"); i > -1 {
			event.Message = event.Message[1:i]
		}
		if event.Message == "VERSION" {
			event.Code = "CTCP_VERSION"
		} else if event.Message == "TIME" {
			event.Code = "CTCP_TIME"
		} else if event.Message[0:4] == "PING" {
			event.Code = "CTCP_PING"
		} else if event.Message == "USERINFO" {
			event.Code = "CTCP_USERINFO"
		} else if event.Message == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"
		}
	}
	if callbacks, ok := irc.events[event.Code]; ok {
		for _, callback := range callbacks {
			go callback(event)
		}
	} else {
		fmt.Printf("No callback for: %#v\n", event)
	}
}

func (irc *IRCConnection) setupCallbacks() {
	irc.events = make(map[string][]func(*IRCEvent))

	//Handle ping events
	irc.AddCallback("PING", func(e *IRCEvent) { irc.SendRaw("PONG :" + e.Message) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01", e.Nick, VERSION))
	})

	irc.AddCallback("CTCP_USERINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user))
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick))
	})

	irc.AddCallback("CTCP_TIME", func(e *IRCEvent) {
		irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick, time.LocalTime().Format("ANSIC")))
	})

	irc.AddCallback("CTCP_PING", func(e *IRCEvent) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) })

	irc.AddCallback("437", func(e *IRCEvent) {
		irc.nick = irc.nick + "_"
		irc.SendRaw(fmt.Sprintf("NICK %s", irc.nick))
	})

	irc.AddCallback("433", func(e *IRCEvent) {
		irc.nick = irc.nick + "_"
		irc.SendRaw(fmt.Sprintf("NICK %s", irc.nick))
	})

	irc.AddCallback("PONG", func(e *IRCEvent) {
		ns, _ := strconv.Atoi64(e.Message)
		fmt.Printf("Lag: %fs\n", float((time.Nanoseconds()-ns))/1000/1000/1000)
	})
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2014 by Artem Andreenko, Openstat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 ******************************************************************************/

package goaero

// #cgo CFLAGS: -I/usr/local/include
// #cgo LDFLAGS: /usr/local/lib/libaerospike.a -llua -lcrypto -lz
// #include <stdlib.h>
// #include <aerospike/aerospike.h>
// #include <aerospike/aerospike_key.h>
// #include <aerospike/as_log.h>
import "C"

import (
	"log"
	"unsafe"
)

type Config struct {
	as_config C.as_config
	lastHost  int
}

func NewConfig() (self *Config) {
	self = new(Config)
	C.as_config_init(&self.as_config)
	return
}

func (self *Config) AddHost(addr string, port uint16) {
	if self.lastHost >= C.AS_CONFIG_HOSTS_SIZE {
		log.Printf("WARNING: reached max hosts size: %d", C.AS_CONFIG_HOSTS_SIZE)
		return
	}
	c_host := C.as_config_host{}
	cAddr := C.CString(addr)
	c_host.addr = C.CString(addr)
	c_host.port = C.uint16_t(port)
	self.as_config.hosts[self.lastHost] = c_host
	self.lastHost++
	C.free(unsafe.Pointer(cAddr))
}

func (self *Config) getCStruct() *C.as_config {
	return &self.as_config
}
<commit_msg>AS_POLICY_RETRY_ONCE testing<commit_after>/*******************************************************************************
 * Copyright 2014 by Artem Andreenko, Openstat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 ******************************************************************************/

package goaero

// #cgo CFLAGS: -I/usr/local/include
// #cgo LDFLAGS: /usr/local/lib/libaerospike.a -llua -lcrypto -lz
// #include <stdlib.h>
// #include <aerospike/aerospike.h>
// #include <aerospike/aerospike_key.h>
// #include <aerospike/as_log.h>
import "C"

import (
	"log"
	"unsafe"
)

type Config struct {
	as_config C.as_config
	lastHost  int
}

func NewConfig() (self *Config) {
	self = new(Config)
	C.as_config_init(&self.as_config)
	self.as_config.policies.retry = C.AS_POLICY_RETRY_ONCE
	return
}

func (self *Config) AddHost(addr string, port uint16) {
	if self.lastHost >= C.AS_CONFIG_HOSTS_SIZE {
		log.Printf("WARNING: reached max hosts size: %d", C.AS_CONFIG_HOSTS_SIZE)
		return
	}
	c_host := C.as_config_host{}
	cAddr := C.CString(addr)
	c_host.addr = C.CString(addr)
	c_host.port = C.uint16_t(port)
	self.as_config.hosts[self.lastHost] = c_host
	self.lastHost++
	C.free(unsafe.Pointer(cAddr))
}

func (self *Config) getCStruct() *C.as_config {
	return &self.as_config
}
<|endoftext|>


<commit_before>package expleto

//

import (
	"encoding/json"
	"errors"
	"fmt"
	// "io/ioutil"
	// "os"
	"path/filepath"
	// "reflect"
	// "strconv"
	// "strings"
	// "fmt"
	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

const (
	ERROR_FORMAT_NOT_SUPPORTED = "expleto: The format is not supported"
)

// Config stores configurations values
type Config struct {
	AppName   string `json:"app_name" yaml:"app_name" toml:"app_name"`
	BaseURL   string `json:"base_url" yaml:"base_url" toml:"base_url"`
	Port      int    `json:"port" yaml:"port" toml:"port"`
	Verbose   bool   `json:"verbose" yaml:"verbose" toml:"verbose"`
	StaticDir string `json:"static_dir" yaml:"static_dir" toml:"static_dir"`
	ViewsDir  string `json:"view_dir" yaml:"view_dir" toml:"view_dir"`
}

// DefaultConfig returns the default configuration settings.
func DefaultConfig() *Config {
	return &Config{
		AppName:   "expleto web app",
		BaseURL:   "http://localhost:9000",
		Port:      9000,
		Verbose:   false,
		StaticDir: "static",
		ViewsDir:  "views",
	}
}

// NewConfig reads configuration from path. The format is deduced from the file extension
//	* .json    - is decoded as json
//	* .yml     - is decoded as yaml
//	* .toml    - is decoded as toml
func NewConfig(path string) (*Config, error) {
	var err error
	data, err := GetDataFromFile(path)
	if err != nil {
		return nil, FormatError(err)
	}

	cfg := &Config{}
	// err = nil
	switch filepath.Ext(path) {

	case ".json":
		err = json.Unmarshal(data, cfg)

	case ".toml":
		_, err = toml.Decode(string(data), cfg)

	case ".yml":
		err = yaml.Unmarshal(data, cfg)

	default:
		err = errors.New(ERROR_FORMAT_NOT_SUPPORTED)
	}
	if err != nil {
		return nil, fmt.Errorf("Can't parse %s: %v", path, err)
	}

	return cfg, nil
}
<commit_msg>adding update env variables<commit_after>package expleto

//

import (
	"encoding/json"
	"errors"
	"fmt"
	// "io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	// "fmt"
	"github.com/BurntSushi/toml"
	"github.com/fatih/camelcase"
	"gopkg.in/yaml.v2"
)

const (
	ERROR_FORMAT_NOT_SUPPORTED = "expleto: The format is not supported"
)

// Config stores configurations values
type Config struct {
	AppName   string `json:"app_name" yaml:"app_name" toml:"app_name"`
	BaseURL   string `json:"base_url" yaml:"base_url" toml:"base_url"`
	Port      int    `json:"port" yaml:"port" toml:"port"`
	Verbose   bool   `json:"verbose" yaml:"verbose" toml:"verbose"`
	StaticDir string `json:"static_dir" yaml:"static_dir" toml:"static_dir"`
	ViewsDir  string `json:"view_dir" yaml:"view_dir" toml:"view_dir"`
}

// DefaultConfig returns the default configuration settings.
func DefaultConfig() *Config {
	return &Config{
		AppName:   "expleto web app",
		BaseURL:   "http://localhost:9000",
		Port:      9000,
		Verbose:   false,
		StaticDir: "static",
		ViewsDir:  "views",
	}
}

// NewConfig reads configuration from path. The format is deduced from the file extension
//	* .json    - is decoded as json
//	* .yml     - is decoded as yaml
//	* .toml    - is decoded as toml
func NewConfig(path string) (*Config, error) {
	var err error
	data, err := GetDataFromFile(path)
	if err != nil {
		return nil, FormatError(err)
	}

	cfg := &Config{}
	// err = nil
	switch filepath.Ext(path) {

	case ".json":
		err = json.Unmarshal(data, cfg)

	case ".toml":
		_, err = toml.Decode(string(data), cfg)

	case ".yml":
		err = yaml.Unmarshal(data, cfg)

	default:
		err = errors.New(ERROR_FORMAT_NOT_SUPPORTED)
	}
	if err != nil {
		return nil, fmt.Errorf("Can't parse %s: %v", path, err)
	}

	return cfg, nil
}

// overrides c field's values that are set in the environment.
// The environment variable names are derived from config fields by underscoring, and uppercasing
// the name. E.g. AppName will have a corresponding environment variable APP_NAME
//
// NOTE only int, string and bool fields are supported and the corresponding values are set.
// when the field value is not supported it is ignored.
func (c *Config) Sync() error {
	cfg := reflect.ValueOf(c).Elem()
	cTyp := cfg.Type()

	for k := range make([]struct{}, cTyp.NumField()) {
		field := cTyp.Field(k)

		cm := getEnvName(field.Name)
		env := os.Getenv(cm)
		if env == "" {
			continue
		}
		switch field.Type.Kind() {
		case reflect.String:
			cfg.FieldByName(field.Name).SetString(env)
		case reflect.Int:
			v, err := strconv.Atoi(env)
			if err != nil {
				return fmt.Errorf("utron: loading config field %s %v", field.Name, err)
			}
			cfg.FieldByName(field.Name).Set(reflect.ValueOf(v))
		case reflect.Bool:
			b, err := strconv.ParseBool(env)
			if err != nil {
				return fmt.Errorf("utron: loading config field %s %v", field.Name, err)
			}
			cfg.FieldByName(field.Name).SetBool(b)
		}

	}
	return nil
}

// returns all upper case and underscore separated string, from field.
// field is a camel case string.
//
// example
//	AppName will change to APP_NAME
func getEnvName(field string) string {
	camSplit := camelcase.Split(field)
	var rst string
	for k, v := range camSplit {
		if k == 0 {
			rst = strings.ToUpper(v)
			continue
		}
		rst = rst + "_" + strings.ToUpper(v)
	}
	return rst
}
<|endoftext|>


<commit_before>package lazycache

import (
	"github.com/spf13/viper"
	kitlog  "github.com/go-kit/kit/log"
	flag "github.com/spf13/pflag"
	"fmt"
	"strings"
)

var DefaultLogger kitlog.Logger

func ViperConfiguration() {

	// Configuration
	viper.SetDefault("port", 8080 )
	viper.SetDefault("bind","0.0.0.0")
	viper.SetDefault("imagestore", "")
	viper.SetDefault("imagestore.bucket","camhd-image-cache")

	viper.SetConfigName("lazycache")
	viper.AddConfigPath("/etc/lazycache")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig() // Find and read the config file
	if err != nil  { // Handle errors reading the config file
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			// ignore
		default:
	    panic(fmt.Errorf("Fatal error config file: %s \n", err))
		}
	}

	viper.SetEnvPrefix("lazycache")
	viper.AutomaticEnv()
	// Convert '.' to '_' in configuration variable names
	viper.SetEnvKeyReplacer( strings.NewReplacer(".", "_") )

	// var (
	// 	bindFlag          = flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	// 	ImageStoreFlag   = flag.String("image-store", "", "Type of image store (none, google)")
	// 	ImageBucketFlag = flag.String("image-store-bucket", "", "Bucket used for Google image store")
	// )
	flag.Int("port", 80, "Network port to listen on (default: 8080)")
	flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	flag.String("image-store", "", "Type of image store (none, google)")

	flag.String("image-store-bucket", "camhd-image-cache", "Bucket used for Google image store")
	flag.String("image-local-root", "", "Bucket used for Google image store")
	flag.String("image-url-root", "", "Bucket used for Google image store")

	viper.BindPFlag("port", flag.Lookup("port"))
	viper.BindPFlag("bind", flag.Lookup("bind"))
	viper.BindPFlag("imagestore", flag.Lookup("image-store"))

	viper.BindPFlag("imagestore.bucket", flag.Lookup("image-store-bucket"))
	viper.BindPFlag("imagestore.localroot", flag.Lookup("image-local-root"))
	viper.BindPFlag("imagestore.urlroo", flag.Lookup("image-url-root"))

	flag.Parse()
}

func ConfigureImageStoreFromViper( logger kitlog.Logger ) {
	switch strings.ToLower( viper.GetString("imagestore" )) {
	case "", "none":
		fmt.Printf("Unable to determine type of image store from ", viper.GetString("imagestore" ) )
		 DefaultImageStore = NullImageStore{}
	case "local":
			DefaultImageStore = CreateLocalStore(viper.GetString("imagestore.localRoot"),
																						viper.GetString("imagestore.urlRoot"), logger )
	case "google":
	   DefaultImageStore = CreateGoogleStore(viper.GetString("imagestore.bucket"), logger)
	}

}
<commit_msg>Fix misspelling in config.go<commit_after>package lazycache

import (
	"github.com/spf13/viper"
	kitlog  "github.com/go-kit/kit/log"
	flag "github.com/spf13/pflag"
	"fmt"
	"strings"
)

var DefaultLogger kitlog.Logger

func ViperConfiguration() {

	// Configuration
	viper.SetDefault("port", 8080 )
	viper.SetDefault("bind","0.0.0.0")
	viper.SetDefault("imagestore", "")
	viper.SetDefault("imagestore.bucket","camhd-image-cache")

	viper.SetConfigName("lazycache")
	viper.AddConfigPath("/etc/lazycache")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig() // Find and read the config file
	if err != nil  { // Handle errors reading the config file
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			// ignore
		default:
	    panic(fmt.Errorf("Fatal error config file: %s \n", err))
		}
	}

	viper.SetEnvPrefix("lazycache")
	viper.AutomaticEnv()
	// Convert '.' to '_' in configuration variable names
	viper.SetEnvKeyReplacer( strings.NewReplacer(".", "_") )

	// var (
	// 	bindFlag          = flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	// 	ImageStoreFlag   = flag.String("image-store", "", "Type of image store (none, google)")
	// 	ImageBucketFlag = flag.String("image-store-bucket", "", "Bucket used for Google image store")
	// )
	flag.Int("port", 80, "Network port to listen on (default: 8080)")
	flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	flag.String("image-store", "", "Type of image store (none, google)")

	flag.String("image-store-bucket", "camhd-image-cache", "Bucket used for Google image store")
	flag.String("image-local-root", "", "Bucket used for Google image store")
	flag.String("image-url-root", "", "Bucket used for Google image store")

	viper.BindPFlag("port", flag.Lookup("port"))
	viper.BindPFlag("bind", flag.Lookup("bind"))
	viper.BindPFlag("imagestore", flag.Lookup("image-store"))

	viper.BindPFlag("imagestore.bucket", flag.Lookup("image-store-bucket"))
	viper.BindPFlag("imagestore.localroot", flag.Lookup("image-local-root"))
	viper.BindPFlag("imagestore.urlroot", flag.Lookup("image-url-root"))

	flag.Parse()
}

func ConfigureImageStoreFromViper( logger kitlog.Logger ) {
	switch strings.ToLower( viper.GetString("imagestore" )) {
	case "", "none":
		fmt.Printf("Unable to determine type of image store from \"%s\"", viper.GetString("imagestore" ) )
		 DefaultImageStore = NullImageStore{}
	case "local":
			DefaultImageStore = CreateLocalStore(viper.GetString("imagestore.localRoot"),
																						viper.GetString("imagestore.urlRoot"), logger )
	case "google":
	   DefaultImageStore = CreateGoogleStore(viper.GetString("imagestore.bucket"), logger)
	}

}
<|endoftext|>


<commit_before>// Package config version v1.0.0
package config

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"reflect"
	"strings"

	"gopkg.in/yaml.v2"
)

// Namespace holds the pieces joined together to form the
// directory namespacing for config.
type Namespace struct {
	Organization string // optional additional namespace for orgs.
	System       string // Name of the system associated with this config.
}

// The Config interface implements config.
type Config interface {
	Load(src string, dst interface{}) error
}

// UserBase and SystemBase are the prefixes for the user and system config
// paths, respectively.
const (
	UserBase   string = "~/.config/"
	SystemBase string = "/etc/"
)

// Load expands the provided src path using config.ExpandUser, then reads
// the file and unmarshals into dst using go-yaml.
func Load(src string, dst interface{}) (err error) {
	dstv := reflect.ValueOf(dst)

	if dstv.Kind() != reflect.Ptr {
		err = errors.New("config: not a pointer")
	}
	if err != nil {
		return
	}

	path, err := ExpandUser(src)
	if err != nil {
		return
	}

	data, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	err = yaml.Unmarshal(data, dst)
	return
}

// ExpandUser acts kind of like os.path.expanduser in Python, except only
// supports expanding "~/" or "$HOME"
func ExpandUser(path string) (exPath string, err error) {
	usr, err := user.Current()
	if err != nil {
		return
	}

	dir := fmt.Sprintf("%s/", usr.HomeDir)

	exPath = path
	if len(path) > 2 && path[:2] == "~/" {
		exPath = strings.Replace(exPath, "~/", dir, 1)
	} else if len(path) > 5 && path[:5] == "$HOME" {
		exPath = strings.Replace(exPath, "$HOME", dir, 1)
	}

	exPath, err = filepath.Abs(filepath.Clean(exPath))

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

	return
}

// Path returns path to config, chosen by hierarchy and checked for
// existence:
//
// 1. User config (~/.config/podhub/canary/config.yaml)
//
// 2. System config (/etc/podhub/canary/config.yaml)
func (c Namespace) Path() (path string) {
	systemPath, _ := c.systemPath()
	if _, err := os.Stat(systemPath); err == nil {
		path, _ = c.systemPath()
	}

	userPath, _ := c.userPath()
	if _, err := os.Stat(userPath); err == nil {
		path, _ = c.userPath()
	}
	return
}

func (c Namespace) systemPath() (path string, err error) {
	path = filepath.Join(SystemBase, c.Organization, c.System, "config.yaml")
	return
}

func (c Namespace) userPath() (path string, err error) {
	userBase, err := ExpandUser(UserBase)
	if err != nil {
		return "", err
	}

	path = filepath.Join(userBase, c.Organization, c.System, "config.yaml")
	return
}

// Load is a convenience function registered to config.Namespace to
// implement Config.Load().
func (c Namespace) Load(dst interface{}) (err error) {
	cfgPath := c.Path()

	err = Load(cfgPath, dst)
	return
}
<commit_msg>remove err return from ExpandUser()<commit_after>// Package config version v1.0.0
package config

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"reflect"
	"strings"

	"gopkg.in/yaml.v2"
)

// Namespace holds the pieces joined together to form the
// directory namespacing for config.
type Namespace struct {
	Organization string // optional additional namespace for orgs.
	System       string // Name of the system associated with this config.
}

// The Config interface implements config.
type Config interface {
	Load(src string, dst interface{}) error
}

// UserBase and SystemBase are the prefixes for the user and system config
// paths, respectively.
const (
	UserBase   string = "~/.config/"
	SystemBase string = "/etc/"
)

// Load expands the provided src path using config.ExpandUser, then reads
// the file and unmarshals into dst using go-yaml.
func Load(src string, dst interface{}) (err error) {
	dstv := reflect.ValueOf(dst)

	if dstv.Kind() != reflect.Ptr {
		err = errors.New("config: not a pointer")
	}
	if err != nil {
		return
	}

	path := ExpandUser(src)

	data, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	err = yaml.Unmarshal(data, dst)
	return
}

// ExpandUser acts kind of like os.path.expanduser in Python, except only
// supports expanding "~/" or "$HOME"
func ExpandUser(path string) (exPath string) {
	usr, err := user.Current()
	if err != nil {
		return
	}

	dir := fmt.Sprintf("%s/", usr.HomeDir)

	exPath = path
	if len(path) > 2 && path[:2] == "~/" {
		exPath = strings.Replace(exPath, "~/", dir, 1)
	} else if len(path) > 5 && path[:5] == "$HOME" {
		exPath = strings.Replace(exPath, "$HOME", dir, 1)
	}

	exPath, err = filepath.Abs(filepath.Clean(exPath))

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

	return
}

// Path returns path to config, chosen by hierarchy and checked for
// existence:
//
// 1. User config (~/.config/podhub/canary/config.yaml)
//
// 2. System config (/etc/podhub/canary/config.yaml)
func (c Namespace) Path() (path string) {
	systemPath, _ := c.systemPath()
	if _, err := os.Stat(systemPath); err == nil {
		path, _ = c.systemPath()
	}

	userPath, _ := c.userPath()
	if _, err := os.Stat(userPath); err == nil {
		path, _ = c.userPath()
	}
	return
}

func (c Namespace) systemPath() (path string, err error) {
	path = filepath.Join(SystemBase, c.Organization, c.System, "config.yaml")
	return
}

func (c Namespace) userPath() (path string, err error) {
	userBase := ExpandUser(UserBase)

	path = filepath.Join(userBase, c.Organization, c.System, "config.yaml")
	return
}

// Load is a convenience function registered to config.Namespace to
// implement Config.Load().
func (c Namespace) Load(dst interface{}) (err error) {
	cfgPath := c.Path()

	err = Load(cfgPath, dst)
	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"runtime/debug"
	"sort"
	"strconv"
	"strings"
	"time"
)

var configLastRead = map[string]time.Time{}

func configReader(dirName string, Zones Zones) {
	go func() {
		for {
			configReadDir(dirName, Zones)
			time.Sleep(5 * time.Second)
		}
	}()
}

func configReadDir(dirName string, Zones Zones) {
	dir, err := ioutil.ReadDir(dirName)
	if err != nil {
		panic(err)
	}

	var seenFiles = map[string]bool{}

	for _, file := range dir {
		fileName := file.Name()
		if !strings.HasSuffix(strings.ToLower(fileName), ".json") {
			continue
		}

		seenFiles[fileName] = true

		if lastRead, ok := configLastRead[fileName]; !ok || file.ModTime().After(lastRead) {
			log.Println("Updated file, going to read", fileName)
			configLastRead[fileName] = file.ModTime()
			zoneName := fileName[0:strings.LastIndex(fileName, ".")]
			//log.Println("FILE:", i, file, zoneName)
			config, err := readZoneFile(zoneName, path.Join(dirName, fileName))
			if config == nil || err != nil {
				log.Println("error reading file: ", err)
			}
			if config != nil && err == nil {
				Zones[zoneName] = config
				dns.HandleFunc(zoneName, setupServerFunc(config))
			}
		}

		// TODO(ask) Disable zones not seen in two subsequent runs
	}
}

func setupPgeodnsZone(Zones Zones) {
	zoneName := "pgeodns"
	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)
	Zones[zoneName] = Zone
	dns.HandleFunc(zoneName, setupServerFunc(Zone))
}

func readZoneFile(zoneName, fileName string) (*Zone, error) {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("reading %s failed: %s", zoneName, err)
			debug.PrintStack()
		}
	}()

	fh, err := os.Open(fileName)
	if err != nil {
		log.Println("Could not read ", fileName, ": ", err)
		panic(err)
	}

	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)

	if err == nil {
		var objmap map[string]interface{}
		decoder := json.NewDecoder(fh)
		err := decoder.Decode(&objmap)
		if err != nil {
			panic(err)
		}
		//log.Println(objmap)

		var data map[string]interface{}

		for k, v := range objmap {
			//log.Printf("k: %s v: %#v, T: %T\n", k, v, v)

			switch k {
			case "ttl", "serial":
				switch option := k; option {
				case "ttl":
					Zone.Options.Ttl = int(v.(float64))
				case "serial":
					Zone.Options.Serial = int(v.(float64))
				}
				continue

			case "data":
				data = v.(map[string]interface{})
			}
		}

		setupZoneData(data, Zone)

	}

	//log.Printf("ZO T: %T %s\n", Zones["0.us"], Zones["0.us"])

	//log.Println("IP", string(Zone.Regions["0.us"].IPv4[0].ip))

	return Zone, nil
}

func setupZoneData(data map[string]interface{}, Zone *Zone) {

	var recordTypes = map[string]uint16{
		"a":     dns.TypeA,
		"aaaa":  dns.TypeAAAA,
		"ns":    dns.TypeNS,
		"cname": dns.TypeCNAME,
		"alias": dns.TypeMF,
	}

	for dk, dv := range data {

		//log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv)

		Zone.Labels[dk] = new(Label)
		label := Zone.Labels[dk]
		label.Label = dk

		// BUG(ask) Read 'ttl' value in label data

		for rType, dnsType := range recordTypes {

			var rdata = dv.(map[string]interface{})[rType]

			if rdata == nil {
				//log.Printf("No %s records for label %s\n", rType, dk)
				continue
			}

			//log.Printf("rdata %s TYPE-R %T\n", rdata, rdata)

			records := make(map[string][]interface{})

			switch rdata.(type) {
			case map[string]interface{}:
				// Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>]
				tmp := make([]interface{}, 0)
				for rdata_k, rdata_v := range rdata.(map[string]interface{}) {
					if rdata_v == nil {
						rdata_v = ""
					}
					tmp = append(tmp, []string{rdata_k, rdata_v.(string)})
				}
				records[rType] = tmp
			case string:
				// CNAME and alias
				tmp := make([]interface{}, 1)
				tmp[0] = rdata.(string)
				records[rType] = tmp
			default:
				records[rType] = rdata.([]interface{})
			}

			//log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records)

			if label.Records == nil {
				label.Records = make(map[uint16]Records)
				label.Weight = make(map[uint16]int)
			}

			label.Records[dnsType] = make(Records, len(records[rType]))

			for i := 0; i < len(records[rType]); i++ {

				//log.Printf("RT %T %#v\n", records[rType][i], records[rType][i])

				record := new(Record)

				var h dns.RR_Header
				// log.Println("TTL OPTIONS", Zone.Options.Ttl)
				h.Ttl = uint32(Zone.Options.Ttl)
				h.Class = dns.ClassINET
				h.Rrtype = dnsType
				h.Name = label.Label + "." + Zone.Origin + "."

				switch dnsType {
				case dns.TypeA, dns.TypeAAAA:
					rec := records[rType][i].([]interface{})
					ip := rec[0].(string)
					var err error
					switch rec[1].(type) {
					case string:
						record.Weight, err = strconv.Atoi(rec[1].(string))
						if err != nil {
							panic("Error converting weight to integer")
						}
						label.Weight[dnsType] += record.Weight
					case float64:
						record.Weight = int(rec[1].(float64))
					}
					switch dnsType {
					case dns.TypeA:
						rr := &dns.RR_A{Hdr: h}
						rr.A = net.ParseIP(ip)
						if rr.A == nil {
							panic("Bad A record")
						}
						record.RR = rr
					case dns.TypeAAAA:
						rr := &dns.RR_AAAA{Hdr: h}
						rr.AAAA = net.ParseIP(ip)
						if rr.AAAA == nil {
							panic("Bad AAAA record")
						}
						record.RR = rr
					}

				case dns.TypeCNAME:
					rec := records[rType][i]
					rr := &dns.RR_CNAME{Hdr: h}
					rr.Target = rec.(string)
					record.RR = rr

				case dns.TypeMF:
					rec := records[rType][i]
					rr := &dns.RR_MF{Hdr: h}
					rr.Mf = rec.(string)
					record.RR = rr

				case dns.TypeNS:
					rec := records[rType][i]
					rr := &dns.RR_NS{Hdr: h}

					switch rec.(type) {
					case string:
						rr.Ns = rec.(string)
					case []string:
						recl := rec.([]string)
						rr.Ns = recl[0]
						if len(recl[1]) > 0 {
							log.Println("NS records with names syntax not supported")
						}
					default:
						log.Printf("Data: %T %#v\n", rec, rec)
						panic("Unrecognized NS format/syntax")
					}

					if h.Ttl < 43000 {
						h.Ttl = 43200
					}
					record.RR = rr

				default:
					log.Println("type:", rType)
					panic("Don't know how to handle this type")
				}

				if record.RR == nil {
					panic("record.RR is nil")
				}

				label.Records[dnsType][i] = *record
			}
			if label.Weight[dnsType] > 0 {
				sort.Sort(RecordsByWeight{label.Records[dnsType]})
			}
		}
	}

	setupSOA(Zone)

	//log.Println(Zones[k])
}

func setupSOA(Zone *Zone) {
	label := Zone.Labels[""]

	primaryNs := "ns"

	if record, ok := label.Records[dns.TypeNS]; ok {
		primaryNs = record[0].RR.(*dns.RR_NS).Ns
	}

	s := Zone.Origin + ". 3600 IN SOA " +
		primaryNs + " support.bitnames.com. " +
		strconv.Itoa(Zone.Options.Serial) +
		" 5400 5400 2419200 " +
		strconv.Itoa(Zone.Options.Ttl)

	log.Println("SOA: ", s)

	rr, err := dns.NewRR(s)

	if err != nil {
		log.Println("SOA Error", err)
		panic("Could not setup SOA")
	}

	record := Record{RR: rr}

	label.Records[dns.TypeSOA] = make([]Record, 1)
	label.Records[dns.TypeSOA][0] = record

}
<commit_msg>Don't crash on NXDOMAIN results from the pgeodns zone<commit_after>package main

import (
	"encoding/json"
	"github.com/miekg/dns"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"runtime/debug"
	"sort"
	"strconv"
	"strings"
	"time"
)

var configLastRead = map[string]time.Time{}

func configReader(dirName string, Zones Zones) {
	go func() {
		for {
			configReadDir(dirName, Zones)
			time.Sleep(5 * time.Second)
		}
	}()
}

func configReadDir(dirName string, Zones Zones) {
	dir, err := ioutil.ReadDir(dirName)
	if err != nil {
		panic(err)
	}

	var seenFiles = map[string]bool{}

	for _, file := range dir {
		fileName := file.Name()
		if !strings.HasSuffix(strings.ToLower(fileName), ".json") {
			continue
		}

		seenFiles[fileName] = true

		if lastRead, ok := configLastRead[fileName]; !ok || file.ModTime().After(lastRead) {
			log.Println("Updated file, going to read", fileName)
			configLastRead[fileName] = file.ModTime()
			zoneName := fileName[0:strings.LastIndex(fileName, ".")]
			//log.Println("FILE:", i, file, zoneName)
			config, err := readZoneFile(zoneName, path.Join(dirName, fileName))
			if config == nil || err != nil {
				log.Println("error reading file: ", err)
			}
			if config != nil && err == nil {
				Zones[zoneName] = config
				dns.HandleFunc(zoneName, setupServerFunc(config))
			}
		}

		// TODO(ask) Disable zones not seen in two subsequent runs
	}
}

func setupPgeodnsZone(Zones Zones) {
	zoneName := "pgeodns"
	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)
	label := new(Label)
	label.Records = make(map[uint16]Records)
	label.Weight = make(map[uint16]int)
	Zone.Labels[""] = label
	setupSOA(Zone)
	Zones[zoneName] = Zone
	dns.HandleFunc(zoneName, setupServerFunc(Zone))
}

func readZoneFile(zoneName, fileName string) (*Zone, error) {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("reading %s failed: %s", zoneName, err)
			debug.PrintStack()
		}
	}()

	fh, err := os.Open(fileName)
	if err != nil {
		log.Println("Could not read ", fileName, ": ", err)
		panic(err)
	}

	Zone := new(Zone)
	Zone.Labels = make(labels)
	Zone.Origin = zoneName
	Zone.LenLabels = dns.LenLabels(Zone.Origin)

	if err == nil {
		var objmap map[string]interface{}
		decoder := json.NewDecoder(fh)
		err := decoder.Decode(&objmap)
		if err != nil {
			panic(err)
		}
		//log.Println(objmap)

		var data map[string]interface{}

		for k, v := range objmap {
			//log.Printf("k: %s v: %#v, T: %T\n", k, v, v)

			switch k {
			case "ttl", "serial":
				switch option := k; option {
				case "ttl":
					Zone.Options.Ttl = int(v.(float64))
				case "serial":
					Zone.Options.Serial = int(v.(float64))
				}
				continue

			case "data":
				data = v.(map[string]interface{})
			}
		}

		setupZoneData(data, Zone)

	}

	//log.Printf("ZO T: %T %s\n", Zones["0.us"], Zones["0.us"])

	//log.Println("IP", string(Zone.Regions["0.us"].IPv4[0].ip))

	return Zone, nil
}

func setupZoneData(data map[string]interface{}, Zone *Zone) {

	var recordTypes = map[string]uint16{
		"a":     dns.TypeA,
		"aaaa":  dns.TypeAAAA,
		"ns":    dns.TypeNS,
		"cname": dns.TypeCNAME,
		"alias": dns.TypeMF,
	}

	for dk, dv := range data {

		//log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv)

		Zone.Labels[dk] = new(Label)
		label := Zone.Labels[dk]
		label.Label = dk

		// BUG(ask) Read 'ttl' value in label data

		for rType, dnsType := range recordTypes {

			var rdata = dv.(map[string]interface{})[rType]

			if rdata == nil {
				//log.Printf("No %s records for label %s\n", rType, dk)
				continue
			}

			//log.Printf("rdata %s TYPE-R %T\n", rdata, rdata)

			records := make(map[string][]interface{})

			switch rdata.(type) {
			case map[string]interface{}:
				// Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>]
				tmp := make([]interface{}, 0)
				for rdata_k, rdata_v := range rdata.(map[string]interface{}) {
					if rdata_v == nil {
						rdata_v = ""
					}
					tmp = append(tmp, []string{rdata_k, rdata_v.(string)})
				}
				records[rType] = tmp
			case string:
				// CNAME and alias
				tmp := make([]interface{}, 1)
				tmp[0] = rdata.(string)
				records[rType] = tmp
			default:
				records[rType] = rdata.([]interface{})
			}

			//log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records)

			if label.Records == nil {
				label.Records = make(map[uint16]Records)
				label.Weight = make(map[uint16]int)
			}

			label.Records[dnsType] = make(Records, len(records[rType]))

			for i := 0; i < len(records[rType]); i++ {

				//log.Printf("RT %T %#v\n", records[rType][i], records[rType][i])

				record := new(Record)

				var h dns.RR_Header
				// log.Println("TTL OPTIONS", Zone.Options.Ttl)
				h.Ttl = uint32(Zone.Options.Ttl)
				h.Class = dns.ClassINET
				h.Rrtype = dnsType
				h.Name = label.Label + "." + Zone.Origin + "."

				switch dnsType {
				case dns.TypeA, dns.TypeAAAA:
					rec := records[rType][i].([]interface{})
					ip := rec[0].(string)
					var err error
					switch rec[1].(type) {
					case string:
						record.Weight, err = strconv.Atoi(rec[1].(string))
						if err != nil {
							panic("Error converting weight to integer")
						}
						label.Weight[dnsType] += record.Weight
					case float64:
						record.Weight = int(rec[1].(float64))
					}
					switch dnsType {
					case dns.TypeA:
						rr := &dns.RR_A{Hdr: h}
						rr.A = net.ParseIP(ip)
						if rr.A == nil {
							panic("Bad A record")
						}
						record.RR = rr
					case dns.TypeAAAA:
						rr := &dns.RR_AAAA{Hdr: h}
						rr.AAAA = net.ParseIP(ip)
						if rr.AAAA == nil {
							panic("Bad AAAA record")
						}
						record.RR = rr
					}

				case dns.TypeCNAME:
					rec := records[rType][i]
					rr := &dns.RR_CNAME{Hdr: h}
					rr.Target = rec.(string)
					record.RR = rr

				case dns.TypeMF:
					rec := records[rType][i]
					rr := &dns.RR_MF{Hdr: h}
					rr.Mf = rec.(string)
					record.RR = rr

				case dns.TypeNS:
					rec := records[rType][i]
					rr := &dns.RR_NS{Hdr: h}

					switch rec.(type) {
					case string:
						rr.Ns = rec.(string)
					case []string:
						recl := rec.([]string)
						rr.Ns = recl[0]
						if len(recl[1]) > 0 {
							log.Println("NS records with names syntax not supported")
						}
					default:
						log.Printf("Data: %T %#v\n", rec, rec)
						panic("Unrecognized NS format/syntax")
					}

					if h.Ttl < 43000 {
						h.Ttl = 43200
					}
					record.RR = rr

				default:
					log.Println("type:", rType)
					panic("Don't know how to handle this type")
				}

				if record.RR == nil {
					panic("record.RR is nil")
				}

				label.Records[dnsType][i] = *record
			}
			if label.Weight[dnsType] > 0 {
				sort.Sort(RecordsByWeight{label.Records[dnsType]})
			}
		}
	}

	setupSOA(Zone)

	//log.Println(Zones[k])
}

func setupSOA(Zone *Zone) {
	label := Zone.Labels[""]

	primaryNs := "ns"

	if record, ok := label.Records[dns.TypeNS]; ok {
		primaryNs = record[0].RR.(*dns.RR_NS).Ns
	}

	s := Zone.Origin + ". 3600 IN SOA " +
		primaryNs + " support.bitnames.com. " +
		strconv.Itoa(Zone.Options.Serial) +
		" 5400 5400 2419200 " +
		strconv.Itoa(Zone.Options.Ttl)

	log.Println("SOA: ", s)

	rr, err := dns.NewRR(s)

	if err != nil {
		log.Println("SOA Error", err)
		panic("Could not setup SOA")
	}

	record := Record{RR: rr}

	label.Records[dns.TypeSOA] = make([]Record, 1)
	label.Records[dns.TypeSOA][0] = record

}
<|endoftext|>