<commit_before>package main

import (
	"archive/zip"
	"bufio"
	"compress/flate"
	"encoding/binary"
	"encoding/hex"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
)

// from archive/zip struct.go

const (
	fileHeaderSignature      = 0x04034b50
	directoryHeaderSignature = 0x02014b50
	dataDescriptorSignature  = 0x08074b50 // de-facto standard; required by OS X Finder
	fileHeaderLen            = 30         // + filename + extra
	dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
	dataDescriptor64Len      = 24         // descriptor with 8 byte sizes

	// version numbers
	zipVersion20 = 20 // 2.0
	zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
)

type readBuf []byte

func (b *readBuf) uint16() uint16 {
	v := binary.LittleEndian.Uint16(*b)
	*b = (*b)[2:]
	return v
}

func (b *readBuf) uint32() uint32 {
	v := binary.LittleEndian.Uint32(*b)
	*b = (*b)[4:]
	return v
}

func (b *readBuf) uint64() uint64 {
	v := binary.LittleEndian.Uint64(*b)
	*b = (*b)[8:]
	return v
}

func main() {
	debug := flag.Bool("debug", false, "print debug info")
	view := flag.Bool("v", false, "view list")
	out := flag.String("out", "", "write recovered files to output zip file")
	override := flag.Bool("override", false, "override existing files")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] {zip-file}\n", path.Base(os.Args[0]))
		fmt.Fprintf(os.Stderr, "options:\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		return
	}

	zipfile := flag.Arg(0)

	f, err := os.Open(zipfile)
	if err != nil {
		log.Fatal("open ", err)
	}

	defer f.Close()

	r := bufio.NewReader(f)

	var outz *zip.Writer

	create_flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
	if !*override {
		create_flags |= os.O_EXCL
	}

	if len(*out) > 0 {
		outf, err := os.OpenFile(*out, create_flags, 0666)
		if err != nil {
			log.Fatal("create output", err)
		}

		outz = zip.NewWriter(outf)

		defer func() {
			outz.Close()
			outf.Close()
		}()
	}

Loop:
	for {
		var fh [fileHeaderLen]byte

		if _, err := io.ReadFull(r, fh[:]); err != nil {
			log.Println("file header", err)
			break Loop
		}

		if *debug {
			fmt.Println(hex.Dump(fh[:]))
		}

		b := readBuf(fh[:])
		magic := b.uint32()
		version := b.uint16()
		flags := b.uint16()
		comp := b.uint16()
		ctime := b.uint16()
		cdate := b.uint16()
		crc32 := b.uint32()
		clen := b.uint32()
		ulen := b.uint32()
		flen := b.uint16()
		elen := b.uint16()

		ctype := ""

		if magic == directoryHeaderSignature {
			// got central directory. Done
			log.Println("found central directory")
			break Loop
		}

		if magic != fileHeaderSignature {
			log.Println("invalid file header signature ", fmt.Sprintf("%08x", magic))
			break Loop
		}

		if *debug {
			fmt.Println()
			fmt.Printf("magic   %08x\n", magic)
			fmt.Printf("version %04x\n", version)
			fmt.Printf("flags   %04x\n", flags)
			fmt.Printf("comp    %04x\n", comp)
			fmt.Printf("time    %04x\n", ctime)
			fmt.Printf("date    %04x\n", cdate)
			fmt.Printf("crc32   %08x\n", crc32)
			fmt.Printf("compressed size   %d\n", clen)
			fmt.Printf("uncompressed size %d\n", ulen)
			fmt.Printf("filename length   %d\n", flen)
			fmt.Printf("extra length      %d\n", elen)
		}

		fn := make([]byte, flen)
		if _, err := io.ReadFull(r, fn); err != nil {
			log.Println("read file name", err)
			break Loop
		}

		if *debug {
			fmt.Println()
			fmt.Println("filename", string(fn))
		}

		if elen > 0 {
			if _, err := io.CopyN(ioutil.Discard, r, int64(elen)); err != nil {
				log.Println("read extra", err)
				break Loop
			}
		}

		filename := string(fn)

		switch comp {
		case zip.Deflate:
			ctype = "Defl:N"

			var w io.Writer

			if *view {
				w = ioutil.Discard
			} else if outz != nil {
				fmt.Println("adding:", filename)
				if f, err := outz.Create(filename); err != nil {
					log.Fatal("create zip entry ", filename, err)
				} else {
					w = f
				}
			} else {
				fmt.Println("inflating:", filename)

				dir := filepath.Dir(filename)
				if dir != "" {
					if err := os.MkdirAll(dir, 0755); err != nil {
						log.Println("mkdir", dir, err)
					}
				}

				if f, err := os.OpenFile(filename, create_flags, 0666); err != nil {
					log.Fatal("create ", filename, err)
				} else {
					w = f
				}
			}

			dec := flate.NewReader(r)
			n, err := io.Copy(w, dec)
			if *debug {
				fmt.Println("decoded", n, "bytes")
			}
			if err != nil {
				if wc, ok := w.(io.Closer); ok {
					wc.Close()
					os.Remove(filename)
				}

				log.Println("decode file", err)
				break Loop
			} else {
				dec.Close()

				if wc, ok := w.(io.Closer); ok {
					wc.Close()
				}
			}

		case zip.Store:
			ctype = "Stored"

			if ulen > 0 {
				n, err := io.CopyN(ioutil.Discard, r, int64(ulen))
				if *debug {
					fmt.Println("read", n, "bytes")
				}
				if err != nil {
					log.Fatal("read file ", err)
				}
			} else {
				log.Fatal("missing lenght")
			}

		default:
			log.Fatal("unsupported compression mode ", comp)
		}

		if (flags & 0x08) != 0 {
			// data descriptor
			var dd [dataDescriptorLen]byte

			if _, err := io.ReadFull(r, dd[:]); err != nil {
				log.Fatal("data descriptor", err)
			}

			b := readBuf(dd[:])
			magic := b.uint32()
			crc32 = b.uint32()
			clen = b.uint32()
			ulen = b.uint32()

			if magic != dataDescriptorSignature {
				log.Fatal("invalid data descriptor signature ", magic)
			}

			if *debug {
				fmt.Println()
				fmt.Printf("magic   %08x\n", magic)
				fmt.Printf("crc32   %08x\n", crc32)
				fmt.Printf("compressed size   %d\n", clen)
				fmt.Printf("uncompressed size %d\n", ulen)
			}
		}

		if *view {
			pc := 0
			if ulen != 0 {
				pc = 100 - int(clen*100/ulen)
			}
			fmt.Printf("%8d  %6s  %8d  %2d%%  %08x  %s\n", ulen, ctype, clen, pc, crc32, filename)
		}
	}
}
<commit_msg>spelling error<commit_after>package main

import (
	"archive/zip"
	"bufio"
	"compress/flate"
	"encoding/binary"
	"encoding/hex"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
)

// from archive/zip struct.go

const (
	fileHeaderSignature      = 0x04034b50
	directoryHeaderSignature = 0x02014b50
	dataDescriptorSignature  = 0x08074b50 // de-facto standard; required by OS X Finder
	fileHeaderLen            = 30         // + filename + extra
	dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
	dataDescriptor64Len      = 24         // descriptor with 8 byte sizes

	// version numbers
	zipVersion20 = 20 // 2.0
	zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
)

type readBuf []byte

func (b *readBuf) uint16() uint16 {
	v := binary.LittleEndian.Uint16(*b)
	*b = (*b)[2:]
	return v
}

func (b *readBuf) uint32() uint32 {
	v := binary.LittleEndian.Uint32(*b)
	*b = (*b)[4:]
	return v
}

func (b *readBuf) uint64() uint64 {
	v := binary.LittleEndian.Uint64(*b)
	*b = (*b)[8:]
	return v
}

func main() {
	debug := flag.Bool("debug", false, "print debug info")
	view := flag.Bool("v", false, "view list")
	out := flag.String("out", "", "write recovered files to output zip file")
	override := flag.Bool("override", false, "override existing files")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] {zip-file}\n", path.Base(os.Args[0]))
		fmt.Fprintf(os.Stderr, "options:\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		return
	}

	zipfile := flag.Arg(0)

	f, err := os.Open(zipfile)
	if err != nil {
		log.Fatal("open ", err)
	}

	defer f.Close()

	r := bufio.NewReader(f)

	var outz *zip.Writer

	create_flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
	if !*override {
		create_flags |= os.O_EXCL
	}

	if len(*out) > 0 {
		outf, err := os.OpenFile(*out, create_flags, 0666)
		if err != nil {
			log.Fatal("create output", err)
		}

		outz = zip.NewWriter(outf)

		defer func() {
			outz.Close()
			outf.Close()
		}()
	}

Loop:
	for {
		var fh [fileHeaderLen]byte

		if _, err := io.ReadFull(r, fh[:]); err != nil {
			log.Println("file header", err)
			break Loop
		}

		if *debug {
			fmt.Println(hex.Dump(fh[:]))
		}

		b := readBuf(fh[:])
		magic := b.uint32()
		version := b.uint16()
		flags := b.uint16()
		comp := b.uint16()
		ctime := b.uint16()
		cdate := b.uint16()
		crc32 := b.uint32()
		clen := b.uint32()
		ulen := b.uint32()
		flen := b.uint16()
		elen := b.uint16()

		ctype := ""

		if magic == directoryHeaderSignature {
			// got central directory. Done
			log.Println("found central directory")
			break Loop
		}

		if magic != fileHeaderSignature {
			log.Println("invalid file header signature ", fmt.Sprintf("%08x", magic))
			break Loop
		}

		if *debug {
			fmt.Println()
			fmt.Printf("magic   %08x\n", magic)
			fmt.Printf("version %04x\n", version)
			fmt.Printf("flags   %04x\n", flags)
			fmt.Printf("comp    %04x\n", comp)
			fmt.Printf("time    %04x\n", ctime)
			fmt.Printf("date    %04x\n", cdate)
			fmt.Printf("crc32   %08x\n", crc32)
			fmt.Printf("compressed size   %d\n", clen)
			fmt.Printf("uncompressed size %d\n", ulen)
			fmt.Printf("filename length   %d\n", flen)
			fmt.Printf("extra length      %d\n", elen)
		}

		fn := make([]byte, flen)
		if _, err := io.ReadFull(r, fn); err != nil {
			log.Println("read file name", err)
			break Loop
		}

		if *debug {
			fmt.Println()
			fmt.Println("filename", string(fn))
		}

		if elen > 0 {
			if _, err := io.CopyN(ioutil.Discard, r, int64(elen)); err != nil {
				log.Println("read extra", err)
				break Loop
			}
		}

		filename := string(fn)

		switch comp {
		case zip.Deflate:
			ctype = "Defl:N"

			var w io.Writer

			if *view {
				w = ioutil.Discard
			} else if outz != nil {
				fmt.Println("adding:", filename)
				if f, err := outz.Create(filename); err != nil {
					log.Fatal("create zip entry ", filename, err)
				} else {
					w = f
				}
			} else {
				fmt.Println("inflating:", filename)

				dir := filepath.Dir(filename)
				if dir != "" {
					if err := os.MkdirAll(dir, 0755); err != nil {
						log.Println("mkdir", dir, err)
					}
				}

				if f, err := os.OpenFile(filename, create_flags, 0666); err != nil {
					log.Fatal("create ", filename, err)
				} else {
					w = f
				}
			}

			dec := flate.NewReader(r)
			n, err := io.Copy(w, dec)
			if *debug {
				fmt.Println("decoded", n, "bytes")
			}
			if err != nil {
				if wc, ok := w.(io.Closer); ok {
					wc.Close()
					os.Remove(filename)
				}

				log.Println("decode file", err)
				break Loop
			} else {
				dec.Close()

				if wc, ok := w.(io.Closer); ok {
					wc.Close()
				}
			}

		case zip.Store:
			ctype = "Stored"

			if ulen > 0 {
				n, err := io.CopyN(ioutil.Discard, r, int64(ulen))
				if *debug {
					fmt.Println("read", n, "bytes")
				}
				if err != nil {
					log.Fatal("read file ", err)
				}
			} else {
				log.Fatal("missing length")
			}

		default:
			log.Fatal("unsupported compression mode ", comp)
		}

		if (flags & 0x08) != 0 {
			// data descriptor
			var dd [dataDescriptorLen]byte

			if _, err := io.ReadFull(r, dd[:]); err != nil {
				log.Fatal("data descriptor", err)
			}

			b := readBuf(dd[:])
			magic := b.uint32()
			crc32 = b.uint32()
			clen = b.uint32()
			ulen = b.uint32()

			if magic != dataDescriptorSignature {
				log.Fatal("invalid data descriptor signature ", magic)
			}

			if *debug {
				fmt.Println()
				fmt.Printf("magic   %08x\n", magic)
				fmt.Printf("crc32   %08x\n", crc32)
				fmt.Printf("compressed size   %d\n", clen)
				fmt.Printf("uncompressed size %d\n", ulen)
			}
		}

		if *view {
			pc := 0
			if ulen != 0 {
				pc = 100 - int(clen*100/ulen)
			}
			fmt.Printf("%8d  %6s  %8d  %2d%%  %08x  %s\n", ulen, ctype, clen, pc, crc32, filename)
		}
	}
}
<|endoftext|>


<commit_before>package autopull

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/google/go-github/github"
	"github.com/parkr/auto-reply/common"
)

var (
	baseBranch *string = github.String("master")
)

type AutoPullHandler struct {
	client *github.Client
	repos  map[string]bool
}

func shortMessage(message string) string {
	return strings.SplitN(message, "\n", 1)[0]
}

// branchFromRef takes "refs/heads/pull/my-pull" and returns "pull/my-pull"
func branchFromRef(ref string) string {
	return strings.Replace(ref, "refs/heads/", "", 1)
}

func prBodyForPush(push github.PushEvent) string {
	var mention string
	if author := push.Commits[0].Author; author != nil {
		if author.Username != nil {
			mention = *author.Username
		} else {
			mention = *author.Name
		}
	} else {
		mention = "unknown"
	}
	return fmt.Sprintf(
		"PR automatically created for @%s.\n\n```text\n%s```",
		mention,
		*push.Commits[0].Message,
	)
}

func newPRForPush(push github.PushEvent) *github.NewPullRequest {
	if push.Commits == nil || len(push.Commits) == 0 {
		return nil
	}
	return &github.NewPullRequest{
		Title: github.String(shortMessage(*push.Commits[0].Message)),
		Head:  github.String(branchFromRef(*push.Ref)),
		Base:  github.String("master"),
		Body:  github.String(prBodyForPush(push)),
	}
}

func (h *AutoPullHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Header.Get("X-GitHub-Event") != "push" {
		log.Println("received non-push event for autopull. sending pong.")
		http.Error(w, "pong. ignored this one.", 200)
		return
	}

	var push github.PushEvent
	err := json.Unmarshal(common.ClearJSONRepoOrgField(r.Body), &push)
	if err != nil {
		log.Println("error unmarshalling issue stuffs:", err)
		body, err := ioutil.ReadAll(r.Body)
		log.Println("ioutil.ReadAll:", body, err)
		http.Error(w, "bad json", 400)
		return
	}

	log.Println(push)
	if _, ok := h.repos[*push.Repo.FullName]; ok && strings.HasPrefix(*push.Ref, "refs/heads/pull/") {
		pr := newPRForPush(push)
		if pr == nil {
			http.Error(w, "ignoring", 200)
			return
		}

		pull, _, err := h.client.PullRequests.Create(*push.Repo.Owner.Name, *push.Repo.Name, pr)
		if err != nil {
			log.Printf("error creating pull request for %s/%s: %v", *push.Repo.Owner.Login, *push.Repo.Name, err)
			http.Error(w, "pr could not be created", 500)
			return
		}

		http.Error(w, "pr created: "+*pull.HTMLURL, 201)
	} else {
		log.Println("ignoring - ref doesn't match pull/* or not supported repo.")
		http.Error(w, "ignoring", 200)
	}
}

func NewHandler(client *github.Client, handledRepos []string) *AutoPullHandler {
	return &AutoPullHandler{
		client: client,
		repos:  common.SliceLookup(handledRepos),
	}
}
<commit_msg>autopull: needs newline in backtick block<commit_after>package autopull

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"

	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/google/go-github/github"
	"github.com/parkr/auto-reply/common"
)

var (
	baseBranch *string = github.String("master")
)

type AutoPullHandler struct {
	client *github.Client
	repos  map[string]bool
}

func shortMessage(message string) string {
	return strings.SplitN(message, "\n", 1)[0]
}

// branchFromRef takes "refs/heads/pull/my-pull" and returns "pull/my-pull"
func branchFromRef(ref string) string {
	return strings.Replace(ref, "refs/heads/", "", 1)
}

func prBodyForPush(push github.PushEvent) string {
	var mention string
	if author := push.Commits[0].Author; author != nil {
		if author.Username != nil {
			mention = *author.Username
		} else {
			mention = *author.Name
		}
	} else {
		mention = "unknown"
	}
	return fmt.Sprintf(
		"PR automatically created for @%s.\n\n```text\n%s\n```",
		mention,
		*push.Commits[0].Message,
	)
}

func newPRForPush(push github.PushEvent) *github.NewPullRequest {
	if push.Commits == nil || len(push.Commits) == 0 {
		return nil
	}
	return &github.NewPullRequest{
		Title: github.String(shortMessage(*push.Commits[0].Message)),
		Head:  github.String(branchFromRef(*push.Ref)),
		Base:  github.String("master"),
		Body:  github.String(prBodyForPush(push)),
	}
}

func (h *AutoPullHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Header.Get("X-GitHub-Event") != "push" {
		log.Println("received non-push event for autopull. sending pong.")
		http.Error(w, "pong. ignored this one.", 200)
		return
	}

	var push github.PushEvent
	err := json.Unmarshal(common.ClearJSONRepoOrgField(r.Body), &push)
	if err != nil {
		log.Println("error unmarshalling issue stuffs:", err)
		body, err := ioutil.ReadAll(r.Body)
		log.Println("ioutil.ReadAll:", body, err)
		http.Error(w, "bad json", 400)
		return
	}

	log.Println(push)
	if _, ok := h.repos[*push.Repo.FullName]; ok && strings.HasPrefix(*push.Ref, "refs/heads/pull/") {
		pr := newPRForPush(push)
		if pr == nil {
			http.Error(w, "ignoring", 200)
			return
		}

		pull, _, err := h.client.PullRequests.Create(*push.Repo.Owner.Name, *push.Repo.Name, pr)
		if err != nil {
			log.Printf("error creating pull request for %s/%s: %v", *push.Repo.Owner.Login, *push.Repo.Name, err)
			http.Error(w, "pr could not be created", 500)
			return
		}

		http.Error(w, "pr created: "+*pull.HTMLURL, 201)
	} else {
		log.Println("ignoring - ref doesn't match pull/* or not supported repo.")
		http.Error(w, "ignoring", 200)
	}
}

func NewHandler(client *github.Client, handledRepos []string) *AutoPullHandler {
	return &AutoPullHandler{
		client: client,
		repos:  common.SliceLookup(handledRepos),
	}
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 Aaron Hopkins. All rights reserved.
// Use of this source code is governed by the GPL v2 license
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"github.com/die-net/fotomat/imager"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"time"
)

var (
	maxOutputDimension    = flag.Int("max_output_dimension", 2048, "Maximum width or height of an image response.")
	maxBufferPixels       = flag.Uint("max_buffer_pixels", 6500000, "Maximum number of pixels to allocate for an intermediate image buffer.")
	maxProcessingDuration = flag.Duration("max_processing_duration", time.Minute, "Maximum duration we can be processing an image before assuming we crashed (0 = disable).")
	pool                  chan bool
)

func init() {
	http.HandleFunc("/", imageProxyHandler)
	http.HandleFunc("/albums/crop", albumsCropHandler)
}

func imageProxyHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" && r.Method != "HEAD" {
		sendError(w, nil, http.StatusMethodNotAllowed)
		return
	}

	path, crop, width, height, ok := parsePath(r.URL.Path)
	if !ok {
		sendError(w, nil, 400)
		return
	}

	u := &url.URL{Scheme: "http", Host: r.Host, Path: path}

	fetchAndProcessImage(w, u.String(), crop, width, height)
}

var matchPath = regexp.MustCompile(`^(/.*)=([sc])(\d{1,5})x(\d{1,5})$`)

func parsePath(path string) (string, bool, uint, uint, bool) {
	g := matchPath.FindStringSubmatch(path)
	if len(g) != 5 {
		return "", false, 0, 0, false
	}

	width, err := strconv.Atoi(g[3])
	if err != nil || width <= 0 || width >= *maxOutputDimension {
		return "", false, 0, 0, false
	}

	height, err := strconv.Atoi(g[4])
	if err != nil || height <= 0 || height >= *maxOutputDimension {
		return "", false, 0, 0, false
	}

	return g[1], (g[2] == "c"), uint(width), uint(height), true
}

func poolInit(limit int) {
	pool = make(chan bool, limit)
	for i := 0; i < limit; i++ {
		pool <- true
	}
}

/*
        Supported geometries:
	WxH#        - scale down so the shorter edge fits within this bounding box, crop to new aspect ratio
	WxH or WxH> - scale down so the longer edge fits within this bounding box, no crop
*/
var matchGeometry = regexp.MustCompile(`^(\d{1,5})x(\d{1,5})([>#])?$`)

func albumsCropHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" && r.Method != "HEAD" {
		sendError(w, nil, http.StatusMethodNotAllowed)
		return
	}

	if err := r.ParseForm(); err != nil {
		sendError(w, err, 0)
		return
	}

	crop, width, height, ok := parseGeometry(r.FormValue("geometry"))
	if !ok {
		sendError(w, nil, 400)
		return
	}

	fetchAndProcessImage(w, r.FormValue("image_url"), crop, width, height)
}

func fetchAndProcessImage(w http.ResponseWriter, url string, crop bool, width, height uint) {
	aborted := w.(http.CloseNotifier).CloseNotify()

	orig, err, status := fetchUrl(url)
	if err != nil || status != http.StatusOK {
		sendError(w, err, status)
		return
	}

	// Wait for an image thread to be available.
	<-pool

	// Has client closed connection while we were waiting?
	select {
	case <-aborted:
		pool <- true // Free up image thread ASAP.
		sendError(w, nil, http.StatusRequestTimeout)
		return
	default:
	}

	thumb, err := processImage(url, orig, crop, width, height)
	orig = nil // Free up image memory ASAP.

	pool <- true // Free up image thread ASAP.

	if err != nil {
		sendError(w, err, 0)
		return
	}

	w.Write(thumb)
}

func parseGeometry(geometry string) (bool, uint, uint, bool) {
	g := matchGeometry.FindStringSubmatch(geometry)
	if len(g) != 4 {
		return false, 0, 0, false
	}
	width, err := strconv.Atoi(g[1])
	if err != nil || width <= 0 || width >= *maxOutputDimension {
		return false, 0, 0, false
	}
	height, err := strconv.Atoi(g[2])
	if err != nil || height <= 0 || height >= *maxOutputDimension {
		return false, 0, 0, false
	}
	crop := (g[3] == "#")
	return crop, uint(width), uint(height), true
}

func fetchUrl(url string) ([]byte, error, int) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err, 0
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err, 0
	}

	switch resp.StatusCode {
	case http.StatusOK,
		http.StatusNoContent,
		http.StatusBadRequest,
		http.StatusUnauthorized,
		http.StatusForbidden,
		http.StatusNotFound,
		http.StatusRequestTimeout,
		http.StatusGone:
		return body, nil, resp.StatusCode
	default:
		err := fmt.Errorf("Proxy received %d %s", resp.StatusCode, http.StatusText(resp.StatusCode))
		return nil, err, http.StatusBadGateway
	}
}

func processImage(url string, orig []byte, crop bool, width, height uint) ([]byte, error) {
	if *maxProcessingDuration > 0 {
		timer := time.AfterFunc(*maxProcessingDuration, func() {
			panic(fmt.Sprintf("Processing %v longer than %v", url, *maxProcessingDuration))
		})
		defer timer.Stop()
	}

	img, err := imager.New(orig, *maxBufferPixels)
	if err != nil {
		return nil, err
	}

	defer img.Close()

	var thumb []byte
	if crop {
		thumb, err = img.Crop(width, height)
	} else {
		thumb, err = img.Thumbnail(width, height, true)
	}
	return thumb, err
}

func sendError(w http.ResponseWriter, err error, status int) {
	if status == 0 {
		switch err {
		case imager.UnknownFormat:
			status = http.StatusUnsupportedMediaType
		case imager.TooBig:
			status = http.StatusRequestEntityTooLarge
		default:
			status = http.StatusInternalServerError
		}
	}
	if err == nil {
		err = fmt.Errorf(http.StatusText(status))
	}
	http.Error(w, err.Error(), status)
}
<commit_msg>Explicitly set thumb = nil when done with image.<commit_after>// Copyright 2013-2014 Aaron Hopkins. All rights reserved.
// Use of this source code is governed by the GPL v2 license
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"github.com/die-net/fotomat/imager"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"time"
)

var (
	maxOutputDimension    = flag.Int("max_output_dimension", 2048, "Maximum width or height of an image response.")
	maxBufferPixels       = flag.Uint("max_buffer_pixels", 6500000, "Maximum number of pixels to allocate for an intermediate image buffer.")
	maxProcessingDuration = flag.Duration("max_processing_duration", time.Minute, "Maximum duration we can be processing an image before assuming we crashed (0 = disable).")
	pool                  chan bool
)

func init() {
	http.HandleFunc("/", imageProxyHandler)
	http.HandleFunc("/albums/crop", albumsCropHandler)
}

func imageProxyHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" && r.Method != "HEAD" {
		sendError(w, nil, http.StatusMethodNotAllowed)
		return
	}

	path, crop, width, height, ok := parsePath(r.URL.Path)
	if !ok {
		sendError(w, nil, 400)
		return
	}

	u := &url.URL{Scheme: "http", Host: r.Host, Path: path}

	fetchAndProcessImage(w, u.String(), crop, width, height)
}

var matchPath = regexp.MustCompile(`^(/.*)=([sc])(\d{1,5})x(\d{1,5})$`)

func parsePath(path string) (string, bool, uint, uint, bool) {
	g := matchPath.FindStringSubmatch(path)
	if len(g) != 5 {
		return "", false, 0, 0, false
	}

	width, err := strconv.Atoi(g[3])
	if err != nil || width <= 0 || width >= *maxOutputDimension {
		return "", false, 0, 0, false
	}

	height, err := strconv.Atoi(g[4])
	if err != nil || height <= 0 || height >= *maxOutputDimension {
		return "", false, 0, 0, false
	}

	return g[1], (g[2] == "c"), uint(width), uint(height), true
}

func poolInit(limit int) {
	pool = make(chan bool, limit)
	for i := 0; i < limit; i++ {
		pool <- true
	}
}

/*
        Supported geometries:
	WxH#        - scale down so the shorter edge fits within this bounding box, crop to new aspect ratio
	WxH or WxH> - scale down so the longer edge fits within this bounding box, no crop
*/
var matchGeometry = regexp.MustCompile(`^(\d{1,5})x(\d{1,5})([>#])?$`)

func albumsCropHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" && r.Method != "HEAD" {
		sendError(w, nil, http.StatusMethodNotAllowed)
		return
	}

	if err := r.ParseForm(); err != nil {
		sendError(w, err, 0)
		return
	}

	crop, width, height, ok := parseGeometry(r.FormValue("geometry"))
	if !ok {
		sendError(w, nil, 400)
		return
	}

	fetchAndProcessImage(w, r.FormValue("image_url"), crop, width, height)
}

func fetchAndProcessImage(w http.ResponseWriter, url string, crop bool, width, height uint) {
	aborted := w.(http.CloseNotifier).CloseNotify()

	orig, err, status := fetchUrl(url)
	if err != nil || status != http.StatusOK {
		sendError(w, err, status)
		return
	}

	// Wait for an image thread to be available.
	<-pool

	// Has client closed connection while we were waiting?
	select {
	case <-aborted:
		pool <- true // Free up image thread ASAP.
		sendError(w, nil, http.StatusRequestTimeout)
		return
	default:
	}

	thumb, err := processImage(url, orig, crop, width, height)
	orig = nil // Free up image memory ASAP.

	pool <- true // Free up image thread ASAP.

	if err != nil {
		thumb = nil // Free up image memory ASAP.
		sendError(w, err, 0)
		return
	}

	w.Write(thumb)
	thumb = nil // Free up image memory ASAP.
}

func parseGeometry(geometry string) (bool, uint, uint, bool) {
	g := matchGeometry.FindStringSubmatch(geometry)
	if len(g) != 4 {
		return false, 0, 0, false
	}
	width, err := strconv.Atoi(g[1])
	if err != nil || width <= 0 || width >= *maxOutputDimension {
		return false, 0, 0, false
	}
	height, err := strconv.Atoi(g[2])
	if err != nil || height <= 0 || height >= *maxOutputDimension {
		return false, 0, 0, false
	}
	crop := (g[3] == "#")
	return crop, uint(width), uint(height), true
}

func fetchUrl(url string) ([]byte, error, int) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err, 0
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err, 0
	}

	switch resp.StatusCode {
	case http.StatusOK,
		http.StatusNoContent,
		http.StatusBadRequest,
		http.StatusUnauthorized,
		http.StatusForbidden,
		http.StatusNotFound,
		http.StatusRequestTimeout,
		http.StatusGone:
		return body, nil, resp.StatusCode
	default:
		err := fmt.Errorf("Proxy received %d %s", resp.StatusCode, http.StatusText(resp.StatusCode))
		return nil, err, http.StatusBadGateway
	}
}

func processImage(url string, orig []byte, crop bool, width, height uint) ([]byte, error) {
	if *maxProcessingDuration > 0 {
		timer := time.AfterFunc(*maxProcessingDuration, func() {
			panic(fmt.Sprintf("Processing %v longer than %v", url, *maxProcessingDuration))
		})
		defer timer.Stop()
	}

	img, err := imager.New(orig, *maxBufferPixels)
	if err != nil {
		return nil, err
	}

	defer img.Close()

	var thumb []byte
	if crop {
		thumb, err = img.Crop(width, height)
	} else {
		thumb, err = img.Thumbnail(width, height, true)
	}
	return thumb, err
}

func sendError(w http.ResponseWriter, err error, status int) {
	if status == 0 {
		switch err {
		case imager.UnknownFormat:
			status = http.StatusUnsupportedMediaType
		case imager.TooBig:
			status = http.StatusRequestEntityTooLarge
		default:
			status = http.StatusInternalServerError
		}
	}
	if err == nil {
		err = fmt.Errorf(http.StatusText(status))
	}
	http.Error(w, err.Error(), status)
}
<|endoftext|>


<commit_before>package images

import(
  "fmt"
  "io"
  "io/ioutil"
  "encoding/json"
  "github.com/ricallinson/forgery"
  "github.com/spacedock-io/registry/db"
  "github.com/spacedock-io/registry/models"
  "github.com/spacedock-io/registry/cloudfiles"
)

func GetJson(req *f.Request, res *f.Response) {
  var image models.Image
  q := db.DB.Where(&models.Image{Uuid: req.Params["id"]}).First(&image)
  if q.Error != nil {
    res.Send(404)
    return
  }

  res.Set("X-Docker-Size", string(image.Size))
  res.Set("X-Docker-Checksum", image.Checksum)

  res.Send(image.Json)
}

func PutJson(req *f.Request, res *f.Response) {
  var image models.Image
  var err error

  q := db.DB.Where(&models.Image{Uuid: req.Params["id"]}).First(&image)
  fmt.Printf("q: %+v\n", q)
  if q.Error != nil {
    if q.RecordNotFound() == false {
      res.Send(404)
      return
    }
  }

  image.Json, err = ioutil.ReadAll(req.Request.Request.Body)

  if err != nil {
    res.Send(500)
    return
  }

  fmt.Printf("image: %+v\n", image)
  q := db.DB.Save(&image)
  fmt.Printf("q: %+v\n", q)
  if q.Error != nil {
    res.Send(500)
    return
  }

  res.Send(200)
}

func GetLayer(req *f.Request, res *f.Response) {
  _, err := cloudfiles.Cloudfiles.ObjectGet(
    "default", req.Params["id"], res.Response.Writer, true, nil)
  if err == nil {
    res.Send(200)
  } else { res.Send(500) }
}

func PutLayer(req *f.Request, res *f.Response) {
  obj, err := cloudfiles.Cloudfiles.ObjectCreate(
    "default", req.Params["id"], true, "", "", nil)
  if err == nil {
    io.Copy(obj, req.Request.Request.Body)
    res.Send(200)
  } else { res.Send(500) }
}

func GetAncestry(req *f.Request, res *f.Response) {
  var image models.Image
  q := db.DB.First(&models.Image{Uuid: req.Params["id"]}).First(&image)
  if q.Error != nil {
    res.Send(404)
    return
  }

  data, err := json.Marshal(image.Ancestry)

  if err == nil {
    res.Send(data)
  } else { res.Send(500) }
}
<commit_msg>Fix no new variables<commit_after>package images

import(
  "fmt"
  "io"
  "io/ioutil"
  "encoding/json"
  "github.com/ricallinson/forgery"
  "github.com/spacedock-io/registry/db"
  "github.com/spacedock-io/registry/models"
  "github.com/spacedock-io/registry/cloudfiles"
)

func GetJson(req *f.Request, res *f.Response) {
  var image models.Image
  q := db.DB.Where(&models.Image{Uuid: req.Params["id"]}).First(&image)
  if q.Error != nil {
    res.Send(404)
    return
  }

  res.Set("X-Docker-Size", string(image.Size))
  res.Set("X-Docker-Checksum", image.Checksum)

  res.Send(image.Json)
}

func PutJson(req *f.Request, res *f.Response) {
  var image models.Image
  var err error

  q := db.DB.Where(&models.Image{Uuid: req.Params["id"]}).First(&image)
  fmt.Printf("q: %+v\n", q)
  if q.Error != nil {
    if q.RecordNotFound() == false {
      res.Send(404)
      return
    }
  }

  image.Json, err = ioutil.ReadAll(req.Request.Request.Body)

  if err != nil {
    res.Send(500)
    return
  }

  fmt.Printf("image: %+v\n", image)
  q = db.DB.Save(&image)
  fmt.Printf("q: %+v\n", q)
  if q.Error != nil {
    res.Send(500)
    return
  }

  res.Send(200)
}

func GetLayer(req *f.Request, res *f.Response) {
  _, err := cloudfiles.Cloudfiles.ObjectGet(
    "default", req.Params["id"], res.Response.Writer, true, nil)
  if err == nil {
    res.Send(200)
  } else { res.Send(500) }
}

func PutLayer(req *f.Request, res *f.Response) {
  obj, err := cloudfiles.Cloudfiles.ObjectCreate(
    "default", req.Params["id"], true, "", "", nil)
  if err == nil {
    io.Copy(obj, req.Request.Request.Body)
    res.Send(200)
  } else { res.Send(500) }
}

func GetAncestry(req *f.Request, res *f.Response) {
  var image models.Image
  q := db.DB.First(&models.Image{Uuid: req.Params["id"]}).First(&image)
  if q.Error != nil {
    res.Send(404)
    return
  }

  data, err := json.Marshal(image.Ancestry)

  if err == nil {
    res.Send(data)
  } else { res.Send(500) }
}
<|endoftext|>


<commit_before>package terminal

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"

	"github.com/derekparker/delve/proc/test"
	"github.com/derekparker/delve/service"
	"github.com/derekparker/delve/service/api"
	"github.com/derekparker/delve/service/rpc"
)

type FakeTerminal struct {
	*Term
	t      testing.TB
	client service.Client
	cmds   *Commands
}

func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
	cmdstr, args := parseCommand(cmdstr)

	outfh, err := ioutil.TempFile("", "cmdtestout")
	if err != nil {
		ft.t.Fatalf("could not create temporary file: %v", err)
	}

	stdout, stderr := os.Stdout, os.Stderr
	os.Stdout, os.Stderr = outfh, outfh
	defer func() {
		os.Stdout, os.Stderr = stdout, stderr
		outfh.Close()
		outbs, err1 := ioutil.ReadFile(outfh.Name())
		if err1 != nil {
			ft.t.Fatalf("could not read temporary output file: %v", err)
		}
		outstr = string(outbs)
		os.Remove(outfh.Name())
	}()
	err = ft.cmds.Call(cmdstr, args, ft.Term)
	return
}

func (ft *FakeTerminal) MustExec(cmdstr string) string {
	outstr, err := ft.Exec(cmdstr)
	if err != nil {
		ft.t.Fatalf("Error executing <%s>: %v", cmdstr, err)
	}
	return outstr
}

func (ft *FakeTerminal) AssertExec(cmdstr, tgt string) {
	out := ft.MustExec(cmdstr)
	if out != tgt {
		ft.t.Fatalf("Error executing %q, expected %q got %q", cmdstr, tgt, out)
	}
}

func (ft *FakeTerminal) AssertExecError(cmdstr, tgterr string) {
	_, err := ft.Exec(cmdstr)
	if err == nil {
		ft.t.Fatalf("Expected error executing %q")
	}
	if err.Error() != tgterr {
		ft.t.Fatalf("Expected error %q executing %q, got error %q", tgterr, cmdstr, err.Error())
	}
}

func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) {
	listener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("couldn't start listener: %s\n", err)
	}
	defer listener.Close()
	server := rpc.NewServer(&service.Config{
		Listener:    listener,
		ProcessArgs: []string{test.BuildFixture(name).Path},
	}, false)
	if err := server.Run(); err != nil {
		t.Fatal(err)
	}
	client := rpc.NewClient(listener.Addr().String())
	defer func() {
		client.Detach(true)
	}()

	ft := &FakeTerminal{
		t:      t,
		client: client,
		cmds:   DebugCommands(client),
		Term:   New(client, nil),
	}
	fn(ft)
}

func TestCommandDefault(t *testing.T) {
	var (
		cmds = Commands{}
		cmd  = cmds.Find("non-existant-command", noPrefix)
	)

	err := cmd(nil, callContext{}, "")
	if err == nil {
		t.Fatal("cmd() did not default")
	}

	if err.Error() != "command not available" {
		t.Fatal("wrong command output")
	}
}

func TestCommandReplay(t *testing.T) {
	cmds := DebugCommands(nil)
	cmds.Register("foo", func(t *Term, ctx callContext, args string) error { return fmt.Errorf("registered command") }, "foo command")
	cmd := cmds.Find("foo", noPrefix)

	err := cmd(nil, callContext{}, "")
	if err.Error() != "registered command" {
		t.Fatal("wrong command output")
	}

	cmd = cmds.Find("", noPrefix)
	err = cmd(nil, callContext{}, "")
	if err.Error() != "registered command" {
		t.Fatal("wrong command output")
	}
}

func TestCommandReplayWithoutPreviousCommand(t *testing.T) {
	var (
		cmds = DebugCommands(nil)
		cmd  = cmds.Find("", noPrefix)
		err  = cmd(nil, callContext{}, "")
	)

	if err != nil {
		t.Error("Null command not returned", err)
	}
}

func TestCommandThread(t *testing.T) {
	var (
		cmds = DebugCommands(nil)
		cmd  = cmds.Find("thread", noPrefix)
	)

	err := cmd(nil, callContext{}, "")
	if err == nil {
		t.Fatal("thread terminal command did not default")
	}

	if err.Error() != "you must specify a thread" {
		t.Fatal("wrong command output: ", err.Error())
	}
}

func TestExecuteFile(t *testing.T) {
	breakCount := 0
	traceCount := 0
	c := &Commands{
		client: nil,
		cmds: []command{
			{aliases: []string{"trace"}, cmdFn: func(t *Term, ctx callContext, args string) error {
				traceCount++
				return nil
			}},
			{aliases: []string{"break"}, cmdFn: func(t *Term, ctx callContext, args string) error {
				breakCount++
				return nil
			}},
		},
	}

	fixturesDir := test.FindFixturesDir()

	err := c.executeFile(nil, filepath.Join(fixturesDir, "bpfile"))

	if err != nil {
		t.Fatalf("executeFile: %v", err)
	}

	if breakCount != 1 || traceCount != 1 {
		t.Fatalf("Wrong counts break: %d trace: %d\n", breakCount, traceCount)
	}
}

func TestIssue354(t *testing.T) {
	printStack([]api.Stackframe{}, "")
	printStack([]api.Stackframe{{api.Location{PC: 0, File: "irrelevant.go", Line: 10, Function: nil}, nil, nil}}, "")
}

func TestIssue411(t *testing.T) {
	withTestTerminal("math", t, func(term *FakeTerminal) {
		term.MustExec("break math.go:8")
		term.MustExec("trace math.go:9")
		term.MustExec("continue")
		out := term.MustExec("next")
		if !strings.HasPrefix(out, "> main.main()") {
			t.Fatalf("Wrong output for next: <%s>", out)
		}
	})
}

func TestScopePrefix(t *testing.T) {
	const goroutinesLinePrefix = "  Goroutine "
	const goroutinesCurLinePrefix = "* Goroutine "
	withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) {
		term.MustExec("b stacktraceme")
		term.MustExec("continue")

		goroutinesOut := strings.Split(term.MustExec("goroutines"), "\n")

		agoroutines := []int{}
		curgid := -1

		for _, line := range goroutinesOut {
			iscur := strings.HasPrefix(line, goroutinesCurLinePrefix)
			if !iscur && !strings.HasPrefix(line, goroutinesLinePrefix) {
				continue
			}

			dash := strings.Index(line, " - ")
			if dash < 0 {
				continue
			}

			gid, err := strconv.Atoi(line[len(goroutinesLinePrefix):dash])
			if err != nil {
				continue
			}

			if iscur {
				curgid = gid
			}

			if idx := strings.Index(line, " main.agoroutine "); idx < 0 {
				continue
			}

			agoroutines = append(agoroutines, gid)
		}

		if len(agoroutines) != 10 {
			t.Fatalf("Output of goroutines did not have 10 goroutines stopped on main.agoroutine: %q", goroutinesOut)
		}

		if curgid < 0 {
			t.Fatalf("Could not find current goroutine in output of goroutines: %q", goroutinesOut)
		}

		seen := make([]bool, 10)
		_ = seen

		for _, gid := range agoroutines {
			stackOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d stack", gid)), "\n")
			fid := -1
			for _, line := range stackOut {
				space := strings.Index(line, " ")
				if space < 0 {
					continue
				}
				curfid, err := strconv.Atoi(line[:space])
				if err != nil {
					continue
				}

				if idx := strings.Index(line, " main.agoroutine"); idx >= 0 {
					fid = curfid
					break
				}
			}
			if fid < 0 {
				t.Fatalf("Could not find frame for goroutine %d: %v", gid, stackOut)
			}
			term.AssertExec(fmt.Sprintf("goroutine %d frame %d locals", gid, fid), "")
			argsOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d frame %d args", gid, fid)), "\n")
			if len(argsOut) != 4 || argsOut[3] != "" {
				t.Fatalf("Wrong number of arguments in goroutine %d frame %d: %v", gid, fid, argsOut)
			}
			out := term.MustExec(fmt.Sprintf("goroutine %d frame %d p i", gid, fid))
			ival, err := strconv.Atoi(out[:len(out)-1])
			if err != nil {
				t.Fatalf("could not parse value %q of i for goroutine %d frame %d: %v", out, gid, fid, err)
			}
			seen[ival] = true
		}

		for i := range seen {
			if !seen[i] {
				t.Fatalf("goroutine %d not found", i)
			}
		}

		term.MustExec("c")

		term.AssertExecError("frame", "not enough arguments")
		term.AssertExecError("frame 1", "not enough arguments")
		term.AssertExecError("frame 1 goroutines", "command not available")
		term.AssertExecError("frame 1 goroutine", "no command passed to goroutine")
		term.AssertExecError(fmt.Sprintf("frame 1 goroutine %d", curgid), "no command passed to goroutine")
		term.AssertExecError(fmt.Sprintf("goroutine %d frame 10 locals", curgid), fmt.Sprintf("Frame 10 does not exist in goroutine %d", curgid))
		term.AssertExecError("goroutine 9000 locals", "Unknown goroutine 9000")

		term.AssertExecError("print n", "could not find symbol value for n")
		term.AssertExec("frame 1 print n", "3\n")
		term.AssertExec("frame 2 print n", "2\n")
		term.AssertExec("frame 3 print n", "1\n")
		term.AssertExec("frame 4 print n", "0\n")
		term.AssertExecError("frame 5 print n", "could not find symbol value for n")
	})
}

func TestOnPrefix(t *testing.T) {
	const prefix = "\ti: "
	withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) {
		term.MustExec("b agobp main.agoroutine")
		term.MustExec("on agobp print i")

		seen := make([]bool, 10)

		for {
			outstr, err := term.Exec("continue")
			if err != nil {
				if strings.Index(err.Error(), "exited") < 0 {
					t.Fatalf("Unexpected error executing 'continue': %v", err)
				}
				break
			}
			out := strings.Split(outstr, "\n")

			for i := range out {
				if !strings.HasPrefix(out[i], "\ti: ") {
					continue
				}
				id, err := strconv.Atoi(out[i][len(prefix):])
				if err != nil {
					continue
				}
				if seen[id] {
					t.Fatalf("Goroutine %d seen twice\n", id)
				}
				seen[id] = true
			}
		}

		for i := range seen {
			if !seen[i] {
				t.Fatalf("Goroutine %d not seen\n", i)
			}
		}
	})
}
<commit_msg>terminal: misc cleanup<commit_after>package terminal

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"

	"github.com/derekparker/delve/proc/test"
	"github.com/derekparker/delve/service"
	"github.com/derekparker/delve/service/api"
	"github.com/derekparker/delve/service/rpc"
)

type FakeTerminal struct {
	*Term
	t testing.TB
}

func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
	cmdstr, args := parseCommand(cmdstr)

	outfh, err := ioutil.TempFile("", "cmdtestout")
	if err != nil {
		ft.t.Fatalf("could not create temporary file: %v", err)
	}

	stdout, stderr := os.Stdout, os.Stderr
	os.Stdout, os.Stderr = outfh, outfh
	defer func() {
		os.Stdout, os.Stderr = stdout, stderr
		outfh.Close()
		outbs, err1 := ioutil.ReadFile(outfh.Name())
		if err1 != nil {
			ft.t.Fatalf("could not read temporary output file: %v", err)
		}
		outstr = string(outbs)
		os.Remove(outfh.Name())
	}()
	err = ft.cmds.Call(cmdstr, args, ft.Term)
	return
}

func (ft *FakeTerminal) MustExec(cmdstr string) string {
	outstr, err := ft.Exec(cmdstr)
	if err != nil {
		ft.t.Fatalf("Error executing <%s>: %v", cmdstr, err)
	}
	return outstr
}

func (ft *FakeTerminal) AssertExec(cmdstr, tgt string) {
	out := ft.MustExec(cmdstr)
	if out != tgt {
		ft.t.Fatalf("Error executing %q, expected %q got %q", cmdstr, tgt, out)
	}
}

func (ft *FakeTerminal) AssertExecError(cmdstr, tgterr string) {
	_, err := ft.Exec(cmdstr)
	if err == nil {
		ft.t.Fatalf("Expected error executing %q", cmdstr)
	}
	if err.Error() != tgterr {
		ft.t.Fatalf("Expected error %q executing %q, got error %q", tgterr, cmdstr, err.Error())
	}
}

func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) {
	listener, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("couldn't start listener: %s\n", err)
	}
	defer listener.Close()
	server := rpc.NewServer(&service.Config{
		Listener:    listener,
		ProcessArgs: []string{test.BuildFixture(name).Path},
	}, false)
	if err := server.Run(); err != nil {
		t.Fatal(err)
	}
	client := rpc.NewClient(listener.Addr().String())
	defer func() {
		client.Detach(true)
	}()

	ft := &FakeTerminal{
		t:    t,
		Term: New(client, nil),
	}
	fn(ft)
}

func TestCommandDefault(t *testing.T) {
	var (
		cmds = Commands{}
		cmd  = cmds.Find("non-existant-command", noPrefix)
	)

	err := cmd(nil, callContext{}, "")
	if err == nil {
		t.Fatal("cmd() did not default")
	}

	if err.Error() != "command not available" {
		t.Fatal("wrong command output")
	}
}

func TestCommandReplay(t *testing.T) {
	cmds := DebugCommands(nil)
	cmds.Register("foo", func(t *Term, ctx callContext, args string) error { return fmt.Errorf("registered command") }, "foo command")
	cmd := cmds.Find("foo", noPrefix)

	err := cmd(nil, callContext{}, "")
	if err.Error() != "registered command" {
		t.Fatal("wrong command output")
	}

	cmd = cmds.Find("", noPrefix)
	err = cmd(nil, callContext{}, "")
	if err.Error() != "registered command" {
		t.Fatal("wrong command output")
	}
}

func TestCommandReplayWithoutPreviousCommand(t *testing.T) {
	var (
		cmds = DebugCommands(nil)
		cmd  = cmds.Find("", noPrefix)
		err  = cmd(nil, callContext{}, "")
	)

	if err != nil {
		t.Error("Null command not returned", err)
	}
}

func TestCommandThread(t *testing.T) {
	var (
		cmds = DebugCommands(nil)
		cmd  = cmds.Find("thread", noPrefix)
	)

	err := cmd(nil, callContext{}, "")
	if err == nil {
		t.Fatal("thread terminal command did not default")
	}

	if err.Error() != "you must specify a thread" {
		t.Fatal("wrong command output: ", err.Error())
	}
}

func TestExecuteFile(t *testing.T) {
	breakCount := 0
	traceCount := 0
	c := &Commands{
		client: nil,
		cmds: []command{
			{aliases: []string{"trace"}, cmdFn: func(t *Term, ctx callContext, args string) error {
				traceCount++
				return nil
			}},
			{aliases: []string{"break"}, cmdFn: func(t *Term, ctx callContext, args string) error {
				breakCount++
				return nil
			}},
		},
	}

	fixturesDir := test.FindFixturesDir()
	err := c.executeFile(nil, filepath.Join(fixturesDir, "bpfile"))
	if err != nil {
		t.Fatalf("executeFile: %v", err)
	}

	if breakCount != 1 || traceCount != 1 {
		t.Fatalf("Wrong counts break: %d trace: %d\n", breakCount, traceCount)
	}
}

func TestIssue354(t *testing.T) {
	printStack([]api.Stackframe{}, "")
	printStack([]api.Stackframe{{api.Location{PC: 0, File: "irrelevant.go", Line: 10, Function: nil}, nil, nil}}, "")
}

func TestIssue411(t *testing.T) {
	withTestTerminal("math", t, func(term *FakeTerminal) {
		term.MustExec("break math.go:8")
		term.MustExec("trace math.go:9")
		term.MustExec("continue")
		out := term.MustExec("next")
		if !strings.HasPrefix(out, "> main.main()") {
			t.Fatalf("Wrong output for next: <%s>", out)
		}
	})
}

func TestScopePrefix(t *testing.T) {
	const goroutinesLinePrefix = "  Goroutine "
	const goroutinesCurLinePrefix = "* Goroutine "
	withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) {
		term.MustExec("b stacktraceme")
		term.MustExec("continue")

		goroutinesOut := strings.Split(term.MustExec("goroutines"), "\n")
		agoroutines := []int{}
		curgid := -1

		for _, line := range goroutinesOut {
			iscur := strings.HasPrefix(line, goroutinesCurLinePrefix)
			if !iscur && !strings.HasPrefix(line, goroutinesLinePrefix) {
				continue
			}

			dash := strings.Index(line, " - ")
			if dash < 0 {
				continue
			}

			gid, err := strconv.Atoi(line[len(goroutinesLinePrefix):dash])
			if err != nil {
				continue
			}

			if iscur {
				curgid = gid
			}

			if idx := strings.Index(line, " main.agoroutine "); idx < 0 {
				continue
			}

			agoroutines = append(agoroutines, gid)
		}

		if len(agoroutines) != 10 {
			t.Fatalf("Output of goroutines did not have 10 goroutines stopped on main.agoroutine: %q", goroutinesOut)
		}

		if curgid < 0 {
			t.Fatalf("Could not find current goroutine in output of goroutines: %q", goroutinesOut)
		}

		seen := make([]bool, 10)
		for _, gid := range agoroutines {
			stackOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d stack", gid)), "\n")
			fid := -1
			for _, line := range stackOut {
				space := strings.Index(line, " ")
				if space < 0 {
					continue
				}
				curfid, err := strconv.Atoi(line[:space])
				if err != nil {
					continue
				}

				if idx := strings.Index(line, " main.agoroutine"); idx >= 0 {
					fid = curfid
					break
				}
			}
			if fid < 0 {
				t.Fatalf("Could not find frame for goroutine %d: %v", gid, stackOut)
			}
			term.AssertExec(fmt.Sprintf("goroutine %d frame %d locals", gid, fid), "")
			argsOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d frame %d args", gid, fid)), "\n")
			if len(argsOut) != 4 || argsOut[3] != "" {
				t.Fatalf("Wrong number of arguments in goroutine %d frame %d: %v", gid, fid, argsOut)
			}
			out := term.MustExec(fmt.Sprintf("goroutine %d frame %d p i", gid, fid))
			ival, err := strconv.Atoi(out[:len(out)-1])
			if err != nil {
				t.Fatalf("could not parse value %q of i for goroutine %d frame %d: %v", out, gid, fid, err)
			}
			seen[ival] = true
		}

		for i := range seen {
			if !seen[i] {
				t.Fatalf("goroutine %d not found", i)
			}
		}

		term.MustExec("c")

		term.AssertExecError("frame", "not enough arguments")
		term.AssertExecError("frame 1", "not enough arguments")
		term.AssertExecError("frame 1 goroutines", "command not available")
		term.AssertExecError("frame 1 goroutine", "no command passed to goroutine")
		term.AssertExecError(fmt.Sprintf("frame 1 goroutine %d", curgid), "no command passed to goroutine")
		term.AssertExecError(fmt.Sprintf("goroutine %d frame 10 locals", curgid), fmt.Sprintf("Frame 10 does not exist in goroutine %d", curgid))
		term.AssertExecError("goroutine 9000 locals", "Unknown goroutine 9000")

		term.AssertExecError("print n", "could not find symbol value for n")
		term.AssertExec("frame 1 print n", "3\n")
		term.AssertExec("frame 2 print n", "2\n")
		term.AssertExec("frame 3 print n", "1\n")
		term.AssertExec("frame 4 print n", "0\n")
		term.AssertExecError("frame 5 print n", "could not find symbol value for n")
	})
}

func TestOnPrefix(t *testing.T) {
	const prefix = "\ti: "
	withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) {
		term.MustExec("b agobp main.agoroutine")
		term.MustExec("on agobp print i")

		seen := make([]bool, 10)

		for {
			outstr, err := term.Exec("continue")
			if err != nil {
				if strings.Index(err.Error(), "exited") < 0 {
					t.Fatalf("Unexpected error executing 'continue': %v", err)
				}
				break
			}
			out := strings.Split(outstr, "\n")

			for i := range out {
				if !strings.HasPrefix(out[i], "\ti: ") {
					continue
				}
				id, err := strconv.Atoi(out[i][len(prefix):])
				if err != nil {
					continue
				}
				if seen[id] {
					t.Fatalf("Goroutine %d seen twice\n", id)
				}
				seen[id] = true
			}
		}

		for i := range seen {
			if !seen[i] {
				t.Fatalf("Goroutine %d not seen\n", i)
			}
		}
	})
}
<|endoftext|>


<commit_before>package tfconfig

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/hashicorp/hcl2/hcl"
)

// LoadModule reads the directory at the given path and attempts to interpret
// it as a Terraform module.
func LoadModule(dir string) (*Module, Diagnostics) {

	// For broad compatibility here we actually have two separate loader
	// codepaths. The main one uses the new HCL parser and API and is intended
	// for configurations from Terraform 0.12 onwards (though will work for
	// many older configurations too), but we'll also fall back on one that
	// uses the _old_ HCL implementation so we can deal with some edge-cases
	// that are not valid in new HCL.

	module, diags := loadModule(dir)
	if diags.HasErrors() {
		// Try using the legacy HCL parser and see if we fare better.
		legacyModule, legacyDiags := loadModuleLegacyHCL(dir)
		if !legacyDiags.HasErrors() {
			legacyModule.init(legacyDiags)
			return legacyModule, legacyDiags
		}
	}

	module.init(diags)
	return module, diags
}

func (m *Module) init(diags Diagnostics) {
	// Fill in any additional provider requirements that are implied by
	// resource configurations, to avoid the caller from needing to apply
	// this logic itself. Implied requirements don't have version constraints,
	// but we'll make sure the requirement value is still non-nil in this
	// case so callers can easily recognize it.
	for _, r := range m.ManagedResources {
		if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
			m.RequiredProviders[r.Provider.Name] = []string{}
		}
	}
	for _, r := range m.DataResources {
		if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
			m.RequiredProviders[r.Provider.Name] = []string{}
		}
	}

	// We redundantly also reference the diagnostics from inside the module
	// object, primarily so that we can easily included in JSON-serialized
	// versions of the module object.
	m.Diagnostics = diags
}

func dirFiles(dir string) (primary []string, diags hcl.Diagnostics) {
	infos, err := ioutil.ReadDir(dir)
	if err != nil {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Failed to read module directory",
			Detail:   fmt.Sprintf("Module directory %s does not exist or cannot be read.", dir),
		})
		return
	}

	var override []string
	for _, info := range infos {
		if info.IsDir() {
			// We only care about files
			continue
		}

		name := info.Name()
		ext := fileExt(name)
		if ext == "" || isIgnoredFile(name) {
			continue
		}

		baseName := name[:len(name)-len(ext)] // strip extension
		isOverride := baseName == "override" || strings.HasSuffix(baseName, "_override")

		fullPath := filepath.Join(dir, name)
		if isOverride {
			override = append(override, fullPath)
		} else {
			primary = append(primary, fullPath)
		}
	}

	// We are assuming that any _override files will be logically named,
	// and processing the files in alphabetical order. Primaries first, then overrides.
	primary = append(primary, override...)

	return
}

// fileExt returns the Terraform configuration extension of the given
// path, or a blank string if it is not a recognized extension.
func fileExt(path string) string {
	if strings.HasSuffix(path, ".tf") {
		return ".tf"
	} else if strings.HasSuffix(path, ".tf.json") {
		return ".tf.json"
	} else {
		return ""
	}
}

// isIgnoredFile returns true if the given filename (which must not have a
// directory path ahead of it) should be ignored as e.g. an editor swap file.
func isIgnoredFile(name string) bool {
	return strings.HasPrefix(name, ".") || // Unix-like hidden files
		strings.HasSuffix(name, "~") || // vim
		strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs
}
<commit_msg>Adding IsModuleDir function (#3)<commit_after>package tfconfig

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/hashicorp/hcl2/hcl"
)

// LoadModule reads the directory at the given path and attempts to interpret
// it as a Terraform module.
func LoadModule(dir string) (*Module, Diagnostics) {

	// For broad compatibility here we actually have two separate loader
	// codepaths. The main one uses the new HCL parser and API and is intended
	// for configurations from Terraform 0.12 onwards (though will work for
	// many older configurations too), but we'll also fall back on one that
	// uses the _old_ HCL implementation so we can deal with some edge-cases
	// that are not valid in new HCL.

	module, diags := loadModule(dir)
	if diags.HasErrors() {
		// Try using the legacy HCL parser and see if we fare better.
		legacyModule, legacyDiags := loadModuleLegacyHCL(dir)
		if !legacyDiags.HasErrors() {
			legacyModule.init(legacyDiags)
			return legacyModule, legacyDiags
		}
	}

	module.init(diags)
	return module, diags
}

// IsModuleDir checks if the given path contains terraform configuration files.
// This allows the caller to decide how to handle directories that do not have tf files.
func IsModuleDir(dir string) bool {
	primaryPaths, _ := dirFiles(dir)
	if len(primaryPaths) == 0 {
		return false
	}
	return true
}

func (m *Module) init(diags Diagnostics) {
	// Fill in any additional provider requirements that are implied by
	// resource configurations, to avoid the caller from needing to apply
	// this logic itself. Implied requirements don't have version constraints,
	// but we'll make sure the requirement value is still non-nil in this
	// case so callers can easily recognize it.
	for _, r := range m.ManagedResources {
		if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
			m.RequiredProviders[r.Provider.Name] = []string{}
		}
	}
	for _, r := range m.DataResources {
		if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
			m.RequiredProviders[r.Provider.Name] = []string{}
		}
	}

	// We redundantly also reference the diagnostics from inside the module
	// object, primarily so that we can easily included in JSON-serialized
	// versions of the module object.
	m.Diagnostics = diags
}

func dirFiles(dir string) (primary []string, diags hcl.Diagnostics) {
	infos, err := ioutil.ReadDir(dir)
	if err != nil {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Failed to read module directory",
			Detail:   fmt.Sprintf("Module directory %s does not exist or cannot be read.", dir),
		})
		return
	}

	var override []string
	for _, info := range infos {
		if info.IsDir() {
			// We only care about files
			continue
		}

		name := info.Name()
		ext := fileExt(name)
		if ext == "" || isIgnoredFile(name) {
			continue
		}

		baseName := name[:len(name)-len(ext)] // strip extension
		isOverride := baseName == "override" || strings.HasSuffix(baseName, "_override")

		fullPath := filepath.Join(dir, name)
		if isOverride {
			override = append(override, fullPath)
		} else {
			primary = append(primary, fullPath)
		}
	}

	// We are assuming that any _override files will be logically named,
	// and processing the files in alphabetical order. Primaries first, then overrides.
	primary = append(primary, override...)

	return
}

// fileExt returns the Terraform configuration extension of the given
// path, or a blank string if it is not a recognized extension.
func fileExt(path string) string {
	if strings.HasSuffix(path, ".tf") {
		return ".tf"
	} else if strings.HasSuffix(path, ".tf.json") {
		return ".tf.json"
	} else {
		return ""
	}
}

// isIgnoredFile returns true if the given filename (which must not have a
// directory path ahead of it) should be ignored as e.g. an editor swap file.
func isIgnoredFile(name string) bool {
	return strings.HasPrefix(name, ".") || // Unix-like hidden files
		strings.HasSuffix(name, "~") || // vim
		strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs
}
<|endoftext|>


<commit_before>// Copyright 2020 DSR Corporation
//
// 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 x509

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"strings"

	"github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types"
)

type Certificate struct {
	Issuer         string
	SerialNumber   string
	Subject        string
	SubjectAsText  string
	SubjectKeyID   string
	AuthorityKeyID string
	Certificate    *x509.Certificate
}

func DecodeX509Certificate(pemCertificate string) (*Certificate, error) {
	block, _ := pem.Decode([]byte(pemCertificate))
	if block == nil {
		return nil, types.NewErrInvalidCertificate("Could not decode pem certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, types.NewErrInvalidCertificate(fmt.Sprintf("Could not parse certificate: %v", err.Error()))
	}

	certificate := Certificate{
		Issuer:         cert.Issuer.String(),
		SerialNumber:   cert.SerialNumber.String(),
		SubjectAsText:  ToSubjectAsText(cert.Subject.String()),
		SubjectKeyID:   BytesToHex(cert.SubjectKeyId),
		AuthorityKeyID: BytesToHex(cert.AuthorityKeyId),
		Certificate:    cert,
	}

	certificate = PatchCertificate(certificate)

	return &certificate, nil
}

func ToSubjectAsText(subject string) string {
	oldVIDKey := "1.3.6.1.4.1.37244.2.1"
	oldPIDKey := "1.3.6.1.4.1.37244.2.2"

	newVIDKey := "vid"
	newPIDKey := "pid"

	subjectAsText := subject
	subjectAsText = FormatOID(subjectAsText, oldVIDKey, newVIDKey)
	subjectAsText = FormatOID(subjectAsText, oldPIDKey, newPIDKey)

	return subjectAsText
}

func FormatOID(header, oldKey, newKey string) string {
	subjectValues := strings.Split(header, ",")

	// When translating a string number into a hexadecimal number,
	// we must take 8 numbers of this string number from the end so that it needs to fit into an integer number.
	hexStringIntegerLength := 8
	for index, value := range subjectValues {
		if strings.HasPrefix(value, oldKey) {
			// get value from header
			value = value[len(value)-hexStringIntegerLength:]

			decoded, _ := hex.DecodeString(value)

			subjectValues[index] = fmt.Sprintf("%s=0x%s", newKey, decoded)
		}
	}

	return strings.Join(subjectValues, ",")
}

func StringtoBase64(subject string) string {
	return base64.StdEncoding.EncodeToString([]byte(subject))
}

func BytesToHex(bytes []byte) string {
	if bytes == nil {
		return ""
	}

	bytesHex := make([]string, len(bytes))
	for i, b := range bytes {
		bytesHex[i] = fmt.Sprintf("%02X", b)
	}

	return strings.Join(bytesHex, ":")
}

func (c Certificate) Verify(parent *Certificate) error {
	roots := x509.NewCertPool()
	roots.AddCert(parent.Certificate)

	opts := x509.VerifyOptions{Roots: roots}

	if _, err := c.Certificate.Verify(opts); err != nil {
		return types.NewErrInvalidCertificate(fmt.Sprintf("Certificate verification failed. Error: %v", err))
	}

	return nil
}

func (c Certificate) IsSelfSigned() bool {
	if len(c.AuthorityKeyID) > 0 {
		return c.Issuer == c.Subject && c.AuthorityKeyID == c.SubjectKeyID
	}

	return c.Issuer == c.Subject
}
<commit_msg>Change name function StringtoBase64 to ToBase64String<commit_after>// Copyright 2020 DSR Corporation
//
// 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 x509

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"strings"

	"github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types"
)

type Certificate struct {
	Issuer         string
	SerialNumber   string
	Subject        string
	SubjectAsText  string
	SubjectKeyID   string
	AuthorityKeyID string
	Certificate    *x509.Certificate
}

func DecodeX509Certificate(pemCertificate string) (*Certificate, error) {
	block, _ := pem.Decode([]byte(pemCertificate))
	if block == nil {
		return nil, types.NewErrInvalidCertificate("Could not decode pem certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, types.NewErrInvalidCertificate(fmt.Sprintf("Could not parse certificate: %v", err.Error()))
	}

	certificate := Certificate{
		Issuer:         ToBase64String(cert.Issuer.String()),
		SerialNumber:   cert.SerialNumber.String(),
		Subject:        ToBase64String(cert.Subject.String()),
		SubjectAsText:  ToSubjectAsText(cert.Subject.String()),
		SubjectKeyID:   BytesToHex(cert.SubjectKeyId),
		AuthorityKeyID: BytesToHex(cert.AuthorityKeyId),
		Certificate:    cert,
	}

	return &certificate, nil
}

func ToSubjectAsText(subject string) string {
	oldVIDKey := "1.3.6.1.4.1.37244.2.1"
	oldPIDKey := "1.3.6.1.4.1.37244.2.2"

	newVIDKey := "vid"
	newPIDKey := "pid"

	subjectAsText := subject
	subjectAsText = FormatOID(subjectAsText, oldVIDKey, newVIDKey)
	subjectAsText = FormatOID(subjectAsText, oldPIDKey, newPIDKey)

	return subjectAsText
}

// This function is needed to patch the Issuer/Subject(vid/pid) field of certificate to hex format.
// https://github.com/zigbee-alliance/distributed-compliance-ledger/issues/270
func FormatOID(header, oldKey, newKey string) string {
	subjectValues := strings.Split(header, ",")

	// When translating a string number into a hexadecimal number,
	// we must take 8 numbers of this string number from the end so that it needs to fit into an integer number.
	hexStringIntegerLength := 8
	for index, value := range subjectValues {
		if strings.HasPrefix(value, oldKey) {
			// get value from header
			value = value[len(value)-hexStringIntegerLength:]

			decoded, _ := hex.DecodeString(value)

			subjectValues[index] = fmt.Sprintf("%s=0x%s", newKey, decoded)
		}
	}

	return strings.Join(subjectValues, ",")
}

func ToBase64String(subject string) string {
	return base64.StdEncoding.EncodeToString([]byte(subject))
}

func BytesToHex(bytes []byte) string {
	if bytes == nil {
		return ""
	}

	bytesHex := make([]string, len(bytes))
	for i, b := range bytes {
		bytesHex[i] = fmt.Sprintf("%02X", b)
	}

	return strings.Join(bytesHex, ":")
}

func (c Certificate) Verify(parent *Certificate) error {
	roots := x509.NewCertPool()
	roots.AddCert(parent.Certificate)

	opts := x509.VerifyOptions{Roots: roots}

	if _, err := c.Certificate.Verify(opts); err != nil {
		return types.NewErrInvalidCertificate(fmt.Sprintf("Certificate verification failed. Error: %v", err))
	}

	return nil
}

func (c Certificate) IsSelfSigned() bool {
	if len(c.AuthorityKeyID) > 0 {
		return c.Issuer == c.Subject && c.AuthorityKeyID == c.SubjectKeyID
	}

	return c.Issuer == c.Subject
}
<|endoftext|>


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

package codec

import (
	"bytes"
	"runtime"
	"unsafe"

	"github.com/juju/errors"
)

const (
	encGroupSize     = 8
	avgEncGroupCount = 20
	encMarker        = byte(0xFF)
	encPad           = byte(0x0)
)

// EncodeBytes guarantees the encoded value is in ascending order for comparison,
// encoding with the following rule:
//  [group1][marker1]...[groupN][markerN]
//  group is 8 bytes sclice which maybe padding with 0.
//  marker is 0xFF - appending 0 number
// For example:
//   [] -> [1 0 0 0 0 0 0 0 0 247]
//   [1, 2, 3] -> [1 1 2 3 0 0 0 0 0 250]
//   [1, 2, 3, 0] -> [1 1 2 3 0 0 0 0 0 251]
//   [1, 2, 3, 4, 5, 6, 7, 8] -> [1 1 2 3 4 5 6 7 8 255 0 0 0 0 0 0 0 0 247]
// Refer: https://github.com/facebook/mysql-5.6/wiki/MyRocks-record-format#memcomparable-format
func EncodeBytes(b []byte, data []byte) []byte {
	// Allocate more space to avoid unnecessary slice growing.
	// Assume that the byte slice size is about 20*8 = 160 bytes.
	dl := len(data)
	bs := reallocBytes(b, dl+avgEncGroupCount)
	for idx := 0; idx <= dl; idx += encGroupSize {
		remain := dl - idx
		padCount := 0
		if remain >= encGroupSize {
			bs = append(bs, data[idx:idx+encGroupSize]...)
		} else {
			padCount = encGroupSize - remain
			bs = append(bs, data[idx:]...)
			bs = append(bs, make([]byte, padCount)...)
		}

		marker := encMarker - byte(padCount)
		bs = append(bs, marker)
	}

	return bs
}

func decodeBytes(b []byte, reverse bool) ([]byte, []byte, error) {
	if len(b) < encGroupSize+1 {
		return nil, nil, errors.New("insufficient bytes to decode value")
	}

	data := []byte{}
	for {
		groupBytes := b[:encGroupSize+1]
		if reverse {
			reverseBytes(groupBytes)
		}

		group := groupBytes[:encGroupSize]
		marker := groupBytes[encGroupSize]

		// Check validity of marker.
		padCount := encMarker - marker
		realGroupSize := encGroupSize - padCount
		if realGroupSize < 0 {
			return nil, nil, errors.Errorf("invalid marker byte, group %v", group)
		}

		data = append(data, group[:realGroupSize]...)
		b = b[encGroupSize+1:]

		if marker != encMarker {
			// Check validity of padding bytes.
			if bytes.Count(group[realGroupSize:], []byte{encPad}) != int(padCount) {
				return nil, nil, errors.Errorf("invalid padding byte, group %v", group)
			}

			break
		}
	}

	return b, data, nil
}

// DecodeBytes decodes bytes which is encoded by EncodeBytes before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytes(b []byte) ([]byte, []byte, error) {
	return decodeBytes(b, false)
}

// EncodeBytesDesc first encodes bytes using EncodeBytes, then bitwise reverses
// encoded value to guarentee the encoded value is in descending order for comparison。
func EncodeBytesDesc(b []byte, data []byte) []byte {
	n := len(b)
	b = EncodeBytes(b, data)
	reverseBytes(b[n:])
	return b
}

// DecodeBytesDesc decodes bytes which is encoded by EncodeBytesDesc before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytesDesc(b []byte) ([]byte, []byte, error) {
	return decodeBytes(b, true)
}

// See https://golang.org/src/crypto/cipher/xor.go
const wordSize = int(unsafe.Sizeof(uintptr(0)))
const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"

func fastReverseBytes(b []byte) {
	n := len(b)
	w := n / wordSize
	if w > 0 {
		bw := *(*[]uintptr)(unsafe.Pointer(&b))
		for i := 0; i < w; i++ {
			bw[i] = ^bw[i]
		}
	}

	for i := w * wordSize; i < n; i++ {
		b[i] = ^b[i]
	}
}

func safeReverseBytes(b []byte) {
	for i := range b {
		b[i] = ^b[i]
	}
}

func reverseBytes(b []byte) {
	if supportsUnaligned {
		fastReverseBytes(b)
		return
	}

	safeReverseBytes(b)
}

// like realloc.
func reallocBytes(b []byte, n int) []byte {
	if cap(b) < n {
		bs := make([]byte, len(b), len(b)+n)
		copy(bs, b)
		return bs
	}

	// slice b has capability to store n bytes
	return b
}
<commit_msg>util/codec: fix type and tiny update comment.<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package codec

import (
	"bytes"
	"runtime"
	"unsafe"

	"github.com/juju/errors"
)

const (
	encGroupSize     = 8
	avgEncGroupCount = 20
	encMarker        = byte(0xFF)
	encPad           = byte(0x0)
)

// EncodeBytes guarantees the encoded value is in ascending order for comparison,
// encoding with the following rule:
//  [group1][marker1]...[groupN][markerN]
//  group is 8 bytes slice which is padding with 0.
//  marker is `0xFF - padding 0 count`
// For example:
//   [] -> [1 0 0 0 0 0 0 0 0 247]
//   [1, 2, 3] -> [1 1 2 3 0 0 0 0 0 250]
//   [1, 2, 3, 0] -> [1 1 2 3 0 0 0 0 0 251]
//   [1, 2, 3, 4, 5, 6, 7, 8] -> [1 1 2 3 4 5 6 7 8 255 0 0 0 0 0 0 0 0 247]
// Refer: https://github.com/facebook/mysql-5.6/wiki/MyRocks-record-format#memcomparable-format
func EncodeBytes(b []byte, data []byte) []byte {
	// Allocate more space to avoid unnecessary slice growing.
	// Assume that the byte slice size is about 20*8 = 160 bytes.
	dl := len(data)
	bs := reallocBytes(b, dl+avgEncGroupCount)
	for idx := 0; idx <= dl; idx += encGroupSize {
		remain := dl - idx
		padCount := 0
		if remain >= encGroupSize {
			bs = append(bs, data[idx:idx+encGroupSize]...)
		} else {
			padCount = encGroupSize - remain
			bs = append(bs, data[idx:]...)
			bs = append(bs, make([]byte, padCount)...)
		}

		marker := encMarker - byte(padCount)
		bs = append(bs, marker)
	}

	return bs
}

func decodeBytes(b []byte, reverse bool) ([]byte, []byte, error) {
	if len(b) < encGroupSize+1 {
		return nil, nil, errors.New("insufficient bytes to decode value")
	}

	data := []byte{}
	for {
		groupBytes := b[:encGroupSize+1]
		if reverse {
			reverseBytes(groupBytes)
		}

		group := groupBytes[:encGroupSize]
		marker := groupBytes[encGroupSize]

		// Check validity of marker.
		padCount := encMarker - marker
		realGroupSize := encGroupSize - padCount
		if realGroupSize < 0 {
			return nil, nil, errors.Errorf("invalid marker byte, group %v", group)
		}

		data = append(data, group[:realGroupSize]...)
		b = b[encGroupSize+1:]

		if marker != encMarker {
			// Check validity of padding bytes.
			if bytes.Count(group[realGroupSize:], []byte{encPad}) != int(padCount) {
				return nil, nil, errors.Errorf("invalid padding byte, group %v", group)
			}

			break
		}
	}

	return b, data, nil
}

// DecodeBytes decodes bytes which is encoded by EncodeBytes before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytes(b []byte) ([]byte, []byte, error) {
	return decodeBytes(b, false)
}

// EncodeBytesDesc first encodes bytes using EncodeBytes, then bitwise reverses
// encoded value to guarentee the encoded value is in descending order for comparison.
func EncodeBytesDesc(b []byte, data []byte) []byte {
	n := len(b)
	b = EncodeBytes(b, data)
	reverseBytes(b[n:])
	return b
}

// DecodeBytesDesc decodes bytes which is encoded by EncodeBytesDesc before,
// returns the leftover bytes and decoded value if no error.
func DecodeBytesDesc(b []byte) ([]byte, []byte, error) {
	return decodeBytes(b, true)
}

// See https://golang.org/src/crypto/cipher/xor.go
const wordSize = int(unsafe.Sizeof(uintptr(0)))
const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"

func fastReverseBytes(b []byte) {
	n := len(b)
	w := n / wordSize
	if w > 0 {
		bw := *(*[]uintptr)(unsafe.Pointer(&b))
		for i := 0; i < w; i++ {
			bw[i] = ^bw[i]
		}
	}

	for i := w * wordSize; i < n; i++ {
		b[i] = ^b[i]
	}
}

func safeReverseBytes(b []byte) {
	for i := range b {
		b[i] = ^b[i]
	}
}

func reverseBytes(b []byte) {
	if supportsUnaligned {
		fastReverseBytes(b)
		return
	}

	safeReverseBytes(b)
}

// like realloc.
func reallocBytes(b []byte, n int) []byte {
	if cap(b) < n {
		bs := make([]byte, len(b), len(b)+n)
		copy(bs, b)
		return bs
	}

	// slice b has capability to store n bytes
	return b
}
<|endoftext|>


<commit_before>package main

import (
	"regexp"
	"strconv"
	"strings"
)

func main() {}

func withRegexp(query map[string]string) bool {
	for key := range query {
		a, _ := regexp.MatchString("(?i)^a[0-9]{1,3}$", key)
		if a {
			return true
		}
		pv, _ := regexp.MatchString("(?i)^pv[0-9]{1,3}$", key)
		if pv {
			return true
		}
		pu, _ := regexp.MatchString("(?i)^pu[0-9]{1,3}$", key)
		if pu {
			return true
		}
		sv, _ := regexp.MatchString("(?i)^sv[0-9]{1,3}$", key)
		if sv {
			return true
		}
	}
	return false
}

func noooRegexp(query map[string]string) bool {
	for key := range query {
		key := strings.TrimSpace(key)
		a := isValid(key, "a")
		if a {
			return true
		}
		pv := isValid(key, "pv")
		if pv {
			return true
		}
		pu := isValid(key, "pu")
		if pu {
			return true
		}
		sv := isValid(key, "sv")
		if sv {
			return true
		}
	}
	return false
}

func isValid(key, prefix string) bool {
	if strings.HasPrefix(key, prefix) {
		rem := key[len(prefix):]
		if _, err := strconv.ParseInt(rem, 10, 64); err != nil {
			return false
		}
		return true
	}
	return false
}
<commit_msg>benchregexp: fix isValid for negative numbers<commit_after>package main

import (
	"regexp"
	"strconv"
	"strings"
)

func main() {}

func withRegexp(query map[string]string) bool {
	for key := range query {
		a, _ := regexp.MatchString("(?i)^a[0-9]{1,3}$", key)
		if a {
			return true
		}
		pv, _ := regexp.MatchString("(?i)^pv[0-9]{1,3}$", key)
		if pv {
			return true
		}
		pu, _ := regexp.MatchString("(?i)^pu[0-9]{1,3}$", key)
		if pu {
			return true
		}
		sv, _ := regexp.MatchString("(?i)^sv[0-9]{1,3}$", key)
		if sv {
			return true
		}
	}
	return false
}

func noooRegexp(query map[string]string) bool {
	for key := range query {
		key := strings.TrimSpace(key)
		a := isValid(key, "a")
		if a {
			return true
		}
		pv := isValid(key, "pv")
		if pv {
			return true
		}
		pu := isValid(key, "pu")
		if pu {
			return true
		}
		sv := isValid(key, "sv")
		if sv {
			return true
		}
	}
	return false
}

func isValid(key, prefix string) bool {
	if strings.HasPrefix(key, prefix) {
		rem := key[len(prefix):]
		nbr, err := strconv.ParseInt(rem, 10, 64)
		if err != nil {
			return false
		}
		if nbr < 0 {
			return false
		}
		return true
	}
	return false
}
<|endoftext|>


<commit_before>// Package influx is a go-metrics to influx DB reporter implementation.
package influx

import (
	"context"
	"fmt"
	"io/ioutil"
	"time"

	"github.com/Sirupsen/logrus"
	client "github.com/influxdata/influxdb/client/v2"
	metrics "github.com/rcrowley/go-metrics"
)

// Reporter holds configuration of go-metrics influx exporter. It can be
// configured only be public setter methods.
type Reporter struct {
	registry  metrics.Registry
	interval  time.Duration
	url       string
	database  string
	tags      map[string]string
	precision string
	ctx       context.Context
	log       logrus.FieldLogger
}

// NewReporter creates a new instance of influx metrcs reporter. It may be
// further configured with helper methods. It will not start exporting metrics
// until Run() is called.
func NewReporter(registry metrics.Registry, interval time.Duration, url string, db string) *Reporter {
	return &Reporter{
		registry:  registry,
		interval:  interval,
		url:       url,
		database:  db,
		tags:      nil,
		precision: "s",
		ctx:       context.Background(),
		log: &logrus.Logger{
			Out:       ioutil.Discard,
			Formatter: new(logrus.TextFormatter),
			Hooks:     make(logrus.LevelHooks),
			Level:     logrus.PanicLevel,
		},
	}
}

// Tags sets a set of tags that will be assiciated with each influx data point
// written by this exporter.
func (r *Reporter) Tags(tags map[string]string) *Reporter {
	r.tags = tags
	return r
}

// Precision changes the timestamp precision used in reported data points. By
// default timestamps are reported with a seconds precision. Having higher than
// seconds precision should be useful only when export interval is less
// than a second.
func (r *Reporter) Precision(precision string) *Reporter {
	r.precision = precision
	return r
}

// Context assigns a context to this reporter. Context is only used to stop
// reporter Run() method.
func (r *Reporter) Context(ctx context.Context) *Reporter {
	r.ctx = ctx
	return r
}

// Logger sets optional logrus logger for error reporting.
func (r *Reporter) Logger(log logrus.FieldLogger) *Reporter {
	r.log = log
	return r
}

// Run starts exporting metrics to influx DB. This method will block until
// context associated with this reporter is stopper (of forever if contex is
// not set).
func (r *Reporter) Run() {
	c, err := client.NewHTTPClient(client.HTTPConfig{
		Addr:    r.url,
		Timeout: r.interval,
	})
	if err != nil {
		r.log.WithField("url", r.url).WithError(err).Error("creating new influx client")
		return
	}

	ticker := time.NewTicker(r.interval)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			r.report(c)
		case <-r.ctx.Done():
			return
		}
	}
}

// report send current snapshot of metrics registry to influx DB.
func (r *Reporter) report(c client.Client) {
	bp, err := client.NewBatchPoints(client.BatchPointsConfig{
		Database:  r.database,
		Precision: r.precision,
	})
	if err != nil {
		r.log.WithFields(logrus.Fields{
			"db":        r.database,
			"precision": r.precision,
		}).WithError(err).Error("creating influx batch points")
		return
	}

	now := time.Now()
	r.registry.Each(func(name string, i interface{}) {
		var point *client.Point
		var err error

		switch metric := i.(type) {
		case metrics.Counter:
			point, err = client.NewPoint(
				fmt.Sprintf("%s.count", name),
				r.tags,
				map[string]interface{}{
					"value": metric.Count(),
				},
				now,
			)
		case metrics.Gauge:
			point, err = client.NewPoint(
				fmt.Sprintf("%s.gauge", name),
				r.tags,
				map[string]interface{}{
					"value": metric.Value(),
				},
				now,
			)
		case metrics.GaugeFloat64:
			point, err = client.NewPoint(
				fmt.Sprintf("%s.gauge", name),
				r.tags,
				map[string]interface{}{
					"value": metric.Value(),
				},
				now,
			)
		case metrics.Histogram:
			ms := metric.Snapshot()
			ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
			point, err = client.NewPoint(
				fmt.Sprintf("%s.histogram", name),
				r.tags,
				map[string]interface{}{
					"count":    ms.Count(),
					"max":      ms.Max(),
					"mean":     ms.Mean(),
					"min":      ms.Min(),
					"stddev":   ms.StdDev(),
					"variance": ms.Variance(),
					"p50":      ps[0],
					"p75":      ps[1],
					"p95":      ps[2],
					"p99":      ps[3],
					"p999":     ps[4],
					"p9999":    ps[5],
				},
				now,
			)
		case metrics.Meter:
			ms := metric.Snapshot()
			point, err = client.NewPoint(
				fmt.Sprintf("%s.meter", name),
				r.tags,
				map[string]interface{}{
					"count": ms.Count(),
					"m1":    ms.Rate1(),
					"m5":    ms.Rate5(),
					"m15":   ms.Rate15(),
					"mean":  ms.RateMean(),
				},
				now,
			)
		case metrics.Timer:
			ms := metric.Snapshot()
			ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
			point, err = client.NewPoint(
				fmt.Sprintf("%s.timer", name),
				r.tags,
				map[string]interface{}{
					"count":    ms.Count(),
					"max":      ms.Max(),
					"mean":     ms.Mean(),
					"min":      ms.Min(),
					"stddev":   ms.StdDev(),
					"variance": ms.Variance(),
					"p50":      ps[0],
					"p75":      ps[1],
					"p95":      ps[2],
					"p99":      ps[3],
					"p999":     ps[4],
					"p9999":    ps[5],
					"m1":       ms.Rate1(),
					"m5":       ms.Rate5(),
					"m15":      ms.Rate15(),
					"meanrate": ms.RateMean(),
				},
				now,
			)
		default:
			// Unhandled metric type
			return
		}
		if err != nil {
			r.log.WithField("name", name).WithError(err).Error("creating influx data point")
			return
		}
		bp.AddPoint(point)
	})

	if len(bp.Points()) == 0 {
		return
	}
	if err = c.Write(bp); err != nil {
		r.log.WithError(err).Error("writing data points to influx")
	}
}
<commit_msg>Drop metric type suffix from measurement name, include diff value for counters<commit_after>// Package influx is a go-metrics to influx DB reporter implementation.
package influx

import (
	"context"
	"io/ioutil"
	"time"

	"github.com/Sirupsen/logrus"
	client "github.com/influxdata/influxdb/client/v2"
	metrics "github.com/rcrowley/go-metrics"
)

// Reporter holds configuration of go-metrics influx exporter. It can be
// configured only be public setter methods.
type Reporter struct {
	registry  metrics.Registry
	interval  time.Duration
	url       string
	database  string
	tags      map[string]string
	precision string
	ctx       context.Context
	log       logrus.FieldLogger

	lastCounter map[string]int64
}

// NewReporter creates a new instance of influx metrcs reporter. It may be
// further configured with helper methods. It will not start exporting metrics
// until Run() is called.
func NewReporter(registry metrics.Registry, interval time.Duration, url string, db string) *Reporter {
	return &Reporter{
		registry:  registry,
		interval:  interval,
		url:       url,
		database:  db,
		tags:      nil,
		precision: "s",
		ctx:       context.Background(),
		log: &logrus.Logger{
			Out:       ioutil.Discard,
			Formatter: new(logrus.TextFormatter),
			Hooks:     make(logrus.LevelHooks),
			Level:     logrus.PanicLevel,
		},
		lastCounter: make(map[string]int64),
	}
}

// Tags sets a set of tags that will be assiciated with each influx data point
// written by this exporter.
func (r *Reporter) Tags(tags map[string]string) *Reporter {
	r.tags = tags
	return r
}

// Precision changes the timestamp precision used in reported data points. By
// default timestamps are reported with a seconds precision. Having higher than
// seconds precision should be useful only when export interval is less
// than a second.
func (r *Reporter) Precision(precision string) *Reporter {
	r.precision = precision
	return r
}

// Context assigns a context to this reporter. Context is only used to stop
// reporter Run() method.
func (r *Reporter) Context(ctx context.Context) *Reporter {
	r.ctx = ctx
	return r
}

// Logger sets optional logrus logger for error reporting.
func (r *Reporter) Logger(log logrus.FieldLogger) *Reporter {
	r.log = log
	return r
}

// Run starts exporting metrics to influx DB. This method will block until
// context associated with this reporter is stopper (of forever if contex is
// not set).
func (r *Reporter) Run() {
	c, err := client.NewHTTPClient(client.HTTPConfig{
		Addr:    r.url,
		Timeout: r.interval,
	})
	if err != nil {
		r.log.WithField("url", r.url).WithError(err).Error("creating new influx client")
		return
	}

	ticker := time.NewTicker(r.interval)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			r.report(c)
		case <-r.ctx.Done():
			return
		}
	}
}

// report send current snapshot of metrics registry to influx DB.
func (r *Reporter) report(c client.Client) {
	bp, err := client.NewBatchPoints(client.BatchPointsConfig{
		Database:  r.database,
		Precision: r.precision,
	})
	if err != nil {
		r.log.WithFields(logrus.Fields{
			"db":        r.database,
			"precision": r.precision,
		}).WithError(err).Error("creating influx batch points")
		return
	}

	now := time.Now()
	r.registry.Each(func(name string, i interface{}) {
		var point *client.Point
		var err error

		switch metric := i.(type) {
		case metrics.Counter:
			count := metric.Count()
			diff := count - r.lastCounter[name]
			r.lastCounter[name] = count
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"count": count,
					"diff":  diff,
				},
				now,
			)
		case metrics.Gauge:
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"value": metric.Value(),
				},
				now,
			)
		case metrics.GaugeFloat64:
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"value": metric.Value(),
				},
				now,
			)
		case metrics.Histogram:
			ms := metric.Snapshot()
			ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"count":    ms.Count(),
					"max":      ms.Max(),
					"mean":     ms.Mean(),
					"min":      ms.Min(),
					"stddev":   ms.StdDev(),
					"variance": ms.Variance(),
					"p50":      ps[0],
					"p75":      ps[1],
					"p95":      ps[2],
					"p99":      ps[3],
					"p999":     ps[4],
					"p9999":    ps[5],
				},
				now,
			)
		case metrics.Meter:
			ms := metric.Snapshot()
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"count": ms.Count(),
					"m1":    ms.Rate1(),
					"m5":    ms.Rate5(),
					"m15":   ms.Rate15(),
					"mean":  ms.RateMean(),
				},
				now,
			)
		case metrics.Timer:
			ms := metric.Snapshot()
			ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
			point, err = client.NewPoint(
				name,
				r.tags,
				map[string]interface{}{
					"count":    ms.Count(),
					"max":      ms.Max(),
					"mean":     ms.Mean(),
					"min":      ms.Min(),
					"stddev":   ms.StdDev(),
					"variance": ms.Variance(),
					"p50":      ps[0],
					"p75":      ps[1],
					"p95":      ps[2],
					"p99":      ps[3],
					"p999":     ps[4],
					"p9999":    ps[5],
					"m1":       ms.Rate1(),
					"m5":       ms.Rate5(),
					"m15":      ms.Rate15(),
					"meanrate": ms.RateMean(),
				},
				now,
			)
		default:
			// Unhandled metric type
			return
		}
		if err != nil {
			r.log.WithField("name", name).WithError(err).Error("creating influx data point")
			return
		}
		bp.AddPoint(point)
	})

	if len(bp.Points()) == 0 {
		return
	}
	if err = c.Write(bp); err != nil {
		r.log.WithError(err).Error("writing data points to influx")
	}
}
<|endoftext|>