<commit_before>/*
Copyright AppsCode Inc. and Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	"fmt"
	"strings"

	apiv1 "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/client-go/apiextensions"
	"kmodules.xyz/resource-metadata/crds"
)

func (v ResourceDescriptor) CustomResourceDefinition() *apiextensions.CustomResourceDefinition {
	return crds.MustCustomResourceDefinition(SchemeGroupVersion.WithResource(ResourceResourceDescriptors))
}

func (v ResourceDescriptor) IsValid() error {
	return nil
}

func IsOfficialType(group string) bool {
	switch {
	case group == "":
		return true
	case !strings.ContainsRune(group, '.'):
		return true
	case group == "k8s.io" || strings.HasSuffix(group, ".k8s.io"):
		return true
	case group == "kubernetes.io" || strings.HasSuffix(group, ".kubernetes.io"):
		return true
	case group == "x-k8s.io" || strings.HasSuffix(group, ".x-k8s.io"):
		return true
	default:
		return false
	}
}

func (r ResourceLocator) GraphQuery(oid apiv1.OID) (string, map[string]interface{}) {
	vars := map[string]interface{}{
		"src":         string(oid),
		"targetGroup": r.Ref.Group,
		"targetKind":  r.Ref.Kind,
	}

	if r.Query.Raw != "" {
		return r.Query.Raw, vars
	}
	return fmt.Sprintf(`query Find($src: String!, $targetGroup: String!, $targetKind: String!) {
  find(oid: $src) {
    refs: %s(group: $targetGroup, kind: $targetKind) {
      namespace
      name
    }
  }
}`, r.Query.ByLabel), vars
}
<commit_msg>Add constants for GraphQL vars<commit_after>/*
Copyright AppsCode Inc. and Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	"fmt"
	"strings"

	apiv1 "kmodules.xyz/client-go/api/v1"
	"kmodules.xyz/client-go/apiextensions"
	"kmodules.xyz/resource-metadata/crds"
)

func (v ResourceDescriptor) CustomResourceDefinition() *apiextensions.CustomResourceDefinition {
	return crds.MustCustomResourceDefinition(SchemeGroupVersion.WithResource(ResourceResourceDescriptors))
}

func (v ResourceDescriptor) IsValid() error {
	return nil
}

func IsOfficialType(group string) bool {
	switch {
	case group == "":
		return true
	case !strings.ContainsRune(group, '.'):
		return true
	case group == "k8s.io" || strings.HasSuffix(group, ".k8s.io"):
		return true
	case group == "kubernetes.io" || strings.HasSuffix(group, ".kubernetes.io"):
		return true
	case group == "x-k8s.io" || strings.HasSuffix(group, ".x-k8s.io"):
		return true
	default:
		return false
	}
}

const (
	GraphQueryVarSource      = "src"
	GraphQueryVarTargetGroup = "targetGroup"
	GraphQueryVarTargetKind  = "targetKind"
)

func (r ResourceLocator) GraphQuery(oid apiv1.OID) (string, map[string]interface{}) {
	vars := map[string]interface{}{
		GraphQueryVarSource:      string(oid),
		GraphQueryVarTargetGroup: r.Ref.Group,
		GraphQueryVarTargetKind:  r.Ref.Kind,
	}

	if r.Query.Raw != "" {
		return r.Query.Raw, vars
	}
	return fmt.Sprintf(`query Find($src: String!, $targetGroup: String!, $targetKind: String!) {
  find(oid: $src) {
    refs: %s(group: $targetGroup, kind: $targetKind) {
      namespace
      name
    }
  }
}`, r.Query.ByLabel), vars
}
<|endoftext|>


<commit_before>package webhook

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/stripe/stripe-go"
)

const ToleranceDefault int64 = 300
const ToleranceIgnoreTimestamp int64 = 0

var ErrNotSigned error = errors.New("Webhook has no Stripe-Signature header")
var ErrNoTimestamp error = errors.New("Webhook has no timestamp")
var ErrTooOld error = errors.New("Webhook had valid signature but timestamp wasn't within tolerance")
var ErrNoValidSignature error = errors.New("Webhook had no valid signature")

// ConstructEvent initializes an Event object from a JSON payload.
// It returns an non-nil error when the payload is not valid JSON or when signature verification fails.
// payload is the webhook request body, i.e. `ioutil.ReadAll(r.Body)`.
// sigHeader is the webhook Stripe-Signature header, i.e. `r.Header.Get("Stripe-Signature")`.
// secret is your Signing Secret, i.e. `"whsec_XYZ"`.  See https://dashboard.stripe.com/webhooks
// tolerance (suggested 300) is the max difference in seconds between now and Stripe-Signature's timestamp. If the difference is greater than this tolerance, the signature is rejected and a non-nil error is returned.  If tolerance is 0 or less, then the timestamp is not checked.
// NOTE: your requests will only have Stripe-Signature if you have clicked to reveal your secret
func ConstructEvent(payload []byte, sigHeader string, secret string, tolerance int64) (stripe.Event, error) {
	e := stripe.Event{}

	if err := json.Unmarshal(payload, &e); err != nil {
		return e, fmt.Errorf("Failed to parse webhook body json: %s", err.Error())
	}

	if sigHeader == "" {
		return e, ErrNotSigned
	}

	// sigHeader looks like "t=1495999758,v1=ABC,v1=DEF,v0=GHI"

	// First extract the timestamp
	var t string
	pairs := strings.Split(sigHeader, ",")
	for _, pair := range pairs {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 || parts[0] != "t" {
			continue
		}

		t = parts[1]
		break
	}

	if t == "" {
		return e, ErrNoTimestamp
	}

	invalidTimestamp := false
	if tolerance > 0 {
		timestamp, err := strconv.ParseInt(t, 10, 64)
		if err == nil {
			currentTimestamp := time.Now().Unix()

			diff := timestamp - currentTimestamp
			if diff < 0 {
				diff = -diff
			}

			if diff > tolerance {
				invalidTimestamp = true
			}
		} else {
			invalidTimestamp = true
		}
	}

	// Compute the expected signature.
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(t))
	mac.Write([]byte("."))
	mac.Write(payload)
	res := mac.Sum(nil)

	// Check all given v1 signatures since multiple v1 can happen in case of rolled secret.
	for _, pair := range pairs {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 || parts[0] != "v1" {
			continue
		}

		sig, err := hex.DecodeString(parts[1])
		if err != nil {
			// Ignore signature which isn't valid hex.
			continue
		}

		if hmac.Equal(res, sig) {
			if invalidTimestamp {
				return e, ErrTooOld
			}

			// OK
			return e, nil
		}
	}

	return e, ErrNoValidSignature
}
<commit_msg>Extract computeSignature.<commit_after>package webhook

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/stripe/stripe-go"
)

const SigningVersion string = "v1"

// computeSignature computes a signature using stripe's v1 signing method.
func computeSignature(t string, payload []byte, secret string) []byte {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(t))
	mac.Write([]byte("."))
	mac.Write(payload)
	return mac.Sum(nil)
}

const ToleranceDefault int64 = 300
const ToleranceIgnoreTimestamp int64 = 0

var ErrNotSigned error = errors.New("Webhook has no Stripe-Signature header")
var ErrNoTimestamp error = errors.New("Webhook has no timestamp")
var ErrTooOld error = errors.New("Webhook had valid signature but timestamp wasn't within tolerance")
var ErrNoValidSignature error = errors.New("Webhook had no valid signature")

// ConstructEvent initializes an Event object from a JSON payload.
// It returns an non-nil error when the payload is not valid JSON or when signature verification fails.
// payload is the webhook request body, i.e. `ioutil.ReadAll(r.Body)`.
// sigHeader is the webhook Stripe-Signature header, i.e. `r.Header.Get("Stripe-Signature")`.
// secret is your Signing Secret, i.e. `"whsec_XYZ"`.  See https://dashboard.stripe.com/webhooks
// tolerance (suggested 300) is the max difference in seconds between now and Stripe-Signature's timestamp. If the difference is greater than this tolerance, the signature is rejected and a non-nil error is returned.  If tolerance is 0 or less, then the timestamp is not checked.
// NOTE: your requests will only have Stripe-Signature if you have clicked to reveal your secret
func ConstructEvent(payload []byte, sigHeader string, secret string, tolerance int64) (stripe.Event, error) {
	e := stripe.Event{}

	if err := json.Unmarshal(payload, &e); err != nil {
		return e, fmt.Errorf("Failed to parse webhook body json: %s", err.Error())
	}

	if sigHeader == "" {
		return e, ErrNotSigned
	}

	// sigHeader looks like "t=1495999758,v1=ABC,v1=DEF,v0=GHI"

	// First extract the timestamp
	var t string
	pairs := strings.Split(sigHeader, ",")
	for _, pair := range pairs {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 || parts[0] != "t" {
			continue
		}

		t = parts[1]
		break
	}

	if t == "" {
		return e, ErrNoTimestamp
	}

	invalidTimestamp := false
	if tolerance > 0 {
		timestamp, err := strconv.ParseInt(t, 10, 64)
		if err == nil {
			currentTimestamp := time.Now().Unix()

			diff := timestamp - currentTimestamp
			if diff < 0 {
				diff = -diff
			}

			if diff > tolerance {
				invalidTimestamp = true
			}
		} else {
			invalidTimestamp = true
		}
	}

	expectedSignature := computeSignature(t, payload, secret)

	// Check all given v1 signatures since multiple v1 can happen in case of rolled secret.
	for _, pair := range pairs {
		parts := strings.Split(pair, "=")
		if len(parts) != 2 || parts[0] != SigningVersion {
			continue
		}

		sig, err := hex.DecodeString(parts[1])
		if err != nil {
			// Ignore signature which isn't valid hex.
			continue
		}

		if hmac.Equal(expectedSignature, sig) {
			if invalidTimestamp {
				return e, ErrTooOld
			}

			// OK
			return e, nil
		}
	}

	return e, ErrNoValidSignature
}
<|endoftext|>


<commit_before>// Package xkcd allows access to metadata for xkcd comics.
package xkcd

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
)

// Comic is a struct that contains infomation about an xkcd comic.
type Comic struct {
	Num        int    `json:"num"`
	Title      string `json:"title"`
	SafeTitle  string `json:"safe_title"`
	Img        string `json:"img"`
	Alt        string `json:"alt"`
	Year       string `json:"year"`
	Month      string `json:"month"`
	Day        string `json:"day"`
	News       string `json:"news"`
	Link       string `json:"link"`
	Transcript string `json:"transcript"`
}

// New reads from an io.Reader and returns a *Comic struct.
func New(r io.Reader) (*Comic, error) {
	d := json.NewDecoder(r)
	c := new(Comic)
	err := d.Decode(c)
	return c, err
}

const (
	currentURL  = "http://xkcd.com/info.0.json"
	templateURL = "http://xkcd.com/%v/info.0.json"
)

// Get fetches information about the xkcd comic number `n'.
func Get(n int) (*Comic, error) {
	url := fmt.Sprintf(templateURL, n)
	return getByURL(url)
}

// GetCurrent fetches information for the newest xkcd comic.
func GetCurrent() (*Comic, error) {
	return getByURL(currentURL)
}

var ErrNotFound = errors.New("Error retrieving comic")

// getByURL returns infomation downloaded from `url'.
func getByURL(url string) (*Comic, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		return nil, ErrNotFound
	}
	return New(resp.Body)
}
<commit_msg>I try spell better<commit_after>// Package xkcd allows access to metadata for xkcd comics.
package xkcd

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
)

// Comic is a struct that contains information about an xkcd comic.
type Comic struct {
	Num        int    `json:"num"`
	Title      string `json:"title"`
	SafeTitle  string `json:"safe_title"`
	Img        string `json:"img"`
	Alt        string `json:"alt"`
	Year       string `json:"year"`
	Month      string `json:"month"`
	Day        string `json:"day"`
	News       string `json:"news"`
	Link       string `json:"link"`
	Transcript string `json:"transcript"`
}

// New reads from an io.Reader and returns a *Comic struct.
func New(r io.Reader) (*Comic, error) {
	d := json.NewDecoder(r)
	c := new(Comic)
	err := d.Decode(c)
	return c, err
}

const (
	currentURL  = "http://xkcd.com/info.0.json"
	templateURL = "http://xkcd.com/%v/info.0.json"
)

// Get fetches information about the xkcd comic number `n'.
func Get(n int) (*Comic, error) {
	url := fmt.Sprintf(templateURL, n)
	return getByURL(url)
}

// GetCurrent fetches information for the newest xkcd comic.
func GetCurrent() (*Comic, error) {
	return getByURL(currentURL)
}

var ErrNotFound = errors.New("Error retrieving comic")

// getByURL returns information downloaded from `url'.
func getByURL(url string) (*Comic, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		return nil, ErrNotFound
	}
	return New(resp.Body)
}
<|endoftext|>


<commit_before>// Package implements creation of XLSX simple spreadsheet files

package xlsx

import (
	"archive/zip"
	"bufio"
	"bytes"
	"fmt"
	"html"
	"io"
	"os"
	"strconv"
	"time"
)

type CellType uint

// Basic spreadsheet cell types
const (
	CellTypeNumber CellType = iota
	CellTypeString
	CellTypeDatetime
	CellTypeInlineString
)

// XLSX Spreadsheet Cell
type Cell struct {
	Type    CellType
	Value   string
	Colspan uint64
}

// XLSX Spreadsheet Row
type Row struct {
	Cells []Cell
}

// XLSX Spreadsheet Column
type Column struct {
	Name  string
	Width uint64
}

// XLSX Workbook Document Properties
type DocumentInfo struct {
	CreatedBy  string
	ModifiedBy string
	CreatedAt  time.Time
	ModifiedAt time.Time
}

// XLSX Spreadsheet
type Sheet struct {
	Title           string
	columns         []Column
	rows            []Row
	sharedStringMap map[string]int
	sharedStrings   []string
	DocumentInfo    DocumentInfo
}

// Create a sheet with no dimensions
func NewSheet() Sheet {
	c := make([]Column, 0)
	r := make([]Row, 0)
	ssm := make(map[string]int)
	sst := make([]string, 0)

	s := Sheet{
		Title:           "Data",
		columns:         c,
		rows:            r,
		sharedStringMap: ssm,
		sharedStrings:   sst,
	}

	return s
}

// Create a sheet with dimensions derived from the given columns
func NewSheetWithColumns(c []Column) Sheet {
	r := make([]Row, 0)
	ssm := make(map[string]int)
	sst := make([]string, 0)

	s := Sheet{
		Title:           "Data",
		columns:         c,
		rows:            r,
		sharedStringMap: ssm,
		sharedStrings:   sst,
	}

	s.DocumentInfo.CreatedBy = "xlsx.go"
	s.DocumentInfo.CreatedAt = time.Now()

	s.DocumentInfo.ModifiedBy = s.DocumentInfo.CreatedBy
	s.DocumentInfo.ModifiedAt = s.DocumentInfo.CreatedAt

	return s
}

// Create a new row with a length caculated by the sheets known column count
func (s *Sheet) NewRow() Row {
	c := make([]Cell, len(s.columns))
	r := Row{
		Cells: c,
	}
	return r
}

// Append a row to the sheet
func (s *Sheet) AppendRow(r Row) error {
	if len(r.Cells) != len(s.columns) {
		return fmt.Errorf("the given row has %d cells and %d were expected", len(r.Cells), len(s.columns))
	}

	cells := make([]Cell, len(s.columns))

	for n, c := range r.Cells {
		cells[n].Type = c.Type
		cells[n].Value = c.Value

		if cells[n].Type == CellTypeString {
			// calculate string reference
			cells[n].Value = html.EscapeString(cells[n].Value)
			i, exists := s.sharedStringMap[cells[n].Value]
			if !exists {
				i = len(s.sharedStrings)
				s.sharedStringMap[cells[n].Value] = i
				s.sharedStrings = append(s.sharedStrings, cells[n].Value)
			}
			cells[n].Value = strconv.Itoa(i)
		}
	}

	row := s.NewRow()
	row.Cells = cells

	s.rows = append(s.rows, row)

	return nil
}

// Get the Shared Strings in the order they were added to the map
func (s *Sheet) SharedStrings() []string {
	return s.sharedStrings
}

// Given zero-based array indices output the Excel cell reference. For
// example (0,0) => "A1"; (2,2) => "C3"; (26,45) => "AA46"
func CellIndex(x, y uint64) (string, uint64) {
	return colName(x), (y + 1)
}

// From a zero-based column number return the Excel column name.
// For example: 0 => "A"; 2 => "C"; 26 => "AA"
func colName(n uint64) string {
	var s string
	n += 1

	for n > 0 {
		n -= 1
		s = string(65+(n%26)) + s
		n /= 26
	}

	return s
}

// Convert time to the OLE Automation format.
func OADate(d time.Time) string {
	epoch := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
	nsPerDay := 24 * time.Hour

	v := -1 * float64(epoch.Sub(d)) / float64(nsPerDay)

	// TODO: deal with dates before epoch
	// e.g. http://stackoverflow.com/questions/15549823/oadate-to-milliseconds-timestamp-in-javascript/15550284#15550284

	if d.Hour() == 0 && d.Minute() == 0 && d.Second() == 0 {
		return fmt.Sprintf("%d", int64(v))
	} else {
		return fmt.Sprintf("%f", v)
	}
}

// Create filename and save the XLSX file
func (s *Sheet) SaveToFile(filename string) error {
	outputfile, err := os.Create(filename)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(outputfile)
	err = s.SaveToWriter(w)
	defer w.Flush()
	return err
}

// Save the XLSX file to the given writer
func (s *Sheet) SaveToWriter(w io.Writer) error {

	ww := NewWorkbookWriter(w)

	sw, err := ww.NewSheetWriter(s)
	if err != nil {
		return err
	}

	err = sw.WriteRows(s.rows)
	if err != nil {
		return err
	}

	ww.SharedStrings = s.sharedStrings

	err = ww.Close()

	return err
}

// Write the header files of the workbook
func (ww *WorkbookWriter) WriteHeader() error {
	if ww.headerWritten {
		panic("Workbook header already written")
	}

	z := ww.zipWriter

	f, err := z.Create("[Content_Types].xml")
	err = TemplateContentTypes.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("docProps/app.xml")
	err = TemplateApp.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("docProps/core.xml")
	err = TemplateCore.Execute(f, ww.documentInfo)
	if err != nil {
		return err
	}

	f, err = z.Create("_rels/.rels")
	err = TemplateRelationships.Execute(f, nil)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/workbook.xml")
	err = TemplateWorkbook.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/_rels/workbook.xml.rels")
	err = TemplateWorkbookRelationships.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/styles.xml")
	err = TemplateStyles.Execute(f, nil)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/sharedStrings.xml")
	err = TemplateStringLookups.Execute(f, ww.SharedStrings)
	if err != nil {
		return err
	}

	return err
}

// Handles the writing of an XLSX workbook
type WorkbookWriter struct {
	zipWriter     *zip.Writer
	sheetWriter   *SheetWriter
	headerWritten bool
	closed        bool
	sheetNames    []string
	SharedStrings []string
	documentInfo  *DocumentInfo
}

// Creates a new WorkbookWriter
func NewWorkbookWriter(w io.Writer) *WorkbookWriter {
	return &WorkbookWriter{zip.NewWriter(w), nil, false, false, []string{}, nil, nil}
}

// Closes the WorkbookWriter
func (ww *WorkbookWriter) Close() error {
	if ww.closed {
		panic("WorkbookWriter already closed")
	}

	if ww.sheetWriter != nil {
		err := ww.sheetWriter.Close()
		if err != nil {
			return err
		}
	}

	if !ww.headerWritten {
		err := ww.WriteHeader()
		if err != nil {
			return err
		}
	}

	ww.closed = true

	return ww.zipWriter.Close()
}

// NewSheetWriter creates a new SheetWriter in this workbook using the given sheet.
// It returns a SheetWriter to which rows can be written.
// All rows must be written to the SheetWriter before the next call to NewSheetWriter,
// as this will automatically close the previous SheetWriter.
func (ww *WorkbookWriter) NewSheetWriter(s *Sheet) (*SheetWriter, error) {
	if ww.closed {
		panic("Can not write to closed WorkbookWriter")
	}

	if ww.sheetWriter != nil {
		err := ww.sheetWriter.Close()
		if err != nil {
			return nil, err
		}
	}

	f, err := ww.zipWriter.Create("xl/worksheets/" + fmt.Sprintf("sheet%s", strconv.Itoa(len(ww.sheetNames)+1)) + ".xml")
	sw := &SheetWriter{f, err, 0, 0, false, "", 0}

	ww.documentInfo = &s.DocumentInfo

	ww.sheetWriter = sw
	err = sw.WriteHeader(s)

	ww.sheetNames = append(ww.sheetNames, s.Title)

	return sw, err
}

// Handles the writing of a sheet
type SheetWriter struct {
	f               io.Writer
	err             error
	currentIndex    uint64
	maxNCols        uint64
	closed          bool
	mergeCells      string
	mergeCellsCount int
}

// Write the given rows to this SheetWriter
func (sw *SheetWriter) WriteRows(rows []Row) error {
	if sw.closed {
		panic("Can not write to closed SheetWriter")
	}

	var err error

	for i, r := range rows {
		rb := &bytes.Buffer{}

		if sw.maxNCols < uint64(len(r.Cells)) {
			sw.maxNCols = uint64(len(r.Cells))
		}

		for j, c := range r.Cells {

			cellX, cellY := CellIndex(uint64(j), uint64(i)+sw.currentIndex)

			if c.Type == CellTypeDatetime {
				d, err := time.Parse(time.RFC3339, c.Value)
				if err == nil {
					c.Value = OADate(d)
				}
			} else if c.Type == CellTypeInlineString {
				c.Value = html.EscapeString(c.Value)
			}

			var cellString string

			switch c.Type {
			case CellTypeString:
				cellString = `<c r="%s%d" t="s" s="1"><v>%s</v></c>`
			case CellTypeInlineString:
				cellString = `<c r="%s%d" t="inlineStr"><is><t>%s</t></is></c>`
			case CellTypeNumber:
				cellString = `<c r="%s%d" t="n" s="1"><v>%s</v></c>`
			case CellTypeDatetime:
				cellString = `<c r="%s%d" s="2"><v>%s</v></c>`
			}

			if c.Colspan < 0 {
				panic(fmt.Sprintf("%v is not a valid colspan", c.Colspan))
			} else if c.Colspan > 0 {

				mergeCellX, _ := CellIndex(uint64(j)+c.Colspan-1, uint64(i)+sw.currentIndex)
				sw.mergeCells += fmt.Sprintf(`<mergeCell ref="%[1]s%[2]d:%[3]s%[2]d"/>`, cellX, cellY, mergeCellX)
				sw.mergeCellsCount += 1
			}

			io.WriteString(rb, fmt.Sprintf(cellString, cellX, cellY, c.Value))

			if err != nil {
				return err
			}
		}

		rowString := fmt.Sprintf(`<row r="%d">%s</row>`, uint64(i)+sw.currentIndex+1, rb.String())

		_, err = io.WriteString(sw.f, rowString)
		if err != nil {
			return err
		}

	}

	sw.currentIndex += uint64(len(rows))

	return nil
}

// Closes the SheetWriter
func (sw *SheetWriter) Close() error {
	if sw.closed {
		panic("SheetWriter already closed")
	}

	cellEndX, cellEndY := CellIndex(sw.maxNCols-1, sw.currentIndex-1)
	sheetEnd := fmt.Sprintf(`<dimension ref="A1:%s%d"/></sheetData>`, cellEndX, cellEndY)
	if sw.mergeCellsCount > 0 {
		sheetEnd += fmt.Sprintf(`<mergeCells count="%v">`, sw.mergeCellsCount)
		sheetEnd += sw.mergeCells
		sheetEnd += `</mergeCells></worksheet>`
	}
	sheetEnd += `</worksheet>`
	_, err := io.WriteString(sw.f, sheetEnd)

	sw.closed = true

	return err
}

// Writes the header of a sheet
func (sw *SheetWriter) WriteHeader(s *Sheet) error {
	if sw.closed {
		panic("Can not write to closed SheetWriter")
	}

	sheet := struct {
		Cols []Column
	}{
		Cols: s.columns,
	}

	return TemplateSheetStart.Execute(sw.f, sheet)
}
<commit_msg>Only add if colspan is greater than 1<commit_after>// Package implements creation of XLSX simple spreadsheet files

package xlsx

import (
	"archive/zip"
	"bufio"
	"bytes"
	"fmt"
	"html"
	"io"
	"os"
	"strconv"
	"time"
)

type CellType uint

// Basic spreadsheet cell types
const (
	CellTypeNumber CellType = iota
	CellTypeString
	CellTypeDatetime
	CellTypeInlineString
)

// XLSX Spreadsheet Cell
type Cell struct {
	Type    CellType
	Value   string
	Colspan uint64
}

// XLSX Spreadsheet Row
type Row struct {
	Cells []Cell
}

// XLSX Spreadsheet Column
type Column struct {
	Name  string
	Width uint64
}

// XLSX Workbook Document Properties
type DocumentInfo struct {
	CreatedBy  string
	ModifiedBy string
	CreatedAt  time.Time
	ModifiedAt time.Time
}

// XLSX Spreadsheet
type Sheet struct {
	Title           string
	columns         []Column
	rows            []Row
	sharedStringMap map[string]int
	sharedStrings   []string
	DocumentInfo    DocumentInfo
}

// Create a sheet with no dimensions
func NewSheet() Sheet {
	c := make([]Column, 0)
	r := make([]Row, 0)
	ssm := make(map[string]int)
	sst := make([]string, 0)

	s := Sheet{
		Title:           "Data",
		columns:         c,
		rows:            r,
		sharedStringMap: ssm,
		sharedStrings:   sst,
	}

	return s
}

// Create a sheet with dimensions derived from the given columns
func NewSheetWithColumns(c []Column) Sheet {
	r := make([]Row, 0)
	ssm := make(map[string]int)
	sst := make([]string, 0)

	s := Sheet{
		Title:           "Data",
		columns:         c,
		rows:            r,
		sharedStringMap: ssm,
		sharedStrings:   sst,
	}

	s.DocumentInfo.CreatedBy = "xlsx.go"
	s.DocumentInfo.CreatedAt = time.Now()

	s.DocumentInfo.ModifiedBy = s.DocumentInfo.CreatedBy
	s.DocumentInfo.ModifiedAt = s.DocumentInfo.CreatedAt

	return s
}

// Create a new row with a length caculated by the sheets known column count
func (s *Sheet) NewRow() Row {
	c := make([]Cell, len(s.columns))
	r := Row{
		Cells: c,
	}
	return r
}

// Append a row to the sheet
func (s *Sheet) AppendRow(r Row) error {
	if len(r.Cells) != len(s.columns) {
		return fmt.Errorf("the given row has %d cells and %d were expected", len(r.Cells), len(s.columns))
	}

	cells := make([]Cell, len(s.columns))

	for n, c := range r.Cells {
		cells[n].Type = c.Type
		cells[n].Value = c.Value

		if cells[n].Type == CellTypeString {
			// calculate string reference
			cells[n].Value = html.EscapeString(cells[n].Value)
			i, exists := s.sharedStringMap[cells[n].Value]
			if !exists {
				i = len(s.sharedStrings)
				s.sharedStringMap[cells[n].Value] = i
				s.sharedStrings = append(s.sharedStrings, cells[n].Value)
			}
			cells[n].Value = strconv.Itoa(i)
		}
	}

	row := s.NewRow()
	row.Cells = cells

	s.rows = append(s.rows, row)

	return nil
}

// Get the Shared Strings in the order they were added to the map
func (s *Sheet) SharedStrings() []string {
	return s.sharedStrings
}

// Given zero-based array indices output the Excel cell reference. For
// example (0,0) => "A1"; (2,2) => "C3"; (26,45) => "AA46"
func CellIndex(x, y uint64) (string, uint64) {
	return colName(x), (y + 1)
}

// From a zero-based column number return the Excel column name.
// For example: 0 => "A"; 2 => "C"; 26 => "AA"
func colName(n uint64) string {
	var s string
	n += 1

	for n > 0 {
		n -= 1
		s = string(65+(n%26)) + s
		n /= 26
	}

	return s
}

// Convert time to the OLE Automation format.
func OADate(d time.Time) string {
	epoch := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
	nsPerDay := 24 * time.Hour

	v := -1 * float64(epoch.Sub(d)) / float64(nsPerDay)

	// TODO: deal with dates before epoch
	// e.g. http://stackoverflow.com/questions/15549823/oadate-to-milliseconds-timestamp-in-javascript/15550284#15550284

	if d.Hour() == 0 && d.Minute() == 0 && d.Second() == 0 {
		return fmt.Sprintf("%d", int64(v))
	} else {
		return fmt.Sprintf("%f", v)
	}
}

// Create filename and save the XLSX file
func (s *Sheet) SaveToFile(filename string) error {
	outputfile, err := os.Create(filename)
	if err != nil {
		return err
	}
	w := bufio.NewWriter(outputfile)
	err = s.SaveToWriter(w)
	defer w.Flush()
	return err
}

// Save the XLSX file to the given writer
func (s *Sheet) SaveToWriter(w io.Writer) error {

	ww := NewWorkbookWriter(w)

	sw, err := ww.NewSheetWriter(s)
	if err != nil {
		return err
	}

	err = sw.WriteRows(s.rows)
	if err != nil {
		return err
	}

	ww.SharedStrings = s.sharedStrings

	err = ww.Close()

	return err
}

// Write the header files of the workbook
func (ww *WorkbookWriter) WriteHeader() error {
	if ww.headerWritten {
		panic("Workbook header already written")
	}

	z := ww.zipWriter

	f, err := z.Create("[Content_Types].xml")
	err = TemplateContentTypes.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("docProps/app.xml")
	err = TemplateApp.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("docProps/core.xml")
	err = TemplateCore.Execute(f, ww.documentInfo)
	if err != nil {
		return err
	}

	f, err = z.Create("_rels/.rels")
	err = TemplateRelationships.Execute(f, nil)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/workbook.xml")
	err = TemplateWorkbook.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/_rels/workbook.xml.rels")
	err = TemplateWorkbookRelationships.Execute(f, ww.sheetNames)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/styles.xml")
	err = TemplateStyles.Execute(f, nil)
	if err != nil {
		return err
	}

	f, err = z.Create("xl/sharedStrings.xml")
	err = TemplateStringLookups.Execute(f, ww.SharedStrings)
	if err != nil {
		return err
	}

	return err
}

// Handles the writing of an XLSX workbook
type WorkbookWriter struct {
	zipWriter     *zip.Writer
	sheetWriter   *SheetWriter
	headerWritten bool
	closed        bool
	sheetNames    []string
	SharedStrings []string
	documentInfo  *DocumentInfo
}

// Creates a new WorkbookWriter
func NewWorkbookWriter(w io.Writer) *WorkbookWriter {
	return &WorkbookWriter{zip.NewWriter(w), nil, false, false, []string{}, nil, nil}
}

// Closes the WorkbookWriter
func (ww *WorkbookWriter) Close() error {
	if ww.closed {
		panic("WorkbookWriter already closed")
	}

	if ww.sheetWriter != nil {
		err := ww.sheetWriter.Close()
		if err != nil {
			return err
		}
	}

	if !ww.headerWritten {
		err := ww.WriteHeader()
		if err != nil {
			return err
		}
	}

	ww.closed = true

	return ww.zipWriter.Close()
}

// NewSheetWriter creates a new SheetWriter in this workbook using the given sheet.
// It returns a SheetWriter to which rows can be written.
// All rows must be written to the SheetWriter before the next call to NewSheetWriter,
// as this will automatically close the previous SheetWriter.
func (ww *WorkbookWriter) NewSheetWriter(s *Sheet) (*SheetWriter, error) {
	if ww.closed {
		panic("Can not write to closed WorkbookWriter")
	}

	if ww.sheetWriter != nil {
		err := ww.sheetWriter.Close()
		if err != nil {
			return nil, err
		}
	}

	f, err := ww.zipWriter.Create("xl/worksheets/" + fmt.Sprintf("sheet%s", strconv.Itoa(len(ww.sheetNames)+1)) + ".xml")
	sw := &SheetWriter{f, err, 0, 0, false, "", 0}

	ww.documentInfo = &s.DocumentInfo

	ww.sheetWriter = sw
	err = sw.WriteHeader(s)

	ww.sheetNames = append(ww.sheetNames, s.Title)

	return sw, err
}

// Handles the writing of a sheet
type SheetWriter struct {
	f               io.Writer
	err             error
	currentIndex    uint64
	maxNCols        uint64
	closed          bool
	mergeCells      string
	mergeCellsCount int
}

// Write the given rows to this SheetWriter
func (sw *SheetWriter) WriteRows(rows []Row) error {
	if sw.closed {
		panic("Can not write to closed SheetWriter")
	}

	var err error

	for i, r := range rows {
		rb := &bytes.Buffer{}

		if sw.maxNCols < uint64(len(r.Cells)) {
			sw.maxNCols = uint64(len(r.Cells))
		}

		for j, c := range r.Cells {

			cellX, cellY := CellIndex(uint64(j), uint64(i)+sw.currentIndex)

			if c.Type == CellTypeDatetime {
				d, err := time.Parse(time.RFC3339, c.Value)
				if err == nil {
					c.Value = OADate(d)
				}
			} else if c.Type == CellTypeInlineString {
				c.Value = html.EscapeString(c.Value)
			}

			var cellString string

			switch c.Type {
			case CellTypeString:
				cellString = `<c r="%s%d" t="s" s="1"><v>%s</v></c>`
			case CellTypeInlineString:
				cellString = `<c r="%s%d" t="inlineStr"><is><t>%s</t></is></c>`
			case CellTypeNumber:
				cellString = `<c r="%s%d" t="n" s="1"><v>%s</v></c>`
			case CellTypeDatetime:
				cellString = `<c r="%s%d" s="2"><v>%s</v></c>`
			}

			if c.Colspan < 0 {
				panic(fmt.Sprintf("%v is not a valid colspan", c.Colspan))
			} else if c.Colspan > 1 {
				mergeCellX, _ := CellIndex(uint64(j)+c.Colspan-1, uint64(i)+sw.currentIndex)
				sw.mergeCells += fmt.Sprintf(`<mergeCell ref="%[1]s%[2]d:%[3]s%[2]d"/>`, cellX, cellY, mergeCellX)
				sw.mergeCellsCount += 1
			}

			io.WriteString(rb, fmt.Sprintf(cellString, cellX, cellY, c.Value))

			if err != nil {
				return err
			}
		}

		rowString := fmt.Sprintf(`<row r="%d">%s</row>`, uint64(i)+sw.currentIndex+1, rb.String())

		_, err = io.WriteString(sw.f, rowString)
		if err != nil {
			return err
		}

	}

	sw.currentIndex += uint64(len(rows))

	return nil
}

// Closes the SheetWriter
func (sw *SheetWriter) Close() error {
	if sw.closed {
		panic("SheetWriter already closed")
	}

	cellEndX, cellEndY := CellIndex(sw.maxNCols-1, sw.currentIndex-1)
	sheetEnd := fmt.Sprintf(`<dimension ref="A1:%s%d"/></sheetData>`, cellEndX, cellEndY)
	if sw.mergeCellsCount > 0 {
		sheetEnd += fmt.Sprintf(`<mergeCells count="%v">`, sw.mergeCellsCount)
		sheetEnd += sw.mergeCells
		sheetEnd += `</mergeCells></worksheet>`
	}
	sheetEnd += `</worksheet>`
	_, err := io.WriteString(sw.f, sheetEnd)

	sw.closed = true

	return err
}

// Writes the header of a sheet
func (sw *SheetWriter) WriteHeader(s *Sheet) error {
	if sw.closed {
		panic("Can not write to closed SheetWriter")
	}

	sheet := struct {
		Cols []Column
	}{
		Cols: s.columns,
	}

	return TemplateSheetStart.Execute(sw.f, sheet)
}
<|endoftext|>


<commit_before>package sms

import (
	"crypto/rand"
	"encoding/base32"
	"encoding/xml"
	"fmt"
	"log"
	"os"
	"strings"

	xco "github.com/mndrix/go-xco"
	"github.com/pkg/errors"
)

// xmppProcess is the piece which interacts with the XMPP network and
// converts those communications into values which the rest of the
// system can understand.
type xmppProcess struct {
	// where to connect to the XMPP server
	host string
	port int

	// credentials for XMPP auth
	name   string
	secret string

	// channel for sending XMPP stanzas to server
	tx chan<- interface{}
}

// runXmppComponent creates a goroutine for sending and receiving XMPP
// stanzas.  it returns a channel for monitoring the goroutine's
// health.  if that channel closes, the XMPP process has died.
func (sc *Component) runXmppComponent(x *xmppProcess) <-chan struct{} {
	opts := xco.Options{
		Name:         x.name,
		SharedSecret: x.secret,
		Address:      fmt.Sprintf("%s:%d", x.host, x.port),
		Logger:       log.New(os.Stderr, "", log.LstdFlags),
	}

	healthCh := make(chan struct{})
	go func() {
		defer func() { close(healthCh) }()

		c, err := xco.NewComponent(opts)
		if err != nil {
			log.Printf("can't create internal XMPP component: %s", err)
			return
		}

		sc.setXmpp(c)
		tx, rx, errx := c.RunAsync()
		x.tx = tx
		for {
			select {
			case stanza := <-rx:
				switch st := stanza.(type) {
				case *xco.Message:
					err = sc.onMessage(st)
				case *xco.Presence:
					log.Printf("Presence: %+v", st)
				case *xco.Iq:
					if st.IsDiscoInfo() {
						var ids []xco.DiscoIdentity
						var features []xco.DiscoFeature
						ids, features, err = x.onDiscoInfo(st)
						if err == nil {
							st, err = st.DiscoInfoReply(ids, features)
							if err == nil {
								go func() { tx <- st }()
							}
						}
					} else {
						log.Printf("Iq: %+v", st)
					}
				case *xml.StartElement:
					log.Printf("Unknown: %+v", st)
				default:
					panic(fmt.Sprintf("Unexpected stanza type: %#v", stanza))
				}
			case err = <-errx:
			}

			if err != nil {
				break
			}
		}

		log.Printf("lost XMPP connection: %s", err)
	}()
	return healthCh
}

func (sc *Component) setXmpp(c *xco.Component) {
	sc.xmppMutex.Lock()
	defer func() { sc.xmppMutex.Unlock() }()

	sc.xmpp = c
}

func (sc *Component) onMessage(m *xco.Message) error {
	log.Printf("Message: %+v", m)
	if m.Body == "" {
		log.Printf("  ignoring message with empty body")
		return nil
	}

	// convert recipient address into a phone number
	toPhone, err := sc.config.AddressToPhone(m.To)
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "converting 'to' address to phone")
	}

	// convert author's address into a phone number
	fromPhone, err := sc.config.AddressToPhone(m.From)
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "converting 'from' address to phone")
	}

	// choose an SMS provider
	provider, err := sc.config.SmsProvider()
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "choosing an SMS provider")
	}

	// send the message
	id, err := provider.SendSms(&Sms{
		From: fromPhone,
		To:   toPhone,
		Body: m.Body,
	})
	if err != nil {
		return errors.Wrap(err, "sending SMS")
	}
	log.Printf("Sent SMS with ID %s", id)

	// prepare to handle delivery receipts
	if m.ReceiptRequest != nil && id != "" {
		receipt := xco.Message{
			Header: xco.Header{
				From: m.Header.To,
				To:   m.Header.From,
				ID:   NewId(),
			},
			ReceiptAck: &xco.ReceiptAck{
				Id: m.Header.ID,
			},
			XMLName: m.XMLName,
		}
		sc.receiptForMutex.Lock()
		defer func() { sc.receiptForMutex.Unlock() }()
		if len(sc.receiptFor) > 10 { // don't get too big
			log.Printf("clearing pending receipts queue")
			sc.receiptFor = make(map[string]*xco.Message)
		}
		sc.receiptFor[id] = &receipt
		log.Printf("Waiting to send receipt: %#v", receipt)
	}

	return nil
}

func (x *xmppProcess) onDiscoInfo(iq *xco.Iq) ([]xco.DiscoIdentity, []xco.DiscoFeature, error) {
	log.Printf("Disco: %+v", iq)
	ids := []xco.DiscoIdentity{
		{
			Category: "gateway",
			Type:     "sms",
			Name:     "SMS over XMPP",
		},
	}
	features := []xco.DiscoFeature{
		{
			Var: "urn:xmpp:receipts",
		},
	}
	return ids, features, nil
}

// xmppSend sends a single XML stanza over the XMPP connection.  It
// serializes concurrent access to avoid collisions on the wire.
func (sc *Component) xmppSend(msg interface{}) error {
	sc.xmppMutex.Lock()
	defer func() { sc.xmppMutex.Unlock() }()

	return sc.xmpp.Send(msg)
}

// NewId generates a random string which is suitable as an XMPP stanza
// ID.  The string contains enough entropy to be universally unique.
func NewId() string {
	// generate 128 random bits (6 more than standard UUID)
	bytes := make([]byte, 16)
	_, err := rand.Read(bytes)
	if err != nil {
		panic(err)
	}

	// convert them to base 32 encoding
	s := base32.StdEncoding.EncodeToString(bytes)
	return strings.ToLower(strings.TrimRight(s, "="))
}
<commit_msg>Prepare to move onMessage into Gateway process<commit_after>package sms

import (
	"crypto/rand"
	"encoding/base32"
	"encoding/xml"
	"fmt"
	"log"
	"os"
	"strings"

	xco "github.com/mndrix/go-xco"
	"github.com/pkg/errors"
)

// xmppProcess is the piece which interacts with the XMPP network and
// converts those communications into values which the rest of the
// system can understand.
type xmppProcess struct {
	// where to connect to the XMPP server
	host string
	port int

	// credentials for XMPP auth
	name   string
	secret string

	// channel for sending XMPP stanzas to server
	tx chan<- interface{}
}

// runXmppComponent creates a goroutine for sending and receiving XMPP
// stanzas.  it returns a channel for monitoring the goroutine's
// health.  if that channel closes, the XMPP process has died.
func (sc *Component) runXmppComponent(x *xmppProcess) <-chan struct{} {
	opts := xco.Options{
		Name:         x.name,
		SharedSecret: x.secret,
		Address:      fmt.Sprintf("%s:%d", x.host, x.port),
		Logger:       log.New(os.Stderr, "", log.LstdFlags),
	}

	healthCh := make(chan struct{})
	go func() {
		defer func() { close(healthCh) }()

		c, err := xco.NewComponent(opts)
		if err != nil {
			log.Printf("can't create internal XMPP component: %s", err)
			return
		}

		sc.setXmpp(c)
		tx, rx, errx := c.RunAsync()
		x.tx = tx
		for {
			select {
			case stanza := <-rx:
				switch st := stanza.(type) {
				case *xco.Message:
					log.Printf("Message: %+v", st)
					if st.Body == "" {
						log.Printf("  ignoring message with empty body")
						break
					}
					err = sc.onMessage(st)
				case *xco.Presence:
					log.Printf("Presence: %+v", st)
				case *xco.Iq:
					if st.IsDiscoInfo() {
						var ids []xco.DiscoIdentity
						var features []xco.DiscoFeature
						ids, features, err = x.onDiscoInfo(st)
						if err == nil {
							st, err = st.DiscoInfoReply(ids, features)
							if err == nil {
								go func() { tx <- st }()
							}
						}
					} else {
						log.Printf("Iq: %+v", st)
					}
				case *xml.StartElement:
					log.Printf("Unknown: %+v", st)
				default:
					panic(fmt.Sprintf("Unexpected stanza type: %#v", stanza))
				}
			case err = <-errx:
			}

			if err != nil {
				break
			}
		}

		log.Printf("lost XMPP connection: %s", err)
	}()
	return healthCh
}

func (sc *Component) setXmpp(c *xco.Component) {
	sc.xmppMutex.Lock()
	defer func() { sc.xmppMutex.Unlock() }()

	sc.xmpp = c
}

func (sc *Component) onMessage(m *xco.Message) error {
	// convert recipient address into a phone number
	toPhone, err := sc.config.AddressToPhone(m.To)
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "converting 'to' address to phone")
	}

	// convert author's address into a phone number
	fromPhone, err := sc.config.AddressToPhone(m.From)
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "converting 'from' address to phone")
	}

	// choose an SMS provider
	provider, err := sc.config.SmsProvider()
	switch err {
	case nil:
		// all is well. we'll continue below
	case ErrIgnoreMessage:
		return nil
	default:
		return errors.Wrap(err, "choosing an SMS provider")
	}

	// send the message
	id, err := provider.SendSms(&Sms{
		From: fromPhone,
		To:   toPhone,
		Body: m.Body,
	})
	if err != nil {
		return errors.Wrap(err, "sending SMS")
	}
	log.Printf("Sent SMS with ID %s", id)

	// prepare to handle delivery receipts
	if m.ReceiptRequest != nil && id != "" {
		receipt := xco.Message{
			Header: xco.Header{
				From: m.Header.To,
				To:   m.Header.From,
				ID:   NewId(),
			},
			ReceiptAck: &xco.ReceiptAck{
				Id: m.Header.ID,
			},
			XMLName: m.XMLName,
		}
		sc.receiptForMutex.Lock()
		defer func() { sc.receiptForMutex.Unlock() }()
		if len(sc.receiptFor) > 10 { // don't get too big
			log.Printf("clearing pending receipts queue")
			sc.receiptFor = make(map[string]*xco.Message)
		}
		sc.receiptFor[id] = &receipt
		log.Printf("Waiting to send receipt: %#v", receipt)
	}

	return nil
}

func (x *xmppProcess) onDiscoInfo(iq *xco.Iq) ([]xco.DiscoIdentity, []xco.DiscoFeature, error) {
	log.Printf("Disco: %+v", iq)
	ids := []xco.DiscoIdentity{
		{
			Category: "gateway",
			Type:     "sms",
			Name:     "SMS over XMPP",
		},
	}
	features := []xco.DiscoFeature{
		{
			Var: "urn:xmpp:receipts",
		},
	}
	return ids, features, nil
}

// xmppSend sends a single XML stanza over the XMPP connection.  It
// serializes concurrent access to avoid collisions on the wire.
func (sc *Component) xmppSend(msg interface{}) error {
	sc.xmppMutex.Lock()
	defer func() { sc.xmppMutex.Unlock() }()

	return sc.xmpp.Send(msg)
}

// NewId generates a random string which is suitable as an XMPP stanza
// ID.  The string contains enough entropy to be universally unique.
func NewId() string {
	// generate 128 random bits (6 more than standard UUID)
	bytes := make([]byte, 16)
	_, err := rand.Read(bytes)
	if err != nil {
		panic(err)
	}

	// convert them to base 32 encoding
	s := base32.StdEncoding.EncodeToString(bytes)
	return strings.ToLower(strings.TrimRight(s, "="))
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
	"sync"
)

var L = struct {
	I *log.Logger
	E *log.Logger
}{
	I: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
	E: log.New(os.Stderr, "[ERROR] ", log.LstdFlags),
}

func timelines(root string) ([]string, error) {
	dir, err := os.Open(root)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	fi, err := dir.Stat()
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, fmt.Errorf("%q is not a directory", root)
	}

	c, err := dir.Readdir(-1)
	if err != nil {
		return nil, err
	}
	sort.Sort(FileInfoByName(c))

	list := make([]string, 0, len(c))
	for _, entry := range c {
		if !entry.Mode().IsRegular() {
			continue
		}

		list = append(list, entry.Name())
	}

	return list, nil
}

func update(ctx context.Context, cpath string) error {
	file, err := os.Open(cpath)
	if err != nil {
		return err
	}
	defer file.Close()

	cfg, err := LoadConfig(file)
	if err != nil {
		return err
	}

	return cfg.Update(ctx)
}

func main() {
	var flags struct {
		configRoot string
	}
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %v [options] <timeline>\n", os.Args[0])
		fmt.Fprintln(os.Stderr)

		fmt.Fprintln(os.Stderr, "Options:")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr)

		fmt.Fprintln(os.Stderr, "Pseudo timelines:")
		fmt.Fprintln(os.Stderr, "  list-timelines")
		fmt.Fprintln(os.Stderr, "      List all timeline configs.")
		fmt.Fprintln(os.Stderr, "  update-all")
		fmt.Fprintln(os.Stderr, "      Update all timelines.")
	}
	flag.StringVar(&flags.configRoot, "confdir", "/etc/yabs/", "The directory that the timeline configs are in.")
	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	ctx := SignalContext(context.Background(), os.Interrupt)

	switch timeline := flag.Arg(0); timeline {
	case "list-timelines":
		tl, err := timelines(flags.configRoot)
		if err != nil {
			L.E.Printf("Failed to get list of timelines: %v", err)
			os.Exit(1)
		}

		for _, tl := range tl {
			fmt.Println(tl)
		}

	case "update-all":
		tl, err := timelines(flags.configRoot)
		if err != nil {
			L.E.Printf("Failed to get list of timelines: %v", err)
			os.Exit(1)
		}

		var wg sync.WaitGroup
		for _, tl := range tl {
			wg.Add(1)
			go func(tl string) {
				defer wg.Done()

				err := update(ctx, filepath.Join(flags.configRoot, tl))
				if err != nil {
					L.E.Printf("Failed to update %q: %v", tl, err)
					return
				}

				L.I.Printf("Updated %q.", tl)
			}(tl)
		}
		wg.Wait()

	default:
		err := update(ctx, filepath.Join(flags.configRoot, timeline))
		if err != nil {
			L.E.Printf("Failed to update %q: %v", timeline, err)
			return
		}

		L.I.Printf("Updated %q.", timeline)
	}
}
<commit_msg>Disallow running as non-root.<commit_after>package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"sync"
)

var L = struct {
	I *log.Logger
	E *log.Logger
}{
	I: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
	E: log.New(os.Stderr, "[ERROR] ", log.LstdFlags),
}

func timelines(root string) ([]string, error) {
	dir, err := os.Open(root)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	fi, err := dir.Stat()
	if err != nil {
		return nil, err
	}
	if !fi.IsDir() {
		return nil, fmt.Errorf("%q is not a directory", root)
	}

	c, err := dir.Readdir(-1)
	if err != nil {
		return nil, err
	}
	sort.Sort(FileInfoByName(c))

	list := make([]string, 0, len(c))
	for _, entry := range c {
		if !entry.Mode().IsRegular() {
			continue
		}

		list = append(list, entry.Name())
	}

	return list, nil
}

func update(ctx context.Context, cpath string) error {
	file, err := os.Open(cpath)
	if err != nil {
		return err
	}
	defer file.Close()

	cfg, err := LoadConfig(file)
	if err != nil {
		return err
	}

	return cfg.Update(ctx)
}

func main() {
	u, err := user.Current()
	if err != nil {
		L.E.Fatalf("Failed to get current user: %v", err)
	}
	if u.Uid != "0" {
		L.E.Fatalf("%v must be run as root.", os.Args[0])
	}

	var flags struct {
		configRoot string
	}
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %v [options] <timeline>\n", os.Args[0])
		fmt.Fprintln(os.Stderr)

		fmt.Fprintln(os.Stderr, "Options:")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr)

		fmt.Fprintln(os.Stderr, "Pseudo timelines:")
		fmt.Fprintln(os.Stderr, "  list-timelines")
		fmt.Fprintln(os.Stderr, "      List all timeline configs.")
		fmt.Fprintln(os.Stderr, "  update-all")
		fmt.Fprintln(os.Stderr, "      Update all timelines.")
	}
	flag.StringVar(&flags.configRoot, "confdir", "/etc/yabs/", "The directory that the timeline configs are in.")
	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(2)
	}

	ctx := SignalContext(context.Background(), os.Interrupt)

	switch timeline := flag.Arg(0); timeline {
	case "list-timelines":
		tl, err := timelines(flags.configRoot)
		if err != nil {
			L.E.Fatalf("Failed to get list of timelines: %v", err)
		}

		for _, tl := range tl {
			fmt.Println(tl)
		}

	case "update-all":
		tl, err := timelines(flags.configRoot)
		if err != nil {
			L.E.Fatalf("Failed to get list of timelines: %v", err)
		}

		var wg sync.WaitGroup
		for _, tl := range tl {
			wg.Add(1)
			go func(tl string) {
				defer wg.Done()

				err := update(ctx, filepath.Join(flags.configRoot, tl))
				if err != nil {
					L.E.Printf("Failed to update %q: %v", tl, err)
					return
				}

				L.I.Printf("Updated %q.", tl)
			}(tl)
		}
		wg.Wait()

	default:
		err := update(ctx, filepath.Join(flags.configRoot, timeline))
		if err != nil {
			L.E.Fatalf("Failed to update %q: %v", timeline, err)
			return
		}

		L.I.Printf("Updated %q.", timeline)
	}
}
<|endoftext|>


<commit_before>package rest

import (
	"connectordb/streamdb"
	"connectordb/streamdb/operator"
	"time"

	log "github.com/Sirupsen/logrus"

	"net/http"
	"strings"

	"github.com/gorilla/mux"
)

var (
	//UnsuccessfulLoginWait is the amount of time to wait between each unsuccessful login attempt
	UnsuccessfulLoginWait = 300 * time.Millisecond
)

func getLogger(request *http.Request) *log.Entry {
	//Since an important use case is behind nginx, the following rule is followed:
	//localhost address is not logged if real-ip header exists (since it is from localhost)
	//if real-ip header exists, faddr=address (forwardedAddress) is logged
	//In essence, if behind nginx, there is no need for the addr=blah

	fields := log.Fields{"addr": request.RemoteAddr, "uri": request.URL.String()}
	if realIP := request.Header.Get("X-Real-IP"); realIP != "" {
		fields["faddr"] = realIP
		if strings.HasPrefix(request.RemoteAddr, "127.0.0.1") || strings.HasPrefix(request.RemoteAddr, "::1") {
			delete(fields, "addr")
		}
	}

	return log.WithFields(fields)
}

//Writes the access control headers for the site
func writeAccessControlHeaders(writer http.ResponseWriter) {
	writer.Header().Set("Access-Control-Allow-Origin", "*")
	writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, UPDATE")
	writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
}

//APIHandler is a function that handles some part of the REST API given a specific operator on the database.
type APIHandler func(o operator.Operator, writer http.ResponseWriter, request *http.Request, logger *log.Entry) error

func authenticator(apifunc APIHandler, db *streamdb.Database) http.HandlerFunc {
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		//Set up the logger for this connection
		logger := getLogger(request)

		writeAccessControlHeaders(writer)

		//Check authentication
		authUser, authPass, ok := request.BasicAuth()

		//If there is no basic auth header, return unauthorized
		if !ok {
			writer.Header().Set("WWW-Authenticate", "Basic")
			writer.WriteHeader(http.StatusUnauthorized)
			logger.WithField("op", "AUTH").Warningln("Login attempt w/o auth")
			return
		}

		//Handle a panic without crashing the whole rest interface
		defer func() {
			if r := recover(); r != nil {
				logger.WithFields(log.Fields{"dev": authUser, "op": "PANIC"}).Errorln(r)
			}
		}()

		o, err := db.LoginOperator(authUser, authPass)

		if err != nil {
			logger.WithFields(log.Fields{"dev": authUser, "op": "AUTH"}).Warningln(err.Error())

			//So there was an unsuccessful attempt at login, huh?
			time.Sleep(UnsuccessfulLoginWait)

			writer.Header().Set("WWW-Authenticate", "Basic")
			writer.WriteHeader(http.StatusUnauthorized)
			writer.Write([]byte(err.Error()))

			return
		}

		//If we got here, o is a valid operator
		err = apifunc(o, writer, request, logger.WithField("dev", o.Name()))
		if err != nil {
			writer.Write([]byte(err.Error()))
		}
	})
}

//When a path is not found, return a 404 with path not recognized message
func notfoundHandler(writer http.ResponseWriter, request *http.Request) {
	getLogger(request).WithField("method", request.Method).Debug("404")
	writer.WriteHeader(http.StatusNotFound)
	writer.Write([]byte("This path is not recognized"))

}

//on OPTIONS to allow cross-site XMLHTTPRequest, allow access control origin
func optionsHandler(writer http.ResponseWriter, request *http.Request) {
	getLogger(request).WithField("method", request.Method).Debug()
	writeAccessControlHeaders(writer)
	writer.WriteHeader(http.StatusOK)
}

//Router returns a fully formed Gorilla router given an optional prefix
func Router(db *streamdb.Database, prefix *mux.Router) *mux.Router {
	if prefix == nil {
		prefix = mux.NewRouter()
	}

	//Allow for the application to match /path and /path/ to the same place.
	prefix.StrictSlash(true)

	prefix.NotFoundHandler = http.HandlerFunc(notfoundHandler)

	prefix.Methods("OPTIONS").Handler(http.HandlerFunc(optionsHandler))

	// Special items
	prefix.HandleFunc("/", authenticator(RunWebsocket, db)).Headers("Upgrade", "websocket").Methods("GET")

	//The 'd' prefix corresponds to data
	d := prefix.PathPrefix("/d").Subrouter()

	d.HandleFunc("/", authenticator(ListUsers, db)).Queries("q", "ls")
	d.HandleFunc("/", authenticator(GetThis, db)).Queries("q", "this")

	//User CRUD
	userPath := "/{user}"
	d.HandleFunc(userPath, authenticator(ListDevices, db)).Methods("GET").Queries("q", "ls")
	d.HandleFunc(userPath, authenticator(ReadUser, db)).Methods("GET")
	d.HandleFunc(userPath, authenticator(CreateUser, db)).Methods("POST")
	d.HandleFunc(userPath, authenticator(UpdateUser, db)).Methods("PUT")
	d.HandleFunc(userPath, authenticator(DeleteUser, db)).Methods("DELETE")

	//Device CRUD
	devicePath := userPath + "/{device}"
	d.HandleFunc(devicePath, authenticator(ListStreams, db)).Methods("GET").Queries("q", "ls")
	d.HandleFunc(devicePath, authenticator(ReadDevice, db)).Methods("GET")
	d.HandleFunc(devicePath, authenticator(CreateDevice, db)).Methods("POST")
	d.HandleFunc(devicePath, authenticator(UpdateDevice, db)).Methods("PUT")
	d.HandleFunc(devicePath, authenticator(DeleteDevice, db)).Methods("DELETE")

	//Stream CRUD
	streamPath := devicePath + "/{stream}"
	d.HandleFunc(streamPath, authenticator(ReadStream, db)).Methods("GET")
	d.HandleFunc(streamPath, authenticator(CreateStream, db)).Methods("POST")
	d.HandleFunc(streamPath, authenticator(UpdateStream, db)).Methods("PUT")
	d.HandleFunc(streamPath, authenticator(DeleteStream, db)).Methods("DELETE")

	//Stream IO
	d.HandleFunc(streamPath, authenticator(WriteStream, db)).Methods("UPDATE")

	d.HandleFunc(streamPath+"/data", authenticator(GetStreamRangeI, db)).Methods("GET").Queries("i1", "{i1}")
	d.HandleFunc(streamPath+"/data", authenticator(GetStreamRangeT, db)).Methods("GET").Queries("t1", "{t1}")

	d.HandleFunc(streamPath+"/length", authenticator(GetStreamLength, db)).Methods("GET")
	d.HandleFunc(streamPath+"/time2index", authenticator(StreamTime2Index, db)).Methods("GET")

	return prefix
}
<commit_msg>Tried "fixing" a problem I introduced that tests fine here but not on Travis.<commit_after>package rest

import (
	"connectordb/streamdb"
	"connectordb/streamdb/operator"
	"time"

	log "github.com/Sirupsen/logrus"

	"net/http"
	"strings"

	"github.com/gorilla/mux"
)

var (
	//UnsuccessfulLoginWait is the amount of time to wait between each unsuccessful login attempt
	UnsuccessfulLoginWait = 300 * time.Millisecond
)

func getLogger(request *http.Request) *log.Entry {
	//Since an important use case is behind nginx, the following rule is followed:
	//localhost address is not logged if real-ip header exists (since it is from localhost)
	//if real-ip header exists, faddr=address (forwardedAddress) is logged
	//In essence, if behind nginx, there is no need for the addr=blah

	fields := log.Fields{"addr": request.RemoteAddr, "uri": request.URL.String()}
	if realIP := request.Header.Get("X-Real-IP"); realIP != "" {
		fields["faddr"] = realIP
		if strings.HasPrefix(request.RemoteAddr, "127.0.0.1") || strings.HasPrefix(request.RemoteAddr, "::1") {
			delete(fields, "addr")
		}
	}

	return log.WithFields(fields)
}

//Writes the access control headers for the site
func writeAccessControlHeaders(writer http.ResponseWriter) {
	writer.Header().Set("Access-Control-Allow-Origin", "*")
	writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, UPDATE")
	writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
}

//APIHandler is a function that handles some part of the REST API given a specific operator on the database.
type APIHandler func(o operator.Operator, writer http.ResponseWriter, request *http.Request, logger *log.Entry) error

func authenticator(apifunc APIHandler, db *streamdb.Database) http.HandlerFunc {
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		//Set up the logger for this connection
		logger := getLogger(request)

		writeAccessControlHeaders(writer)

		//Check authentication
		authUser, authPass, ok := request.BasicAuth()

		//If there is no basic auth header, return unauthorized
		if !ok {
			writer.Header().Set("WWW-Authenticate", "Basic")
			writer.WriteHeader(http.StatusUnauthorized)
			logger.WithField("op", "AUTH").Warningln("Login attempt w/o auth")
			return
		}

		//Handle a panic without crashing the whole rest interface
		defer func() {
			if r := recover(); r != nil {
				logger.WithFields(log.Fields{"dev": authUser, "op": "PANIC"}).Errorln(r)
			}
		}()

		o, err := db.LoginOperator(authUser, authPass)

		if err != nil {
			logger.WithFields(log.Fields{"dev": authUser, "op": "AUTH"}).Warningln(err.Error())

			//So there was an unsuccessful attempt at login, huh?
			time.Sleep(UnsuccessfulLoginWait)

			writer.Header().Set("WWW-Authenticate", "Basic")
			writer.WriteHeader(http.StatusUnauthorized)
			writer.Write([]byte(err.Error()))

			return
		}

		//If we got here, o is a valid operator
		err = apifunc(o, writer, request, logger.WithField("dev", o.Name()))
		if err != nil {
			writer.Write([]byte(err.Error()))
		}
	})
}

//When a path is not found, return a 404 with path not recognized message
func notfoundHandler(writer http.ResponseWriter, request *http.Request) {
	getLogger(request).WithField("method", request.Method).Debug("404")
	writer.WriteHeader(http.StatusNotFound)
	writer.Write([]byte("This path is not recognized"))

}

//on OPTIONS to allow cross-site XMLHTTPRequest, allow access control origin
func optionsHandler(writer http.ResponseWriter, request *http.Request) {
	getLogger(request).WithField("method", request.Method).Debug()
	writeAccessControlHeaders(writer)
	writer.WriteHeader(http.StatusOK)
}

//Router returns a fully formed Gorilla router given an optional prefix
func Router(db *streamdb.Database, prefix *mux.Router) *mux.Router {
	if prefix == nil {
		prefix = mux.NewRouter()
	}

	//Allow for the application to match /path and /path/ to the same place.
	prefix.StrictSlash(true)

	prefix.NotFoundHandler = http.HandlerFunc(notfoundHandler)

	prefix.Methods("OPTIONS").Handler(http.HandlerFunc(optionsHandler))

	// Special items
	prefix.HandleFunc("/", authenticator(RunWebsocket, db)).Headers("Upgrade", "websocket").Methods("GET")

	//The 'd' prefix corresponds to data
	d := prefix.PathPrefix("/d").Subrouter()

	d.HandleFunc("/", authenticator(ListUsers, db)).Queries("q", "ls")
	d.HandleFunc("/", authenticator(GetThis, db)).Queries("q", "this")

	//User CRUD
	d.HandleFunc("/{user}", authenticator(ListDevices, db)).Methods("GET").Queries("q", "ls")
	d.HandleFunc("/{user}", authenticator(ReadUser, db)).Methods("GET")
	d.HandleFunc("/{user}", authenticator(CreateUser, db)).Methods("POST")
	d.HandleFunc("/{user}", authenticator(UpdateUser, db)).Methods("PUT")
	d.HandleFunc("/{user}", authenticator(DeleteUser, db)).Methods("DELETE")

	//Device CRUD
	d.HandleFunc("/{user}/{device}", authenticator(ListStreams, db)).Methods("GET").Queries("q", "ls")
	d.HandleFunc("/{user}/{device}", authenticator(ReadDevice, db)).Methods("GET")
	d.HandleFunc("/{user}/{device}", authenticator(CreateDevice, db)).Methods("POST")
	d.HandleFunc("/{user}/{device}", authenticator(UpdateDevice, db)).Methods("PUT")
	d.HandleFunc("/{user}/{device}", authenticator(DeleteDevice, db)).Methods("DELETE")

	//Stream CRUD
	d.HandleFunc("/{user}/{device}/{stream}", authenticator(ReadStream, db)).Methods("GET")
	d.HandleFunc("/{user}/{device}/{stream}", authenticator(CreateStream, db)).Methods("POST")
	d.HandleFunc("/{user}/{device}/{stream}", authenticator(UpdateStream, db)).Methods("PUT")
	d.HandleFunc("/{user}/{device}/{stream}", authenticator(DeleteStream, db)).Methods("DELETE")

	//Stream IO
	d.HandleFunc("/{user}/{device}/{stream}", authenticator(WriteStream, db)).Methods("UPDATE")

	d.HandleFunc("/{user}/{device}/{stream}/data", authenticator(GetStreamRangeI, db)).Methods("GET").Queries("i1", "{i1}")
	d.HandleFunc("/{user}/{device}/{stream}/data", authenticator(GetStreamRangeT, db)).Methods("GET").Queries("t1", "{t1}")

	d.HandleFunc("/{user}/{device}/{stream}/length", authenticator(GetStreamLength, db)).Methods("GET")
	d.HandleFunc("/{user}/{device}/{stream}/time2index", authenticator(StreamTime2Index, db)).Methods("GET")

	return prefix
}
<|endoftext|>


<commit_before>package notifications

import "code.cloudfoundry.org/lager"

//go:generate counterfeiter . Router

type Router interface {
	Deliver(logger lager.Logger, batch []Notification) error
}

type router struct {
	notifier    Notifier
	addressBook AddressBook
	whitelist   Whitelist
}

func NewRouter(notifier Notifier, addressBook AddressBook, whitelist Whitelist) Router {
	return &router{
		notifier:    notifier,
		addressBook: addressBook,
		whitelist:   whitelist,
	}
}

func (r *router) Deliver(logger lager.Logger, batch []Notification) error {
	logger = logger.Session("deliver")

	envelopes := r.filterAndGroupByDestination(logger, batch)

	for _, envelope := range envelopes {
		_ = r.notifier.Send(logger, *envelope)
	}

	return nil
}

func (r *router) filterAndGroupByDestination(logger lager.Logger, batch []Notification) []*Envelope {
	bag := mailbag{}

	for _, notification := range batch {
		if r.whitelist.ShouldSkipNotification(notification.Private, notification.Repository) {
			continue
		}

		addresses := r.addressBook.AddressForRepo(logger, notification.Owner, notification.Repository)

		for _, address := range addresses {
			bag.envelopeToAddress(notification, address)
		}
	}

	return bag.Envelopes
}

type mailbag struct {
	Envelopes []*Envelope
}

func (m *mailbag) envelopeToAddress(notification Notification, address Address) {
	for _, envelope := range m.Envelopes {
		if envelope.Address == address {
			envelope.Contents = append(envelope.Contents, notification)
			return
		}
	}

	envelope := &Envelope{
		Address:  address,
		Contents: []Notification{notification},
	}

	m.Envelopes = append(m.Envelopes, envelope)
}
<commit_msg>Add more logging to the router<commit_after>package notifications

import "code.cloudfoundry.org/lager"

//go:generate counterfeiter . Router

type Router interface {
	Deliver(logger lager.Logger, batch []Notification) error
}

type router struct {
	notifier    Notifier
	addressBook AddressBook
	whitelist   Whitelist
}

func NewRouter(notifier Notifier, addressBook AddressBook, whitelist Whitelist) Router {
	return &router{
		notifier:    notifier,
		addressBook: addressBook,
		whitelist:   whitelist,
	}
}

func (r *router) Deliver(logger lager.Logger, batch []Notification) error {
	logger = logger.Session("deliver")

	envelopes := r.filterAndGroupByDestination(logger, batch)

	logger.Debug("sending", lager.Data{
		"envelope-count":     len(envelopes),
		"notification-count": len(batch),
	})

	for _, envelope := range envelopes {
		err := r.notifier.Send(logger, *envelope)
		if err != nil {
			return err
		}
	}

	logger.Debug("sent")

	return nil
}

func (r *router) filterAndGroupByDestination(logger lager.Logger, batch []Notification) []*Envelope {
	bag := mailbag{}

	for _, notification := range batch {
		if r.whitelist.ShouldSkipNotification(notification.Private, notification.Repository) {
			continue
		}

		addresses := r.addressBook.AddressForRepo(logger, notification.Owner, notification.Repository)

		for _, address := range addresses {
			bag.envelopeToAddress(notification, address)
		}
	}

	return bag.Envelopes
}

type mailbag struct {
	Envelopes []*Envelope
}

func (m *mailbag) envelopeToAddress(notification Notification, address Address) {
	for _, envelope := range m.Envelopes {
		if envelope.Address == address {
			envelope.Contents = append(envelope.Contents, notification)
			return
		}
	}

	envelope := &Envelope{
		Address:  address,
		Contents: []Notification{notification},
	}

	m.Envelopes = append(m.Envelopes, envelope)
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
)

var result int

func benchmarkHelper(b *testing.B, fn func([]int) int, args []int) {
	var r int
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		r = fn(args)
	}
	result = r
}

var benchCases = []struct {
	name string
	fn   func([]int) int
	args []int
}{
	{"one(nil)", one, nil},
	{"two(nil)", two, nil},
	// not nil
	{"one(1,2,3)", one, []int{1, 2, 3}},
	{"two(1,2,3)", two, []int{1, 2, 3}},
}

func BenchmarkAll(b *testing.B) {
	for _, bc := range benchCases {
		b.Run(bc.name, func(b *testing.B) {
			benchmarkHelper(b, bc.fn, bc.args)
		})
	}
}
<commit_msg>nilrange: add three benchmarks<commit_after>package main

import (
	"testing"
)

var result int

func benchmarkHelper(b *testing.B, fn func([]int) int, args []int) {
	var r int
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		r = fn(args)
	}
	result = r
}

var benchCases = []struct {
	name string
	fn   func([]int) int
	args []int
}{
	{"one(nil)", one, nil},
	{"two(nil)", two, nil},
	{"three(nil)", three, nil},
	// not nil
	{"one(1,2,3)", one, []int{1, 2, 3}},
	{"two(1,2,3)", two, []int{1, 2, 3}},
	{"three(1,2,3)", three, []int{1, 2, 3}},
}

func BenchmarkAll(b *testing.B) {
	for _, bc := range benchCases {
		b.Run(bc.name, func(b *testing.B) {
			benchmarkHelper(b, bc.fn, bc.args)
		})
	}
}
<|endoftext|>


<commit_before>package quic

import (
	"reflect"
	"testing"
)

func TestStreamFrameFrame(t *testing.T) {
	// fin: true, streamID: 1, offset: 1, dataLength: 1
	//data := []byte{0xe4, 0x01, 0x00, 0x01, 0x00, 0x05}
	data := [][]byte{
		// fin: true, streamID: 1, offset: 1, dataLength: 1
		[]byte{0xe4, 0x01, 0x00, 0x01, 0x00, 0x05},
		// fin: false, streamID: 256, offset 0, dataLength: 1
		[]byte{0xa1, 0x01, 0x00, 0x00, 0x05},
	}

	testD := []byte("aiueo")
	fp := NewFramePacket(0, 0)
	actualFrames := []*StreamFrame{
		NewStreamFrame(true, 1, 1, testD),
		NewStreamFrame(false, 256, 0, testD),
	}
	for i, d := range data {
		d := append(d, testD...)
		frame, _ := FrameParserMap[FrameType(d[0]&StreamFrameType)](fp, d)
		actualFrame := actualFrames[i]
		actualFrame.FramePacket = fp

		wire, _ := actualFrame.GetWire()
		if len(wire) != len(d) {
			t.Errorf("got %v\nwant %v", len(wire), len(d))
		}

		if !reflect.DeepEqual(actualFrame, frame) {
			t.Errorf("got %v\nwant %v", actualFrame, frame)
		}

		actualWire, _ := frame.GetWire()
		if !reflect.DeepEqual(actualWire, d) {
			t.Errorf("got %v\nwant %v", actualWire, d)
		}

	}
}

func TestPaddingFrame(t *testing.T) {
	data := []byte{0x00, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)
	fp.DataSize = 1945
	fp.RestSize = 5

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewPaddingFrame()
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestRstStreamFrame(t *testing.T) {
	// streamID:1, offset:1, errorcode: QUIC_NO_ERROR
	data := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewRstStreamFrame(1, 1, QUIC_NO_ERROR)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestPingFrame(t *testing.T) {
	data := []byte{0x07}
	fp := NewFramePacket(0, 0)

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewPingFrame()
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestConnectionCloseFrame(t *testing.T) {
	// errorcode: QUIC_NO_ERROR, reason length: 14, reason: "This is reason",
	data := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewConnectionCloseFrame(QUIC_NO_ERROR, reason)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestGoAwayFrame(t *testing.T) {
	// errorcode: QUIC_NO_ERROR, last streamID: 1, reason length: 14, reason: "This is reason",
	data := []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewGoAwayFrame(QUIC_NO_ERROR, 1, reason)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestWindowUpdateFrame(t *testing.T) {
	// streamID: 1, offset 1
	data := []byte{0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewWindowUpdateFrame(1, 1)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestBlockedFrame(t *testing.T) {
	// streamID: 1
	data := []byte{0x05, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewBlockedFrame(1)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestStopWaitingFrame(t *testing.T) {
	data := [][]byte{
		// Sent Entropy: 1, least unacked delta: 1
		[]byte{0x06, 0x01},
		// Sent Entropy: 0, least unacked delta: 257
		[]byte{0x06, 0x01, 0x01},
	}
	fp := NewFramePacket(0, 0)
	actualFrames := []*StopWaitingFrame{
		NewStopWaitingFrame(1),
		NewStopWaitingFrame(257),
	}

	for i, d := range data {
		if i == 1 {
			fp.PacketHeader.PublicFlags |= PACKET_NUMBER_LENGTH_2
		}
		frame, _ := FrameParserMap[FrameType(d[0])](fp, d)
		actualFrame := actualFrames[i]
		actualFrame.FramePacket = fp

		wire, _ := actualFrame.GetWire()
		if len(wire) != len(d) {
			t.Errorf("got %v\nwant %v", len(wire), len(d))
		}

		if !reflect.DeepEqual(actualFrame, frame) {
			t.Errorf("got %v\nwant %v", actualFrame, frame)
		}

		actualWire, _ := frame.GetWire()
		if !reflect.DeepEqual(actualWire, d) {
			t.Errorf("got %v\nwant %v", actualWire, d)
		}
	}
}
<commit_msg>add ack test<commit_after>package quic

import (
	"reflect"
	"testing"
)

func TestAckFrame(t *testing.T) {
	data := [][]byte{
		// 0b0100 0000, LAcked:0, LAckedDelta:0, NumTimeStamp:0,
		[]byte{0x40, 0x00, 0x00, 0x00, 0x00},
		// 0b0100 0000, LAcked:0, LAckedDelta:0, NumTimeStamp:1,
		//[]byte{0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
	}
	fp := NewFramePacket(0, 0)
	actualFrames := []*AckFrame{
		NewAckFrame(0, 0, 0, nil, nil, nil),
		/*
			NewAckFrame(0, 0, 0, nil, &FirstTimestamp{
				DeltaLargestAcked:     0,
				TimeSinceLargestAcked: 0,
			}, nil),
		*/
	}

	for i, d := range data {
		frame, _ := FrameParserMap[FrameType(d[0]&AckFrameType)](fp, d)
		actualFrame := actualFrames[i]
		actualFrame.FramePacket = fp

		wire, _ := actualFrame.GetWire()
		if len(wire) != len(d) {
			t.Errorf("got %v\nwant %v", len(wire), len(d))
		}
		/*
			if !reflect.DeepEqual(actualFrame, frame) {
				t.Errorf("got %v\nwant %v", actualFrame, frame)
			}
		*/
		actualWire, _ := frame.GetWire()
		if !reflect.DeepEqual(actualWire, d) {
			t.Errorf("got %v\nwant %v", actualWire, d)
		}
	}
}

func TestStreamFrame(t *testing.T) {
	// fin: true, streamID: 1, offset: 1, dataLength: 1
	//data := []byte{0xe4, 0x01, 0x00, 0x01, 0x00, 0x05}
	data := [][]byte{
		// fin: true, streamID: 1, offset: 1, dataLength: 1
		[]byte{0xe4, 0x01, 0x00, 0x01, 0x00, 0x05},
		// fin: false, streamID: 256, offset 0, dataLength: 1
		[]byte{0xa1, 0x01, 0x00, 0x00, 0x05},
	}

	testD := []byte("aiueo")
	fp := NewFramePacket(0, 0)
	actualFrames := []*StreamFrame{
		NewStreamFrame(true, 1, 1, testD),
		NewStreamFrame(false, 256, 0, testD),
	}
	for i, d := range data {
		d := append(d, testD...)
		frame, _ := FrameParserMap[FrameType(d[0]&StreamFrameType)](fp, d)
		actualFrame := actualFrames[i]
		actualFrame.FramePacket = fp

		wire, _ := actualFrame.GetWire()
		if len(wire) != len(d) {
			t.Errorf("got %v\nwant %v", len(wire), len(d))
		}

		if !reflect.DeepEqual(actualFrame, frame) {
			t.Errorf("got %v\nwant %v", actualFrame, frame)
		}

		actualWire, _ := frame.GetWire()
		if !reflect.DeepEqual(actualWire, d) {
			t.Errorf("got %v\nwant %v", actualWire, d)
		}

	}
}

func TestPaddingFrame(t *testing.T) {
	data := []byte{0x00, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)
	fp.DataSize = 1945
	fp.RestSize = 5

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewPaddingFrame()
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestRstStreamFrame(t *testing.T) {
	// streamID:1, offset:1, errorcode: QUIC_NO_ERROR
	data := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewRstStreamFrame(1, 1, QUIC_NO_ERROR)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestPingFrame(t *testing.T) {
	data := []byte{0x07}
	fp := NewFramePacket(0, 0)

	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewPingFrame()
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestConnectionCloseFrame(t *testing.T) {
	// errorcode: QUIC_NO_ERROR, reason length: 14, reason: "This is reason",
	data := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewConnectionCloseFrame(QUIC_NO_ERROR, reason)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestGoAwayFrame(t *testing.T) {
	// errorcode: QUIC_NO_ERROR, last streamID: 1, reason length: 14, reason: "This is reason",
	data := []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewGoAwayFrame(QUIC_NO_ERROR, 1, reason)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestWindowUpdateFrame(t *testing.T) {
	// streamID: 1, offset 1
	data := []byte{0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewWindowUpdateFrame(1, 1)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestBlockedFrame(t *testing.T) {
	// streamID: 1
	data := []byte{0x05, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame, _ := FrameParserMap[FrameType(data[0])](fp, data)
	actualFrame := NewBlockedFrame(1)
	actualFrame.FramePacket = fp

	wire, _ := actualFrame.GetWire()
	if len(wire) != len(data) {
		t.Errorf("got %v\nwant %v", len(wire), len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestStopWaitingFrame(t *testing.T) {
	data := [][]byte{
		// Sent Entropy: 1, least unacked delta: 1
		[]byte{0x06, 0x01},
		// Sent Entropy: 0, least unacked delta: 257
		[]byte{0x06, 0x01, 0x01},
	}
	fp := NewFramePacket(0, 0)
	actualFrames := []*StopWaitingFrame{
		NewStopWaitingFrame(1),
		NewStopWaitingFrame(257),
	}

	for i, d := range data {
		if i == 1 {
			fp.PacketHeader.PublicFlags |= PACKET_NUMBER_LENGTH_2
		}
		frame, _ := FrameParserMap[FrameType(d[0])](fp, d)
		actualFrame := actualFrames[i]
		actualFrame.FramePacket = fp

		wire, _ := actualFrame.GetWire()
		if len(wire) != len(d) {
			t.Errorf("got %v\nwant %v", len(wire), len(d))
		}

		if !reflect.DeepEqual(actualFrame, frame) {
			t.Errorf("got %v\nwant %v", actualFrame, frame)
		}

		actualWire, _ := frame.GetWire()
		if !reflect.DeepEqual(actualWire, d) {
			t.Errorf("got %v\nwant %v", actualWire, d)
		}
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamUserPolicy() *schema.Resource {
	return &schema.Resource{
		// PutUserPolicy API is idempotent, so these can be the same.
		Create: resourceAwsIamUserPolicyPut,
		Read:   resourceAwsIamUserPolicyRead,
		Update: resourceAwsIamUserPolicyPut,
		Delete: resourceAwsIamUserPolicyDelete,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"policy": {
				Type:             schema.TypeString,
				Required:         true,
				ValidateFunc:     validateIAMPolicyJson,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
			},
			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
			},
			"name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name"},
			},
			"user": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceAwsIamUserPolicyPut(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	request := &iam.PutUserPolicyInput{
		UserName:       aws.String(d.Get("user").(string)),
		PolicyDocument: aws.String(d.Get("policy").(string)),
	}

	var policyName string
	var err error
	if !d.IsNewResource() {
		_, policyName, err = resourceAwsIamUserPolicyParseId(d.Id())
		if err != nil {
			return err
		}
	} else if v, ok := d.GetOk("name"); ok {
		policyName = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		policyName = resource.PrefixedUniqueId(v.(string))
	} else {
		policyName = resource.UniqueId()
	}
	request.PolicyName = aws.String(policyName)

	if _, err := iamconn.PutUserPolicy(request); err != nil {
		return fmt.Errorf("Error putting IAM user policy %s: %s", *request.PolicyName, err)
	}

	d.SetId(fmt.Sprintf("%s:%s", *request.UserName, *request.PolicyName))
	return nil
}

func resourceAwsIamUserPolicyRead(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	user, name, err := resourceAwsIamUserPolicyParseId(d.Id())
	if err != nil {
		return err
	}

	request := &iam.GetUserPolicyInput{
		PolicyName: aws.String(name),
		UserName:   aws.String(user),
	}

	getResp, err := iamconn.GetUserPolicy(request)
	if err != nil {
		if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error reading IAM policy %s from user %s: %s", name, user, err)
	}

	if getResp.PolicyDocument == nil {
		return fmt.Errorf("GetUserPolicy returned a nil policy document")
	}

	policy, err := url.QueryUnescape(*getResp.PolicyDocument)
	if err != nil {
		return err
	}
	if err := d.Set("policy", policy); err != nil {
		return err
	}
	if err := d.Set("name", name); err != nil {
		return err
	}
	return d.Set("user", user)
}

func resourceAwsIamUserPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	user, name, err := resourceAwsIamUserPolicyParseId(d.Id())
	if err != nil {
		return err
	}

	request := &iam.DeleteUserPolicyInput{
		PolicyName: aws.String(name),
		UserName:   aws.String(user),
	}

	if _, err := iamconn.DeleteUserPolicy(request); err != nil {
		if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
			return nil
		}
		return fmt.Errorf("Error deleting IAM user policy %s: %s", d.Id(), err)
	}
	return nil
}

func resourceAwsIamUserPolicyParseId(id string) (userName, policyName string, err error) {
	parts := strings.SplitN(id, ":", 2)
	if len(parts) != 2 {
		err = fmt.Errorf("user_policy id must be of the form <user name>:<policy name>")
		return
	}

	userName = parts[0]
	policyName = parts[1]
	return
}
<commit_msg>Add warn log<commit_after>package aws

import (
	"fmt"
	"log"
	"net/url"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIamUserPolicy() *schema.Resource {
	return &schema.Resource{
		// PutUserPolicy API is idempotent, so these can be the same.
		Create: resourceAwsIamUserPolicyPut,
		Read:   resourceAwsIamUserPolicyRead,
		Update: resourceAwsIamUserPolicyPut,
		Delete: resourceAwsIamUserPolicyDelete,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"policy": {
				Type:             schema.TypeString,
				Required:         true,
				ValidateFunc:     validateIAMPolicyJson,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
			},
			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
			},
			"name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name"},
			},
			"user": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
		},
	}
}

func resourceAwsIamUserPolicyPut(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	request := &iam.PutUserPolicyInput{
		UserName:       aws.String(d.Get("user").(string)),
		PolicyDocument: aws.String(d.Get("policy").(string)),
	}

	var policyName string
	var err error
	if !d.IsNewResource() {
		_, policyName, err = resourceAwsIamUserPolicyParseId(d.Id())
		if err != nil {
			return err
		}
	} else if v, ok := d.GetOk("name"); ok {
		policyName = v.(string)
	} else if v, ok := d.GetOk("name_prefix"); ok {
		policyName = resource.PrefixedUniqueId(v.(string))
	} else {
		policyName = resource.UniqueId()
	}
	request.PolicyName = aws.String(policyName)

	if _, err := iamconn.PutUserPolicy(request); err != nil {
		return fmt.Errorf("Error putting IAM user policy %s: %s", *request.PolicyName, err)
	}

	d.SetId(fmt.Sprintf("%s:%s", *request.UserName, *request.PolicyName))
	return nil
}

func resourceAwsIamUserPolicyRead(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	user, name, err := resourceAwsIamUserPolicyParseId(d.Id())
	if err != nil {
		return err
	}

	request := &iam.GetUserPolicyInput{
		PolicyName: aws.String(name),
		UserName:   aws.String(user),
	}

	getResp, err := iamconn.GetUserPolicy(request)
	if err != nil {
		if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
			log.Printf("[WARN] IAM User Policy (%s) for %s not found, removing from state", name, user)
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error reading IAM policy %s from user %s: %s", name, user, err)
	}

	if getResp.PolicyDocument == nil {
		return fmt.Errorf("GetUserPolicy returned a nil policy document")
	}

	policy, err := url.QueryUnescape(*getResp.PolicyDocument)
	if err != nil {
		return err
	}
	if err := d.Set("policy", policy); err != nil {
		return err
	}
	if err := d.Set("name", name); err != nil {
		return err
	}
	return d.Set("user", user)
}

func resourceAwsIamUserPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	iamconn := meta.(*AWSClient).iamconn

	user, name, err := resourceAwsIamUserPolicyParseId(d.Id())
	if err != nil {
		return err
	}

	request := &iam.DeleteUserPolicyInput{
		PolicyName: aws.String(name),
		UserName:   aws.String(user),
	}

	if _, err := iamconn.DeleteUserPolicy(request); err != nil {
		if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
			return nil
		}
		return fmt.Errorf("Error deleting IAM user policy %s: %s", d.Id(), err)
	}
	return nil
}

func resourceAwsIamUserPolicyParseId(id string) (userName, policyName string, err error) {
	parts := strings.SplitN(id, ":", 2)
	if len(parts) != 2 {
		err = fmt.Errorf("user_policy id must be of the form <user name>:<policy name>")
		return
	}

	userName = parts[0]
	policyName = parts[1]
	return
}
<|endoftext|>


<commit_before>package sla

import (
	"fmt"
	"strconv"
)

const (
	SlaKeyRetentionHours = "retention.hours"
	SlaKeyRetentionBytes = "retention.bytes"
	SlaKeyPartitions     = "partitions"
	SlaKeyReplicas       = "replicas"
)

const (
	defaultRetentionBytes = -1     // unlimited
	defaultRetentionHours = 3 * 24 // 3 days
	defaultPartitions     = 1
	defaultReplicas       = 2
)

type TopicSla struct {
	RetentionHours float64
	RetentionBytes int
	Partitions     int
	Replicas       int
}

func DefaultSla() *TopicSla {
	return &TopicSla{
		RetentionBytes: -1,
		RetentionHours: defaultRetentionHours,
		Partitions:     defaultPartitions,
		Replicas:       defaultReplicas,
	}
}

func (this *TopicSla) IsDefault() bool {
	return this.Replicas == defaultReplicas &&
		this.Partitions == defaultPartitions &&
		this.RetentionBytes == defaultRetentionBytes &&
		this.RetentionHours == defaultRetentionHours
}

func (this *TopicSla) ParseRetentionHours(s string) error {
	if len(s) == 0 {
		return ErrEmptyArg
	}

	f, e := strconv.ParseFloat(s, 64)
	if e != nil {
		return ErrNotNumber
	}

	if f < 0 {
		return ErrNegative
	}

	this.RetentionHours = f

	return nil
}

// Dump the sla for kafka-topics.sh as arguments.
func (this *TopicSla) DumpForTopicsCli() []string {
	r := make([]string, 0)
	if this.Partitions != defaultPartitions && this.Partitions > 0 {
		r = append(r, fmt.Sprintf("--partitions %d", this.Partitions))
	}
	if this.Replicas != defaultReplicas && this.Replicas > 0 {
		r = append(r, fmt.Sprintf("--replication-factor %d", this.Replicas))
	}
	if this.RetentionBytes != defaultRetentionBytes && this.RetentionBytes > 0 {
		r = append(r, fmt.Sprintf("--config retention.bytes=%d", this.RetentionBytes))
	}
	if this.RetentionHours != defaultRetentionHours && this.RetentionHours > 0 {
		r = append(r, fmt.Sprintf("--config retention.ms=%d",
			int(this.RetentionHours*1000*3600)))
	}
	return r
}
<commit_msg>validation of upper limit for SLA's<commit_after>package sla

import (
	"fmt"
	"strconv"
)

const (
	SlaKeyRetentionHours = "retention.hours"
	SlaKeyRetentionBytes = "retention.bytes"
	SlaKeyPartitions     = "partitions"
	SlaKeyReplicas       = "replicas"
)

const (
	defaultRetentionBytes = -1     // unlimited
	defaultRetentionHours = 3 * 24 // 3 days
	defaultPartitions     = 1
	defaultReplicas       = 2

	maxReplicas       = 3
	maxPartitions     = 20
	maxRetentionHours = 7 * 24
)

type TopicSla struct {
	RetentionHours float64
	RetentionBytes int
	Partitions     int
	Replicas       int
}

func DefaultSla() *TopicSla {
	return &TopicSla{
		RetentionBytes: -1,
		RetentionHours: defaultRetentionHours,
		Partitions:     defaultPartitions,
		Replicas:       defaultReplicas,
	}
}

func (this *TopicSla) IsDefault() bool {
	return this.Replicas == defaultReplicas &&
		this.Partitions == defaultPartitions &&
		this.RetentionBytes == defaultRetentionBytes &&
		this.RetentionHours == defaultRetentionHours
}

func (this *TopicSla) ParseRetentionHours(s string) error {
	if len(s) == 0 {
		return ErrEmptyArg
	}

	f, e := strconv.ParseFloat(s, 64)
	if e != nil {
		return ErrNotNumber
	}

	if f < 0 {
		return ErrNegative
	}

	this.RetentionHours = f

	return nil
}

// Dump the sla for kafka-topics.sh as arguments.
func (this *TopicSla) DumpForTopicsCli() []string {
	r := make([]string, 0)
	if this.Partitions != defaultPartitions && this.Partitions > 0 && this.Partitions <= maxPartitions {
		r = append(r, fmt.Sprintf("--partitions %d", this.Partitions))
	}
	if this.Replicas != defaultReplicas && this.Replicas > 0 && this.Replicas <= maxReplicas {
		r = append(r, fmt.Sprintf("--replication-factor %d", this.Replicas))
	}
	if this.RetentionBytes != defaultRetentionBytes && this.RetentionBytes > 0 {
		r = append(r, fmt.Sprintf("--config retention.bytes=%d", this.RetentionBytes))
	}
	if this.RetentionHours != defaultRetentionHours && this.RetentionHours > 0 && this.RetentionHours <= maxRetentionHours {
		r = append(r, fmt.Sprintf("--config retention.ms=%d",
			int(this.RetentionHours*1000*3600)))
	}
	return r
}
<|endoftext|>