<commit_before>package warden

import (
	"bufio"
	"code.google.com/p/goprotobuf/proto"
	"errors"
	"fmt"
	"net"
	"strconv"
	"sync"
)

type Connection struct {
	conn      net.Conn
	read      *bufio.Reader
	writeLock sync.Mutex

	disconnected chan bool
}

type WardenError struct {
	Message   string
	Data      string
	Backtrace []string
}

func (e *WardenError) Error() string {
	return e.Message
}

func Connect(socket_path string) (*Connection, error) {
	conn, err := net.Dial("unix", socket_path)
	if err != nil {
		return nil, err
	}

	return NewConnection(conn), nil
}

func NewConnection(conn net.Conn) *Connection {
	return &Connection{
		conn: conn,
		read: bufio.NewReader(conn),

		// buffer size of 1 so that read and write errors
		// can both send without blocking
		disconnected: make(chan bool, 1),
	}
}

func (c *Connection) Close() {
	c.conn.Close()
}

func (c *Connection) Create() (*CreateResponse, error) {
	res, err := c.roundTrip(&CreateRequest{}, &CreateResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*CreateResponse), nil
}

func (c *Connection) Destroy(handle string) (*DestroyResponse, error) {
	res, err := c.roundTrip(
		&DestroyRequest{Handle: proto.String(handle)},
		&DestroyResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*DestroyResponse), nil
}

func (c *Connection) Spawn(handle, script string) (*SpawnResponse, error) {
	res, err := c.roundTrip(
		&SpawnRequest{
			Handle: proto.String(handle),
			Script: proto.String(script),
		},
		&SpawnResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*SpawnResponse), nil
}

func (c *Connection) Run(handle, script string) (*RunResponse, error) {
	res, err := c.roundTrip(
		&RunRequest{
			Handle: proto.String(handle),
			Script: proto.String(script),
		},
		&RunResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*RunResponse), nil
}

func (c *Connection) Stream(handle string, jobId uint32) (chan *StreamResponse, error) {
	err := c.sendMessage(
		&StreamRequest{
			Handle: proto.String(handle),
			JobId:  proto.Uint32(jobId),
		},
	)

	if err != nil {
		return nil, err
	}

	responses := make(chan *StreamResponse)

	go func() {
		for {
			resMsg, err := c.readResponse(&StreamResponse{})
			if err != nil {
				close(responses)
				break
			}

			response := resMsg.(*StreamResponse)

			responses <- response

			if response.ExitStatus != nil {
				close(responses)
				break
			}
		}
	}()

	return responses, nil
}

func (c *Connection) NetIn(handle string) (*NetInResponse, error) {
	res, err := c.roundTrip(
		&NetInRequest{Handle: proto.String(handle)},
		&NetInResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*NetInResponse), nil
}

func (c *Connection) CopyIn(handle, src, dst string) (*CopyInResponse, error) {
	res, err := c.roundTrip(
		&CopyInRequest{
			Handle:  proto.String(handle),
			SrcPath: proto.String(src),
			DstPath: proto.String(dst),
		},
		&CopyInResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*CopyInResponse), nil
}

func (c *Connection) List() (*ListResponse, error) {
	res, err := c.roundTrip(&ListRequest{}, &ListResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*ListResponse), nil
}

func (c *Connection) Info(handle string) (*InfoResponse, error) {
	res, err := c.roundTrip(&InfoRequest{
		Handle: proto.String(handle),
	}, &InfoResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*InfoResponse), nil
}

func (c *Connection) roundTrip(request proto.Message, response proto.Message) (proto.Message, error) {
	err := c.sendMessage(request)
	if err != nil {
		return nil, err
	}

	resp, err := c.readResponse(response)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (c *Connection) sendMessage(req proto.Message) error {
	c.writeLock.Lock()
	defer c.writeLock.Unlock()

	request, err := proto.Marshal(req)
	if err != nil {
		return err
	}

	msg := &Message{
		Type:    Message_Type(message2type(req)).Enum(),
		Payload: request,
	}

	data, err := proto.Marshal(msg)
	if err != nil {
		return err
	}

	_, err = c.conn.Write(
		[]byte(
			fmt.Sprintf(
				"%d\r\n%s\r\n",
				len(data),
				data,
			),
		),
	)

	if err != nil {
		c.disconnected <- true
		return err
	}

	return nil
}

func (c *Connection) readResponse(response proto.Message) (proto.Message, error) {
	payload, err := c.readPayload()
	if err != nil {
		c.disconnected <- true
		return nil, err
	}

	message := &Message{}
	err = proto.Unmarshal(payload, message)
	if err != nil {
		return nil, err
	}

	// error response from server
	if message.GetType() == Message_Type(1) {
		errorResponse := &ErrorResponse{}
		err = proto.Unmarshal(message.Payload, errorResponse)
		if err != nil {
			return nil, errors.New("error unmarshalling error!")
		}

		return nil, &WardenError{
			Message:   errorResponse.GetMessage(),
			Data:      errorResponse.GetData(),
			Backtrace: errorResponse.GetBacktrace(),
		}
	}

	response_type := Message_Type(message2type(response))
	if message.GetType() != response_type {
		return nil, errors.New(
			fmt.Sprintf(
				"expected message type %s, got %s\n",
				response_type.String(),
				message.GetType().String(),
			),
		)
	}

	err = proto.Unmarshal(message.GetPayload(), response)
	return response, err
}

func (c *Connection) readPayload() ([]byte, error) {
	msgHeader, err := c.read.ReadBytes('\n')
	if err != nil {
		return nil, err
	}

	msgLen, err := strconv.ParseUint(string(msgHeader[0:len(msgHeader)-2]), 10, 0)
	if err != nil {
		return nil, err
	}

	payload, err := readNBytes(int(msgLen), c.read)
	if err != nil {
		return nil, err
	}

	_, err = readNBytes(2, c.read) // CRLN
	if err != nil {
		return nil, err
	}

	return payload, err
}

func message2type(msg proto.Message) int32 {
	switch msg.(type) {
	case *ErrorResponse:
		return 1

	case *CreateRequest, *CreateResponse:
		return 11
	case *StopRequest, *StopResponse:
		return 12
	case *DestroyRequest, *DestroyResponse:
		return 13
	case *InfoRequest, *InfoResponse:
		return 13

	case *SpawnRequest, *SpawnResponse:
		return 21
	case *LinkRequest, *LinkResponse:
		return 22
	case *RunRequest, *RunResponse:
		return 23
	case *StreamRequest, *StreamResponse:
		return 24

	case *NetInRequest, *NetInResponse:
		return 31
	case *NetOutRequest, *NetOutResponse:
		return 32

	case *CopyInRequest, *CopyInResponse:
		return 41
	case *CopyOutRequest, *CopyOutResponse:
		return 42

	case *LimitMemoryRequest, *LimitMemoryResponse:
		return 51
	case *LimitDiskRequest, *LimitDiskResponse:
		return 52
	case *LimitBandwidthRequest, *LimitBandwidthResponse:
		return 53

	case *PingRequest, *PingResponse:
		return 91
	case *ListRequest, *ListResponse:
		return 92
	case *EchoRequest, *EchoResponse:
		return 93
	}

	panic("unknown message type")
}

func readNBytes(payloadLen int, io *bufio.Reader) ([]byte, error) {
	payload := make([]byte, payloadLen)

	for readCount := 0; readCount < payloadLen; {
		n, err := io.Read(payload[readCount:])
		if err != nil {
			return nil, err
		}

		readCount += n
	}

	return payload, nil
}
<commit_msg>fix info == destroy<commit_after>package warden

import (
	"bufio"
	"code.google.com/p/goprotobuf/proto"
	"errors"
	"fmt"
	"net"
	"strconv"
	"sync"
)

type Connection struct {
	conn      net.Conn
	read      *bufio.Reader
	writeLock sync.Mutex

	disconnected chan bool
}

type WardenError struct {
	Message   string
	Data      string
	Backtrace []string
}

func (e *WardenError) Error() string {
	return e.Message
}

func Connect(socket_path string) (*Connection, error) {
	conn, err := net.Dial("unix", socket_path)
	if err != nil {
		return nil, err
	}

	return NewConnection(conn), nil
}

func NewConnection(conn net.Conn) *Connection {
	return &Connection{
		conn: conn,
		read: bufio.NewReader(conn),

		// buffer size of 1 so that read and write errors
		// can both send without blocking
		disconnected: make(chan bool, 1),
	}
}

func (c *Connection) Close() {
	c.conn.Close()
}

func (c *Connection) Create() (*CreateResponse, error) {
	res, err := c.roundTrip(&CreateRequest{}, &CreateResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*CreateResponse), nil
}

func (c *Connection) Destroy(handle string) (*DestroyResponse, error) {
	res, err := c.roundTrip(
		&DestroyRequest{Handle: proto.String(handle)},
		&DestroyResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*DestroyResponse), nil
}

func (c *Connection) Spawn(handle, script string) (*SpawnResponse, error) {
	res, err := c.roundTrip(
		&SpawnRequest{
			Handle: proto.String(handle),
			Script: proto.String(script),
		},
		&SpawnResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*SpawnResponse), nil
}

func (c *Connection) Run(handle, script string) (*RunResponse, error) {
	res, err := c.roundTrip(
		&RunRequest{
			Handle: proto.String(handle),
			Script: proto.String(script),
		},
		&RunResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*RunResponse), nil
}

func (c *Connection) Stream(handle string, jobId uint32) (chan *StreamResponse, error) {
	err := c.sendMessage(
		&StreamRequest{
			Handle: proto.String(handle),
			JobId:  proto.Uint32(jobId),
		},
	)

	if err != nil {
		return nil, err
	}

	responses := make(chan *StreamResponse)

	go func() {
		for {
			resMsg, err := c.readResponse(&StreamResponse{})
			if err != nil {
				close(responses)
				break
			}

			response := resMsg.(*StreamResponse)

			responses <- response

			if response.ExitStatus != nil {
				close(responses)
				break
			}
		}
	}()

	return responses, nil
}

func (c *Connection) NetIn(handle string) (*NetInResponse, error) {
	res, err := c.roundTrip(
		&NetInRequest{Handle: proto.String(handle)},
		&NetInResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*NetInResponse), nil
}

func (c *Connection) CopyIn(handle, src, dst string) (*CopyInResponse, error) {
	res, err := c.roundTrip(
		&CopyInRequest{
			Handle:  proto.String(handle),
			SrcPath: proto.String(src),
			DstPath: proto.String(dst),
		},
		&CopyInResponse{},
	)

	if err != nil {
		return nil, err
	}

	return res.(*CopyInResponse), nil
}

func (c *Connection) List() (*ListResponse, error) {
	res, err := c.roundTrip(&ListRequest{}, &ListResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*ListResponse), nil
}

func (c *Connection) Info(handle string) (*InfoResponse, error) {
	res, err := c.roundTrip(&InfoRequest{
		Handle: proto.String(handle),
	}, &InfoResponse{})
	if err != nil {
		return nil, err
	}

	return res.(*InfoResponse), nil
}

func (c *Connection) roundTrip(request proto.Message, response proto.Message) (proto.Message, error) {
	err := c.sendMessage(request)
	if err != nil {
		return nil, err
	}

	resp, err := c.readResponse(response)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (c *Connection) sendMessage(req proto.Message) error {
	c.writeLock.Lock()
	defer c.writeLock.Unlock()

	request, err := proto.Marshal(req)
	if err != nil {
		return err
	}

	msg := &Message{
		Type:    Message_Type(message2type(req)).Enum(),
		Payload: request,
	}

	data, err := proto.Marshal(msg)
	if err != nil {
		return err
	}

	_, err = c.conn.Write(
		[]byte(
			fmt.Sprintf(
				"%d\r\n%s\r\n",
				len(data),
				data,
			),
		),
	)

	if err != nil {
		c.disconnected <- true
		return err
	}

	return nil
}

func (c *Connection) readResponse(response proto.Message) (proto.Message, error) {
	payload, err := c.readPayload()
	if err != nil {
		c.disconnected <- true
		return nil, err
	}

	message := &Message{}
	err = proto.Unmarshal(payload, message)
	if err != nil {
		return nil, err
	}

	// error response from server
	if message.GetType() == Message_Type(1) {
		errorResponse := &ErrorResponse{}
		err = proto.Unmarshal(message.Payload, errorResponse)
		if err != nil {
			return nil, errors.New("error unmarshalling error!")
		}

		return nil, &WardenError{
			Message:   errorResponse.GetMessage(),
			Data:      errorResponse.GetData(),
			Backtrace: errorResponse.GetBacktrace(),
		}
	}

	response_type := Message_Type(message2type(response))
	if message.GetType() != response_type {
		return nil, errors.New(
			fmt.Sprintf(
				"expected message type %s, got %s\n",
				response_type.String(),
				message.GetType().String(),
			),
		)
	}

	err = proto.Unmarshal(message.GetPayload(), response)
	return response, err
}

func (c *Connection) readPayload() ([]byte, error) {
	msgHeader, err := c.read.ReadBytes('\n')
	if err != nil {
		return nil, err
	}

	msgLen, err := strconv.ParseUint(string(msgHeader[0:len(msgHeader)-2]), 10, 0)
	if err != nil {
		return nil, err
	}

	payload, err := readNBytes(int(msgLen), c.read)
	if err != nil {
		return nil, err
	}

	_, err = readNBytes(2, c.read) // CRLN
	if err != nil {
		return nil, err
	}

	return payload, err
}

func message2type(msg proto.Message) int32 {
	switch msg.(type) {
	case *ErrorResponse:
		return 1

	case *CreateRequest, *CreateResponse:
		return 11
	case *StopRequest, *StopResponse:
		return 12
	case *DestroyRequest, *DestroyResponse:
		return 13
	case *InfoRequest, *InfoResponse:
		return 14

	case *SpawnRequest, *SpawnResponse:
		return 21
	case *LinkRequest, *LinkResponse:
		return 22
	case *RunRequest, *RunResponse:
		return 23
	case *StreamRequest, *StreamResponse:
		return 24

	case *NetInRequest, *NetInResponse:
		return 31
	case *NetOutRequest, *NetOutResponse:
		return 32

	case *CopyInRequest, *CopyInResponse:
		return 41
	case *CopyOutRequest, *CopyOutResponse:
		return 42

	case *LimitMemoryRequest, *LimitMemoryResponse:
		return 51
	case *LimitDiskRequest, *LimitDiskResponse:
		return 52
	case *LimitBandwidthRequest, *LimitBandwidthResponse:
		return 53

	case *PingRequest, *PingResponse:
		return 91
	case *ListRequest, *ListResponse:
		return 92
	case *EchoRequest, *EchoResponse:
		return 93
	}

	panic("unknown message type")
}

func readNBytes(payloadLen int, io *bufio.Reader) ([]byte, error) {
	payload := make([]byte, payloadLen)

	for readCount := 0; readCount < payloadLen; {
		n, err := io.Read(payload[readCount:])
		if err != nil {
			return nil, err
		}

		readCount += n
	}

	return payload, nil
}
<|endoftext|>


<commit_before>package core

import (
	"encoding/base64"
	"image"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"os"
	"path"
	"strings"

	"github.com/OpenBazaar/openbazaar-go/ipfs"
	"github.com/OpenBazaar/openbazaar-go/pb"
	"github.com/nfnt/resize"
)

type Images struct {
	Tiny     string `json:"tiny"`
	Small    string `json:"small"`
	Medium   string `json:"medium"`
	Large    string `json:"large"`
	Original string `json:"original"`
}

func (n *OpenBazaarNode) SetAvatarImages(base64ImageData string) (*Images, error) {
	reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, err
	}
	reader = base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	imgCfg, _, err := image.DecodeConfig(reader)
	if err != nil {
		return nil, err
	}
	w := uint(imgCfg.Width)
	h := uint(imgCfg.Height)
	if w > h {
		w = w / h
		h = uint(1)
	} else if h > w {
		h = h / w
		w = uint(1)
	} else {
		w = uint(1)
		h = uint(1)
	}

	ty := resize.Resize(w*50, h*50, img, resize.Lanczos3)
	sm := resize.Resize(w*100, h*100, img, resize.Lanczos3)
	md := resize.Resize(w*140, h*140, img, resize.Lanczos3)
	lg := resize.Resize(w*280, h*280, img, resize.Lanczos3)

	imgPath := path.Join(n.RepoPath, "root", "images")

	out, err := os.Create(path.Join(imgPath, "tiny", "avatar"))
	if err != nil {
		return nil, err
	}
	defer out.Close()
	jpeg.Encode(out, ty, nil)

	out, err = os.Create(path.Join(imgPath, "small", "avatar"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, sm, nil)

	out, err = os.Create(path.Join(imgPath, "medium", "avatar"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, md, nil)

	out, err = os.Create(path.Join(imgPath, "large", "avatar"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, lg, nil)

	out, err = os.Create(path.Join(imgPath, "original", "avatar"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, img, nil)

	// Add hash to profile
	t, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "tiny", "avatar"))
	if aerr != nil {
		return nil, err
	}
	s, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "small", "avatar"))
	if aerr != nil {
		return nil, err
	}
	m, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "medium", "avatar"))
	if aerr != nil {
		return nil, err
	}
	l, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "large", "avatar"))
	if aerr != nil {
		return nil, err
	}
	o, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "original", "avatar"))
	if aerr != nil {
		return nil, err
	}
	profile, err := n.GetProfile()
	if err != nil {
		return nil, err
	}
	i := new(pb.Profile_Image)
	i.Tiny = t
	i.Small = s
	i.Medium = m
	i.Large = l
	i.Original = o
	profile.AvatarHashes = i
	err = n.UpdateProfile(&profile)
	if aerr != nil {
		return nil, err
	}
	return &Images{t, s, m, l, o}, nil
}

func (n *OpenBazaarNode) SetHeaderImages(base64ImageData string) (*Images, error) {
	reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, err
	}
	reader = base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	imgCfg, _, err := image.DecodeConfig(reader)
	if err != nil {
		return nil, err
	}
	imgWidth := uint(imgCfg.Width)
	imgHeight := uint(imgCfg.Height)

	w, h := getImageAttributes(304, 87, imgWidth, imgHeight)
	ty := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(608, 174, imgWidth, imgHeight)
	sm := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(1225, 350, imgWidth, imgHeight)
	md := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(2450, 700, imgWidth, imgHeight)
	lg := resize.Resize(w, h, img, resize.Lanczos3)

	imgPath := path.Join(n.RepoPath, "root", "images")

	out, err := os.Create(path.Join(imgPath, "tiny", "header"))
	if err != nil {
		return nil, err
	}
	defer out.Close()
	jpeg.Encode(out, ty, nil)

	out, err = os.Create(path.Join(imgPath, "small", "header"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, sm, nil)

	out, err = os.Create(path.Join(imgPath, "medium", "header"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, md, nil)

	out, err = os.Create(path.Join(imgPath, "large", "header"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, lg, nil)

	out, err = os.Create(path.Join(imgPath, "original", "header"))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, img, nil)

	// Add hash to profile
	t, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "tiny", "header"))
	if aerr != nil {
		return nil, err
	}
	s, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "small", "header"))
	if aerr != nil {
		return nil, err
	}
	m, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "medium", "header"))
	if aerr != nil {
		return nil, err
	}
	l, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "large", "header"))
	if aerr != nil {
		return nil, err
	}
	o, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "original", "header"))
	if aerr != nil {
		return nil, err
	}
	profile, err := n.GetProfile()
	if err != nil {
		return nil, err
	}
	i := new(pb.Profile_Image)
	i.Tiny = t
	i.Small = s
	i.Medium = m
	i.Large = l
	i.Original = o
	profile.HeaderHashes = i
	err = n.UpdateProfile(&profile)
	if aerr != nil {
		return nil, err
	}
	return &Images{t, s, m, l, o}, nil
}

func (n *OpenBazaarNode) SetProductImages(base64ImageData, filename string) (*Images, error) {
	// Decode base64 image data
	reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	img, _, err := image.Decode(reader)
	if err != nil {
		fmt.Println(1)
		return nil, err
	}

	// Get the image config
	reader = base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	imgCfg, _, err := image.DecodeConfig(reader)
	if err != nil {
		return nil, err
	}
	imgWidth := uint(imgCfg.Width)
	imgHeight := uint(imgCfg.Height)

	w, h := getImageAttributes(60, 60, imgWidth, imgHeight)
	ty := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(228, 228, imgWidth, imgHeight)
	sm := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(500, 500, imgWidth, imgHeight)
	md := resize.Resize(w, h, img, resize.Lanczos3)
	w, h = getImageAttributes(1000, 1000, imgWidth, imgHeight)
	lg := resize.Resize(w, h, img, resize.Lanczos3)

	imgPath := path.Join(n.RepoPath, "root", "images")

	out, err := os.Create(path.Join(imgPath, "tiny", filename))
	if err != nil {
		return nil, err
	}
	defer out.Close()
	jpeg.Encode(out, ty, nil)

	out, err = os.Create(path.Join(imgPath, "small", filename))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, sm, nil)

	out, err = os.Create(path.Join(imgPath, "medium", filename))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, md, nil)

	out, err = os.Create(path.Join(imgPath, "large", filename))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, lg, nil)

	out, err = os.Create(path.Join(imgPath, "original", filename))
	if err != nil {
		return nil, err
	}
	jpeg.Encode(out, img, nil)

	// Get the image hashes
	t, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "tiny", filename))
	if aerr != nil {
		return nil, err
	}
	s, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "small", filename))
	if aerr != nil {
		return nil, err
	}
	m, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "medium", filename))
	if aerr != nil {
		return nil, err
	}
	l, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "large", filename))
	if aerr != nil {
		return nil, err
	}
	o, aerr := ipfs.AddFile(n.Context, path.Join(imgPath, "original", filename))
	if aerr != nil {
		return nil, err
	}
	ret := &Images{t, s, m, l, o}
	return ret, nil
}

func getImageAttributes(targetWidth, targetHeight, imgWidth, imgHeight uint) (width, height uint) {
	targetRatio := float32(targetWidth) / float32(targetHeight)
	imageRatio := float32(imgWidth) / float32(imgHeight)
	var h, w float32
	if imageRatio > targetRatio {
		h = float32(targetHeight)
		w = float32(targetHeight) * imageRatio
	} else {
		w = float32(targetWidth)
		h = float32(targetWidth) * (float32(imgHeight) / float32(imgWidth))
	}
	return uint(w), uint(h)
}
<commit_msg>Refactor and DRY up image handling<commit_after>package core

import (
	"encoding/base64"
	"image"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"os"
	"path"
	"strings"

	"github.com/OpenBazaar/openbazaar-go/ipfs"
	"github.com/OpenBazaar/openbazaar-go/pb"
	"github.com/nfnt/resize"
)

type Images struct {
	Tiny     string `json:"tiny"`
	Small    string `json:"small"`
	Medium   string `json:"medium"`
	Large    string `json:"large"`
	Original string `json:"original"`
}

func (n *OpenBazaarNode) SetAvatarImages(base64ImageData string) (*Images, error) {
	img, imgCfg, err := decodeImageData(base64ImageData)
	if err != nil {
		return nil, err
	}

	imgPath := path.Join(n.RepoPath, "root", "images")

	t, err := n.addResizedImage(img, imgCfg, 50, 50, path.Join(imgPath, "tiny", "avatar"))
	if err != nil {
		return nil, err
	}
	s, err := n.addResizedImage(img, imgCfg, 100, 100, path.Join(imgPath, "small", "avatar"))
	if err != nil {
		return nil, err
	}
	m, err := n.addResizedImage(img, imgCfg, 140, 140, path.Join(imgPath, "medium", "avatar"))
	if err != nil {
		return nil, err
	}
	l, err := n.addResizedImage(img, imgCfg, 280, 280, path.Join(imgPath, "large", "avatar"))
	if err != nil {
		return nil, err
	}
	o, err := n.addImage(img, path.Join(imgPath, "original", "avatar"))
	if err != nil {
		return nil, err
	}

	profile, err := n.GetProfile()
	if err != nil {
		return nil, err
	}
	i := new(pb.Profile_Image)
	i.Tiny = t
	i.Small = s
	i.Medium = m
	i.Large = l
	i.Original = o
	profile.AvatarHashes = i
	err = n.UpdateProfile(&profile)
	if err != nil {
		return nil, err
	}
	return &Images{t, s, m, l, o}, nil
}

func (n *OpenBazaarNode) SetHeaderImages(base64ImageData string) (*Images, error) {
	img, imgCfg, err := decodeImageData(base64ImageData)
	if err != nil {
		return nil, err
	}

	imgPath := path.Join(n.RepoPath, "root", "images")

	t, err := n.addResizedImage(img, imgCfg, 304, 87, path.Join(imgPath, "tiny", "header"))
	if err != nil {
		return nil, err
	}
	s, err := n.addResizedImage(img, imgCfg, 608, 174, path.Join(imgPath, "small", "header"))
	if err != nil {
		return nil, err
	}
	m, err := n.addResizedImage(img, imgCfg, 1225, 350, path.Join(imgPath, "medium", "header"))
	if err != nil {
		return nil, err
	}
	l, err := n.addResizedImage(img, imgCfg, 2450, 700, path.Join(imgPath, "large", "header"))
	if err != nil {
		return nil, err
	}
	o, err := n.addImage(img, path.Join(imgPath, "original", "header"))
	if err != nil {
		return nil, err
	}
	profile, err := n.GetProfile()
	if err != nil {
		return nil, err
	}
	i := new(pb.Profile_Image)
	i.Tiny = t
	i.Small = s
	i.Medium = m
	i.Large = l
	i.Original = o
	profile.HeaderHashes = i
	err = n.UpdateProfile(&profile)
	if err != nil {
		return nil, err
	}
	return &Images{t, s, m, l, o}, nil
}

func (n *OpenBazaarNode) SetProductImages(base64ImageData, filename string) (*Images, error) {
	img, imgCfg, err := decodeImageData(base64ImageData)
	if err != nil {
		return nil, err
	}

	imgPath := path.Join(n.RepoPath, "root", "images")

	t, err := n.addResizedImage(img, imgCfg, 60, 60, path.Join(imgPath, "tiny", filename))
	if err != nil {
		return nil, err
	}
	s, err := n.addResizedImage(img, imgCfg, 228, 228, path.Join(imgPath, "small", filename))
	if err != nil {
		return nil, err
	}
	m, err := n.addResizedImage(img, imgCfg, 500, 500, path.Join(imgPath, "medium", filename))
	if err != nil {
		return nil, err
	}
	l, err := n.addResizedImage(img, imgCfg, 1000, 1000, path.Join(imgPath, "large", filename))
	if err != nil {
		return nil, err
	}
	o, err := n.addImage(img, path.Join(imgPath, "original", filename))
	if err != nil {
		return nil, err
	}

	return &Images{t, s, m, l, o}, nil
}

func (n *OpenBazaarNode) addImage(img image.Image, imgPath string) (string, error) {
	out, err := os.Create(imgPath)
	if err != nil {
		return "", err
	}
	defer out.Close()
	jpeg.Encode(out, img, nil)
	return ipfs.AddFile(n.Context, imgPath)
}

func (n *OpenBazaarNode) addResizedImage(img image.Image, imgCfg *image.Config, w, h uint, imgPath string) (string, error) {
	width, height := getImageAttributes(w, h, uint(imgCfg.Width), uint(imgCfg.Height))
	newImg := resize.Resize(width, height, img, resize.Lanczos3)
	return n.addImage(newImg, imgPath)
}

func decodeImageData(base64ImageData string) (image.Image, *image.Config, error) {
	reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, nil, err
	}
	reader = base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64ImageData))
	imgCfg, _, err := image.DecodeConfig(reader)
	if err != nil {
		return nil, nil, err
	}
	return img, &imgCfg, err
}

func getImageAttributes(targetWidth, targetHeight, imgWidth, imgHeight uint) (width, height uint) {
	targetRatio := float32(targetWidth) / float32(targetHeight)
	imageRatio := float32(imgWidth) / float32(imgHeight)
	var h, w float32
	if imageRatio > targetRatio {
		h = float32(targetHeight)
		w = float32(targetHeight) * imageRatio
	} else {
		w = float32(targetWidth)
		h = float32(targetWidth) * (float32(imgHeight) / float32(imgWidth))
	}
	return uint(w), uint(h)
}
<|endoftext|>


<commit_before>package seccomp

import (
	"fmt"
)

/* TODO Import from C headers instead of hardcoding these if not in golang syscall... */

const (
	FUTEX_WAIT            = 0
	FUTEX_WAKE            = 1
	FUTEX_FD              = 2
	FUTEX_REQUEUE         = 3
	FUTEX_CMP_REQUEUE     = 4
	FUTEX_WAKE_OP         = 5
	FUTEX_LOCK_PI         = 6
	FUTEX_UNLOCK_PI       = 7
	FUTEX_TRYLOCK_PI      = 8
	FUTEX_WAIT_BITSET     = 9
	FUTEX_WAKE_BITSET     = 10
	FUTEX_WAIT_REQUEUE_PI = 11
	FUTEX_CMP_REQUEUE_PI  = 12
	FUTEX_PRIVATE_FLAG    = 128
	FUTEX_CLOCK_REALTIME  = 256

	FUTEX_WAIT_PRIVATE        = (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
	FUTEX_WAKE_PRIVATE        = (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
	FUTEX_REQUEUE_PRIVATE     = (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
	FUTEX_CMP_REQUEUE_PRIVATE = (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
)

func render_futex(pid int, args RegisterArgs) (string, error) {

	ops := map[uint]string{
		FUTEX_WAIT:                             "FUTEX_WAIT",
		FUTEX_WAKE:                             "FUTEX_WAKE",
		FUTEX_FD:                               "FUTEX_FD",
		FUTEX_REQUEUE:                          "FUTEX_REQUEUE",
		FUTEX_CMP_REQUEUE:                      "FUTEX_CMP_REQUEUE",
		FUTEX_WAIT | FUTEX_PRIVATE_FLAG:        "FUTEX_WAIT_PRIVATE",
		FUTEX_WAKE | FUTEX_PRIVATE_FLAG:        "FUTEX_WAKE_PRIVATE",
		FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG:     "FUTEX_REQUEUE_PRIVATE",
		FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG: "FUTEX_CMP_REQUEUE_PRIVATE",
	}

	callrep := ""
	op := uint(args[1]) & 127
	opstr := ops[uint(args[1])]

	// TODO: lots

	switch op {
	case FUTEX_WAIT:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d", uintptr(args[0]), opstr, int32(args[2]))
	case FUTEX_WAKE:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d)", uintptr(args[0]), opstr, int32(args[2]))
	case FUTEX_FD:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d)", uintptr(args[0]), opstr, int32(args[2]))
	case FUTEX_WAKE_BITSET:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, %d)", uintptr(args[0]), opstr, int32(args[2]), args[5])
	case FUTEX_WAIT_BITSET:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, %d, %d", uintptr(args[0]), opstr, int32(args[2]), args[3], args[5])
	default:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, 0x%X, 0x%x, %d)", uintptr(args[0]), opstr, int32(args[2]), uintptr(args[3]), args[4], args[5])
	}
	return callrep, nil

}
<commit_msg>Improvements to still incomplete futex(2) renderer.<commit_after>package seccomp

import (
	"fmt"
)

// #include "linux/futex.h"
import "C"

func render_futex(pid int, args RegisterArgs) (string, error) {

	ops := map[uint]string{
		C.FUTEX_WAIT:                    "FUTEX_WAIT",
		C.FUTEX_WAKE:                    "FUTEX_WAKE",
		C.FUTEX_FD:                      "FUTEX_FD",
		C.FUTEX_REQUEUE:                 "FUTEX_REQUEUE",
		C.FUTEX_CMP_REQUEUE:             "FUTEX_CMP_REQUEUE",
		C.FUTEX_WAKE_OP:                 "FUTEX_WAKE_OP",
		C.FUTEX_LOCK_PI:                 "FUTEX_LOCK_PI",
		C.FUTEX_UNLOCK_PI:               "FUTEX_UNLOCK_PI",
		C.FUTEX_TRYLOCK_PI:              "FUTEX_TRYLOCK_PI",
		C.FUTEX_WAIT_BITSET:             "FUTEX_WAIT_BITSET",
		C.FUTEX_WAKE_BITSET:             "FUTEX_WAKE_BITSET",
		C.FUTEX_WAIT_REQUEUE_PI:         "FUTEX_WAIT_REQUEUE_PI",
		C.FUTEX_CMP_REQUEUE_PI:          "FUTEX_CMP_REQUEUE_PI",
		C.FUTEX_WAIT_PRIVATE:            "FUTEX_WAIT_PRIVATE",
		C.FUTEX_WAKE_PRIVATE:            "FUTEX_WAKE_PRIVATE",
		C.FUTEX_REQUEUE_PRIVATE:         "FUTEX_REQUEUE_PRIVATE",
		C.FUTEX_CMP_REQUEUE_PRIVATE:     "FUTEX_CMP_REQUEUE_PRIVATE",
		C.FUTEX_WAKE_OP_PRIVATE:         "FUTEX_WAKE_OP_PRIVATE",
		C.FUTEX_LOCK_PI_PRIVATE:         "FUTEX_LOCK_PI_PRIVATE",
		C.FUTEX_UNLOCK_PI_PRIVATE:       "FUTEX_UNLOCK_PI_PRIVATE",
		C.FUTEX_TRYLOCK_PI_PRIVATE:      "FUTEX_TRYLOCK_PI_PRIVATE",
		C.FUTEX_WAIT_BITSET_PRIVATE:     "FUTEX_WAIT_BITSET_PRIVATE",
		C.FUTEX_WAKE_BITSET_PRIVATE:     "FUTEX_WAKE_BITSET_PRIVATE",
		C.FUTEX_WAIT_REQUEUE_PI_PRIVATE: "FUTEX_WAIT_REQUEUE_PI_PRIVATE",
		C.FUTEX_CMP_REQUEUE_PI_PRIVATE:  "FUTEX_CMP_REQUEUE_PI_PRIVATE",
	}

	callrep := ""
	op := uint(args[1]) & 127
	opstr := ""

	for x, y := range ops {
		if uint(args[1])&x == x {
			opstr = y
		}
	}

	if opstr == "" {
		opstr = fmt.Sprintf("(FUTEX_??? %d %d %s)", args[1], op, ops[op])
	}

	if (args[1] & C.FUTEX_CLOCK_REALTIME) == C.FUTEX_CLOCK_REALTIME {
		opstr += "|FUTEX_CLOCK_REALTIME"
	}

	// TODO: lots

	switch op {
	case C.FUTEX_WAIT:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d)", uintptr(args[0]), opstr, int32(args[2]))
	case C.FUTEX_WAKE:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d)", uintptr(args[0]), opstr, int32(args[2]))
	case C.FUTEX_FD:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d)", uintptr(args[0]), opstr, int32(args[2]))
	case C.FUTEX_WAKE_BITSET:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, %d)", uintptr(args[0]), opstr, int32(args[2]), args[5])
	case C.FUTEX_WAIT_BITSET:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, %d, %d)", uintptr(args[0]), opstr, int32(args[2]), args[3], args[5])
	default:
		callrep = fmt.Sprintf("futex(0x%X, %s, %d, 0x%X, 0x%x, %d)", uintptr(args[0]), opstr, int32(args[2]), uintptr(args[3]), args[4], args[5])
	}
	return callrep, nil

}
<|endoftext|>


<commit_before>package discovery

import (
	"context"
	"time"

	logging "github.com/ipfs/go-log"
	pstore "github.com/libp2p/go-libp2p-peerstore"
)

var log = logging.Logger("discovery")

// FindPeers is a utility function that synchonously collects peers from a Discoverer
func FindPeers(ctx context.Context, d Discoverer, ns string, limit int) ([]pstore.PeerInfo, error) {
	res := make([]pstore.PeerInfo, 0, limit)

	ch, err := d.FindPeers(ctx, ns, Limit(limit))
	if err != nil {
		return nil, err
	}

	for pi := range ch {
		res = append(res, pi)
	}

	return res, nil
}

// Advertise is a utility function that persistently advertises a service through an Advertiser
func Advertise(ctx context.Context, a Advertiser, ns string) {
	go func() {
		for {
			ttl, err := a.Advertise(ctx, ns)
			if err != nil {
				log.Debugf("Error advertising %s: %s", ns, err.Error())
				if ctx.Err() != nil {
					return
				}

				select {
				case <-time.After(2 * time.Minute):
					continue
				case <-ctx.Done():
					return
				}
			}

			wait := 7 * ttl / 8
			select {
			case <-time.After(wait):
			case <-ctx.Done():
				return
			}
		}
	}()
}
<commit_msg>add options to utility interface<commit_after>package discovery

import (
	"context"
	"time"

	logging "github.com/ipfs/go-log"
	pstore "github.com/libp2p/go-libp2p-peerstore"
)

var log = logging.Logger("discovery")

// FindPeers is a utility function that synchonously collects peers from a Discoverer
func FindPeers(ctx context.Context, d Discoverer, ns string, opts ...Option) ([]pstore.PeerInfo, error) {
	var res []pstore.PeerInfo

	ch, err := d.FindPeers(ctx, ns, opts...)
	if err != nil {
		return nil, err
	}

	for pi := range ch {
		res = append(res, pi)
	}

	return res, nil
}

// Advertise is a utility function that persistently advertises a service through an Advertiser
func Advertise(ctx context.Context, a Advertiser, ns string, opts ...Option) {
	go func() {
		for {
			ttl, err := a.Advertise(ctx, ns, opts...)
			if err != nil {
				log.Debugf("Error advertising %s: %s", ns, err.Error())
				if ctx.Err() != nil {
					return
				}

				select {
				case <-time.After(2 * time.Minute):
					continue
				case <-ctx.Done():
					return
				}
			}

			wait := 7 * ttl / 8
			select {
			case <-time.After(wait):
			case <-ctx.Done():
				return
			}
		}
	}()
}
<|endoftext|>


<commit_before>package pnet

import (
	"bytes"
	"encoding/base64"
	"testing"
)

func bufWithBase(base string, windows bool) *bytes.Buffer {

	b := &bytes.Buffer{}
	b.Write(pathPSKv1)
	if windows {
		b.WriteString("\r")
	}
	b.WriteString("\n")
	b.WriteString(base)
	if windows {
		b.WriteString("\r")
	}
	b.WriteString("\n")
	return b
}

func TestDecodeHex(t *testing.T) {
	testDecodeHex(t, true)
	testDecodeHex(t, false)
}

func testDecodeHex(t *testing.T, windows bool) {
	b := bufWithBase("/base16/", windows)
	for i := 0; i < 32; i++ {
		b.WriteString("FF")
	}

	psk, err := decodeV1PSK(b)
	if err != nil {
		t.Fatal(err)
	}

	for _, b := range psk {
		if b != 255 {
			t.Fatal("byte was wrong")
		}
	}
}

func TestDecodeB64(t *testing.T) {
	testDecodeB64(t, true)
	testDecodeB64(t, false)
}

func testDecodeB64(t *testing.T, windows bool) {
	b := bufWithBase("/base64/", windows)
	key := make([]byte, 32)
	for i := 0; i < 32; i++ {
		key[i] = byte(i)
	}

	e := base64.NewEncoder(base64.StdEncoding, b)
	_, err := e.Write(key)
	if err != nil {
		t.Fatal(err)
	}
	err = e.Close()
	if err != nil {
		t.Fatal(err)
	}

	psk, err := decodeV1PSK(b)
	if err != nil {
		t.Fatal(err)
	}

	for i, b := range psk {
		if b != psk[i] {
			t.Fatal("byte was wrong")
		}
	}

}
<commit_msg>Add bad encoding test case<commit_after>package pnet

import (
	"bytes"
	"encoding/base64"
	"testing"
)

func bufWithBase(base string, windows bool) *bytes.Buffer {

	b := &bytes.Buffer{}
	b.Write(pathPSKv1)
	if windows {
		b.WriteString("\r")
	}
	b.WriteString("\n")
	b.WriteString(base)
	if windows {
		b.WriteString("\r")
	}
	b.WriteString("\n")
	return b
}

func TestDecodeHex(t *testing.T) {
	testDecodeHex(t, true)
	testDecodeHex(t, false)
}

func TestDecodeBad(t *testing.T) {
	testDecodeBad(t, true)
	testDecodeBad(t, false)
}
func testDecodeBad(t *testing.T, windows bool) {
	b := bufWithBase("/verybadbase/", windows)
	b.WriteString("Have fun decoding that key")

	_, err := decodeV1PSK(b)
	if err == nil {
		t.Fatal("expected 'unknown encoding' got nil")
	}
}

func testDecodeHex(t *testing.T, windows bool) {
	b := bufWithBase("/base16/", windows)
	for i := 0; i < 32; i++ {
		b.WriteString("FF")
	}

	psk, err := decodeV1PSK(b)
	if err != nil {
		t.Fatal(err)
	}

	for _, b := range psk {
		if b != 255 {
			t.Fatal("byte was wrong")
		}
	}
}

func TestDecodeB64(t *testing.T) {
	testDecodeB64(t, true)
	testDecodeB64(t, false)
}

func testDecodeB64(t *testing.T, windows bool) {
	b := bufWithBase("/base64/", windows)
	key := make([]byte, 32)
	for i := 0; i < 32; i++ {
		key[i] = byte(i)
	}

	e := base64.NewEncoder(base64.StdEncoding, b)
	_, err := e.Write(key)
	if err != nil {
		t.Fatal(err)
	}
	err = e.Close()
	if err != nil {
		t.Fatal(err)
	}

	psk, err := decodeV1PSK(b)
	if err != nil {
		t.Fatal(err)
	}

	for i, b := range psk {
		if b != psk[i] {
			t.Fatal("byte was wrong")
		}
	}

}
<|endoftext|>


<commit_before>package version

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

// Constraint represents a single constraint for a version, such as
// ">= 1.0".
type Constraint struct {
	f        constraintFunc
	check    *Version
	original string
}

// Constraints is a slice of constraints. We make a custom type so that
// we can add methods to it.
type Constraints []*Constraint

type constraintFunc func(v, c *Version) bool

var constraintOperators map[string]constraintFunc

var constraintRegexp *regexp.Regexp

func init() {
	constraintOperators = map[string]constraintFunc{
		"":   constraintEqual,
		"=":  constraintEqual,
		"!=": constraintNotEqual,
		">":  constraintGreaterThan,
		"<":  constraintLessThan,
		">=": constraintGreaterThanEqual,
		"<=": constraintLessThanEqual,
		"~>": constraintPessimistic,
	}

	ops := make([]string, 0, len(constraintOperators))
	for k := range constraintOperators {
		ops = append(ops, regexp.QuoteMeta(k))
	}

	constraintRegexp = regexp.MustCompile(fmt.Sprintf(
		`^\s*(%s)\s*(%s)\s*$`,
		strings.Join(ops, "|"),
		VersionRegexpRaw))
}

// NewConstraint will parse one or more constraints from the given
// constraint string. The string must be a comma-separated list of
// constraints.
func NewConstraint(v string) (Constraints, error) {
	vs := strings.Split(v, ",")
	result := make([]*Constraint, len(vs))
	for i, single := range vs {
		c, err := parseSingle(single)
		if err != nil {
			return nil, err
		}

		result[i] = c
	}

	return Constraints(result), nil
}

// Check tests if a version satisfies all the constraints.
func (cs Constraints) Check(v *Version) bool {
	for _, c := range cs {
		if !c.Check(v) {
			return false
		}
	}

	return true
}

// Returns the string format of the constraints
func (cs Constraints) String() string {
	csStr := make([]string, len(cs))
	for i, c := range cs {
		csStr[i] = c.String()
	}

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

// Check tests if a constraint is validated by the given version.
func (c *Constraint) Check(v *Version) bool {
	return c.f(v, c.check)
}

func (c *Constraint) String() string {
	return c.original
}

func parseSingle(v string) (*Constraint, error) {
	matches := constraintRegexp.FindStringSubmatch(v)
	if matches == nil {
		return nil, fmt.Errorf("Malformed constraint: %s", v)
	}

	check, err := NewVersion(matches[2])
	if err != nil {
		return nil, err
	}

	return &Constraint{
		f:        constraintOperators[matches[1]],
		check:    check,
		original: v,
	}, nil
}

func prereleaseCheck(v, c *Version) bool {
	switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
	case cPre && vPre:
		// A constraint with a pre-release can only match a pre-release version
		// with the same base segments.
		return reflect.DeepEqual(c.Segments64(), v.Segments64())

	case !cPre && vPre:
		// A constraint without a pre-release can only match a version without a
		// pre-release.
		return false

	case cPre && !vPre:
		// OK, except with the pessimistic operator
	case !cPre && !vPre:
		// OK
	}
	return true
}

//-------------------------------------------------------------------
// Constraint functions
//-------------------------------------------------------------------

func constraintEqual(v, c *Version) bool {
	return v.Equal(c)
}

func constraintNotEqual(v, c *Version) bool {
	return !v.Equal(c)
}

func constraintGreaterThan(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) == 1
}

func constraintLessThan(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) == -1
}

func constraintGreaterThanEqual(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) >= 0
}

func constraintLessThanEqual(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) <= 0
}

func constraintPessimistic(v, c *Version) bool {
	// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
	if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
		return false
	}

	// If the version being checked is naturally less than the constraint, then there
	// is no way for the version to be valid against the constraint
	if v.LessThan(c) {
		return false
	}
	// We'll use this more than once, so grab the length now so it's a little cleaner
	// to write the later checks
	cs := len(c.segments)

	// If the version being checked has less specificity than the constraint, then there
	// is no way for the version to be valid against the constraint
	if cs > len(v.segments) {
		return false
	}

	// Check the segments in the constraint against those in the version. If the version
	// being checked, at any point, does not have the same values in each index of the
	// constraints segments, then it cannot be valid against the constraint.
	for i := 0; i < c.si-1; i++ {
		if v.segments[i] != c.segments[i] {
			return false
		}
	}

	// Check the last part of the segment in the constraint. If the version segment at
	// this index is less than the constraints segment at this index, then it cannot
	// be valid against the constraint
	if c.segments[cs-1] > v.segments[cs-1] {
		return false
	}

	// If nothing has rejected the version by now, it's valid
	return true
}
<commit_msg>Introduce MustConstraints()<commit_after>package version

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
)

// Constraint represents a single constraint for a version, such as
// ">= 1.0".
type Constraint struct {
	f        constraintFunc
	check    *Version
	original string
}

// Constraints is a slice of constraints. We make a custom type so that
// we can add methods to it.
type Constraints []*Constraint

type constraintFunc func(v, c *Version) bool

var constraintOperators map[string]constraintFunc

var constraintRegexp *regexp.Regexp

func init() {
	constraintOperators = map[string]constraintFunc{
		"":   constraintEqual,
		"=":  constraintEqual,
		"!=": constraintNotEqual,
		">":  constraintGreaterThan,
		"<":  constraintLessThan,
		">=": constraintGreaterThanEqual,
		"<=": constraintLessThanEqual,
		"~>": constraintPessimistic,
	}

	ops := make([]string, 0, len(constraintOperators))
	for k := range constraintOperators {
		ops = append(ops, regexp.QuoteMeta(k))
	}

	constraintRegexp = regexp.MustCompile(fmt.Sprintf(
		`^\s*(%s)\s*(%s)\s*$`,
		strings.Join(ops, "|"),
		VersionRegexpRaw))
}

// NewConstraint will parse one or more constraints from the given
// constraint string. The string must be a comma-separated list of
// constraints.
func NewConstraint(v string) (Constraints, error) {
	vs := strings.Split(v, ",")
	result := make([]*Constraint, len(vs))
	for i, single := range vs {
		c, err := parseSingle(single)
		if err != nil {
			return nil, err
		}

		result[i] = c
	}

	return Constraints(result), nil
}

// MustConstraints is a helper that wraps a call to a function
// returning (Constraints, error) and panics if error is non-nil.
func MustConstraints(c Constraints, err error) Constraints {
	if err != nil {
		panic(err)
	}

	return c
}

// Check tests if a version satisfies all the constraints.
func (cs Constraints) Check(v *Version) bool {
	for _, c := range cs {
		if !c.Check(v) {
			return false
		}
	}

	return true
}

// Returns the string format of the constraints
func (cs Constraints) String() string {
	csStr := make([]string, len(cs))
	for i, c := range cs {
		csStr[i] = c.String()
	}

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

// Check tests if a constraint is validated by the given version.
func (c *Constraint) Check(v *Version) bool {
	return c.f(v, c.check)
}

func (c *Constraint) String() string {
	return c.original
}

func parseSingle(v string) (*Constraint, error) {
	matches := constraintRegexp.FindStringSubmatch(v)
	if matches == nil {
		return nil, fmt.Errorf("Malformed constraint: %s", v)
	}

	check, err := NewVersion(matches[2])
	if err != nil {
		return nil, err
	}

	return &Constraint{
		f:        constraintOperators[matches[1]],
		check:    check,
		original: v,
	}, nil
}

func prereleaseCheck(v, c *Version) bool {
	switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
	case cPre && vPre:
		// A constraint with a pre-release can only match a pre-release version
		// with the same base segments.
		return reflect.DeepEqual(c.Segments64(), v.Segments64())

	case !cPre && vPre:
		// A constraint without a pre-release can only match a version without a
		// pre-release.
		return false

	case cPre && !vPre:
		// OK, except with the pessimistic operator
	case !cPre && !vPre:
		// OK
	}
	return true
}

//-------------------------------------------------------------------
// Constraint functions
//-------------------------------------------------------------------

func constraintEqual(v, c *Version) bool {
	return v.Equal(c)
}

func constraintNotEqual(v, c *Version) bool {
	return !v.Equal(c)
}

func constraintGreaterThan(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) == 1
}

func constraintLessThan(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) == -1
}

func constraintGreaterThanEqual(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) >= 0
}

func constraintLessThanEqual(v, c *Version) bool {
	return prereleaseCheck(v, c) && v.Compare(c) <= 0
}

func constraintPessimistic(v, c *Version) bool {
	// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
	if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
		return false
	}

	// If the version being checked is naturally less than the constraint, then there
	// is no way for the version to be valid against the constraint
	if v.LessThan(c) {
		return false
	}
	// We'll use this more than once, so grab the length now so it's a little cleaner
	// to write the later checks
	cs := len(c.segments)

	// If the version being checked has less specificity than the constraint, then there
	// is no way for the version to be valid against the constraint
	if cs > len(v.segments) {
		return false
	}

	// Check the segments in the constraint against those in the version. If the version
	// being checked, at any point, does not have the same values in each index of the
	// constraints segments, then it cannot be valid against the constraint.
	for i := 0; i < c.si-1; i++ {
		if v.segments[i] != c.segments[i] {
			return false
		}
	}

	// Check the last part of the segment in the constraint. If the version segment at
	// this index is less than the constraints segment at this index, then it cannot
	// be valid against the constraint
	if c.segments[cs-1] > v.segments[cs-1] {
		return false
	}

	// If nothing has rejected the version by now, it's valid
	return true
}
<|endoftext|>


<commit_before>// Copyright © 2015 Hilko Bengen <bengen@hilluzination.de>. All rights reserved.
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

// Package yara provides bindings to the YARA library.
package yara

/*
#include <yara.h>

int rules_callback(int message, void *message_data, void *user_data);
size_t stream_read(void* ptr, size_t size, size_t nmemb, void* user_data);
size_t stream_write(void* ptr, size_t size, size_t nmemb, void* user_data);
*/
import "C"
import (
	"errors"
	"io"
	"runtime"
	"time"
	"unsafe"
)

// Rules contains a compiled YARA ruleset.
type Rules struct {
	*rules
}

type rules struct {
	cptr *C.YR_RULES
}

// A MatchRule represents a rule successfully matched against a block
// of data.
type MatchRule struct {
	Rule      string
	Namespace string
	Tags      []string
	Meta      map[string]interface{}
	Strings   []MatchString
}

// A MatchString represents a string declared and matched in a rule.
type MatchString struct {
	Name   string
	Offset uint64
	Data   []byte
}

func init() {
	_ = C.yr_initialize()
}

//export newMatch
func newMatch(matches *[]MatchRule, namespace, identifier *C.char) {
	*matches = append(*matches, MatchRule{
		Rule:      C.GoString(identifier),
		Namespace: C.GoString(namespace),
		Tags:      []string{},
		Meta:      map[string]interface{}{},
		Strings:   []MatchString{},
	})
}

//export addMetaInt
func addMetaInt(matches *[]MatchRule, identifier *C.char, value C.int) {
	(*matches)[len(*matches)-1].Meta[C.GoString(identifier)] = int32(value)
}

//export addMetaString
func addMetaString(matches *[]MatchRule, identifier *C.char, value *C.char) {
	(*matches)[len(*matches)-1].Meta[C.GoString(identifier)] = C.GoString(value)
}

//export addMetaBool
func addMetaBool(matches *[]MatchRule, identifier *C.char, value C.int) {
	(*matches)[len(*matches)-1].Meta[C.GoString(identifier)] = bool(value != 0)
}

//export addTag
func addTag(matches *[]MatchRule, tag *C.char) {
	(*matches)[len(*matches)-1].Tags = append((*matches)[len(*matches)-1].Tags, C.GoString(tag))
}

//export addString
func addString(matches *[]MatchRule, identifier *C.char, offset C.uint64_t, data unsafe.Pointer, length C.int) {
	(*matches)[len(*matches)-1].Strings = append(
		(*matches)[len(*matches)-1].Strings,
		MatchString{
			Name:   C.GoString(identifier),
			Offset: uint64(offset),
			Data:   C.GoBytes(data, length),
		})
}

// ScanFlags are used to tweak the behavior of Scan* functions.
type ScanFlags int

const (
	// ScanFlagsFastMode avoids multiple matches of the same string
	// when not necessary.
	ScanFlagsFastMode = C.SCAN_FLAGS_FAST_MODE
	// ScanFlagsProcessMemory causes the scanned data to be
	// interpreted like live, in-prcess memory rather than an on-disk
	// file.
	ScanFlagsProcessMemory = C.SCAN_FLAGS_PROCESS_MEMORY
)

// ScanMem scans an in-memory buffer using the ruleset.
func (r *Rules) ScanMem(buf []byte, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	var ptr *C.uint8_t
	if len(buf) > 0 {
		ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0])))
	}
	err = newError(C.yr_rules_scan_mem(
		r.cptr,
		ptr,
		C.size_t(len(buf)),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// ScanFile scans a file using the ruleset.
func (r *Rules) ScanFile(filename string, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_scan_file(
		r.cptr,
		cfilename,
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// ScanProc scans a live process using the ruleset.
func (r *Rules) ScanProc(pid int, flags int, timeout time.Duration) (matches []MatchRule, err error) {
	err = newError(C.yr_rules_scan_proc(
		r.cptr,
		C.int(pid),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// Save writes a compiled ruleset to filename.
func (r *Rules) Save(filename string) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_save(r.cptr, cfilename))
	return
}

// Write writes a compiled ruleset to an io.Writer.
func (r *Rules) Write(wr io.Writer) (err error) {
	var stream C.YR_STREAM
	stream.user_data = unsafe.Pointer(&wr)
	stream.write = C.YR_STREAM_WRITE_FUNC(C.stream_write)
	err = newError(C.yr_rules_save_stream(r.cptr, &stream))
	return
}

// LoadRules retrieves a compiled ruleset from filename.
func LoadRules(filename string) (*Rules, error) {
	var yrRules *C.YR_RULES
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	if err := newError(C.yr_rules_load(cfilename, &yrRules)); err != nil {
		return nil, err
	}
	r := &Rules{rules: &rules{cptr: yrRules}}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

// ReadRules retrieves a compiled ruleset from an io.Reader
func ReadRules(rd io.Reader) (*Rules, error) {
	var yrRules *C.YR_RULES
	var stream C.YR_STREAM
	stream.user_data = unsafe.Pointer(&rd)
	stream.read = C.YR_STREAM_READ_FUNC(C.stream_read)
	if err := newError(C.yr_rules_load_stream(&stream, &yrRules)); err != nil {
		return nil, err
	}
	r := &Rules{rules: &rules{cptr: yrRules}}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

func (r *rules) finalize() {
	C.yr_rules_destroy(r.cptr)
	runtime.SetFinalizer(r, nil)
}

// Destroy destroys the YARA data structure representing a ruleset.
// Since a Finalizer for the underlying YR_RULES structure is
// automatically set up on creation, it should not be necessary to
// explicitly call this method.
func (r *Rules) Destroy() {
	if r.rules != nil {
		r.rules.finalize()
		r.rules = nil
	}
}

// DefineVariable defines a named variable for use by the compiler.
// Boolean, int64, float64, and string types are supported.
func (r *Rules) DefineVariable(name string, value interface{}) (err error) {
	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))
	switch value.(type) {
	case bool:
		var v int
		if value.(bool) {
			v = 1
		}
		err = newError(C.yr_rules_define_boolean_variable(
			r.cptr, cname, C.int(v)))
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		value := toint64(value)
		err = newError(C.yr_rules_define_integer_variable(
			r.cptr, cname, C.int64_t(value)))
	case float64:
		err = newError(C.yr_rules_define_float_variable(
			r.cptr, cname, C.double(value.(float64))))
	case string:
		cvalue := C.CString(value.(string))
		defer C.free(unsafe.Pointer(cvalue))
		err = newError(C.yr_rules_define_string_variable(
			r.cptr, cname, cvalue))
	default:
		err = errors.New("wrong value type passed to DefineVariable; bool, int64, float64, string are accepted")
	}
	return
}
<commit_msg>Make code a bit clearer. There may be a bug here.<commit_after>// Copyright © 2015 Hilko Bengen <bengen@hilluzination.de>. All rights reserved.
// Use of this source code is governed by the license that can be
// found in the LICENSE file.

// Package yara provides bindings to the YARA library.
package yara

/*
#include <yara.h>

int rules_callback(int message, void *message_data, void *user_data);
size_t stream_read(void* ptr, size_t size, size_t nmemb, void* user_data);
size_t stream_write(void* ptr, size_t size, size_t nmemb, void* user_data);
*/
import "C"
import (
	"errors"
	"io"
	"runtime"
	"time"
	"unsafe"
)

// Rules contains a compiled YARA ruleset.
type Rules struct {
	*rules
}

type rules struct {
	cptr *C.YR_RULES
}

// A MatchRule represents a rule successfully matched against a block
// of data.
type MatchRule struct {
	Rule      string
	Namespace string
	Tags      []string
	Meta      map[string]interface{}
	Strings   []MatchString
}

// A MatchString represents a string declared and matched in a rule.
type MatchString struct {
	Name   string
	Offset uint64
	Data   []byte
}

func init() {
	_ = C.yr_initialize()
}

//export newMatch
func newMatch(matches *[]MatchRule, namespace, identifier *C.char) {
	*matches = append(*matches, MatchRule{
		Rule:      C.GoString(identifier),
		Namespace: C.GoString(namespace),
		Tags:      []string{},
		Meta:      map[string]interface{}{},
		Strings:   []MatchString{},
	})
}

//export addMetaInt
func addMetaInt(matches *[]MatchRule, identifier *C.char, value C.int) {
	i := len(*matches) - 1
	(*matches)[i].Meta[C.GoString(identifier)] = int32(value)
}

//export addMetaString
func addMetaString(matches *[]MatchRule, identifier *C.char, value *C.char) {
	i := len(*matches) - 1
	(*matches)[i].Meta[C.GoString(identifier)] = C.GoString(value)
}

//export addMetaBool
func addMetaBool(matches *[]MatchRule, identifier *C.char, value C.int) {
	i := len(*matches) - 1
	(*matches)[i].Meta[C.GoString(identifier)] = bool(value != 0)
}

//export addTag
func addTag(matches *[]MatchRule, tag *C.char) {
	i := len(*matches) - 1
	(*matches)[i].Tags = append((*matches)[i].Tags, C.GoString(tag))
}

//export addString
func addString(matches *[]MatchRule, identifier *C.char, offset C.uint64_t, data unsafe.Pointer, length C.int) {
	i := len(*matches) - 1
	(*matches)[i].Strings = append(
		(*matches)[i].Strings,
		MatchString{
			Name:   C.GoString(identifier),
			Offset: uint64(offset),
			Data:   C.GoBytes(data, length),
		})
}

// ScanFlags are used to tweak the behavior of Scan* functions.
type ScanFlags int

const (
	// ScanFlagsFastMode avoids multiple matches of the same string
	// when not necessary.
	ScanFlagsFastMode = C.SCAN_FLAGS_FAST_MODE
	// ScanFlagsProcessMemory causes the scanned data to be
	// interpreted like live, in-prcess memory rather than an on-disk
	// file.
	ScanFlagsProcessMemory = C.SCAN_FLAGS_PROCESS_MEMORY
)

// ScanMem scans an in-memory buffer using the ruleset.
func (r *Rules) ScanMem(buf []byte, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	var ptr *C.uint8_t
	if len(buf) > 0 {
		ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0])))
	}
	err = newError(C.yr_rules_scan_mem(
		r.cptr,
		ptr,
		C.size_t(len(buf)),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// ScanFile scans a file using the ruleset.
func (r *Rules) ScanFile(filename string, flags ScanFlags, timeout time.Duration) (matches []MatchRule, err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_scan_file(
		r.cptr,
		cfilename,
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// ScanProc scans a live process using the ruleset.
func (r *Rules) ScanProc(pid int, flags int, timeout time.Duration) (matches []MatchRule, err error) {
	err = newError(C.yr_rules_scan_proc(
		r.cptr,
		C.int(pid),
		C.int(flags),
		C.YR_CALLBACK_FUNC(C.rules_callback),
		unsafe.Pointer(&matches),
		C.int(timeout/time.Second)))
	return
}

// Save writes a compiled ruleset to filename.
func (r *Rules) Save(filename string) (err error) {
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	err = newError(C.yr_rules_save(r.cptr, cfilename))
	return
}

// Write writes a compiled ruleset to an io.Writer.
func (r *Rules) Write(wr io.Writer) (err error) {
	var stream C.YR_STREAM
	stream.user_data = unsafe.Pointer(&wr)
	stream.write = C.YR_STREAM_WRITE_FUNC(C.stream_write)
	err = newError(C.yr_rules_save_stream(r.cptr, &stream))
	return
}

// LoadRules retrieves a compiled ruleset from filename.
func LoadRules(filename string) (*Rules, error) {
	var yrRules *C.YR_RULES
	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))
	if err := newError(C.yr_rules_load(cfilename, &yrRules)); err != nil {
		return nil, err
	}
	r := &Rules{rules: &rules{cptr: yrRules}}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

// ReadRules retrieves a compiled ruleset from an io.Reader
func ReadRules(rd io.Reader) (*Rules, error) {
	var yrRules *C.YR_RULES
	var stream C.YR_STREAM
	stream.user_data = unsafe.Pointer(&rd)
	stream.read = C.YR_STREAM_READ_FUNC(C.stream_read)
	if err := newError(C.yr_rules_load_stream(&stream, &yrRules)); err != nil {
		return nil, err
	}
	r := &Rules{rules: &rules{cptr: yrRules}}
	runtime.SetFinalizer(r.rules, (*rules).finalize)
	return r, nil
}

func (r *rules) finalize() {
	C.yr_rules_destroy(r.cptr)
	runtime.SetFinalizer(r, nil)
}

// Destroy destroys the YARA data structure representing a ruleset.
// Since a Finalizer for the underlying YR_RULES structure is
// automatically set up on creation, it should not be necessary to
// explicitly call this method.
func (r *Rules) Destroy() {
	if r.rules != nil {
		r.rules.finalize()
		r.rules = nil
	}
}

// DefineVariable defines a named variable for use by the compiler.
// Boolean, int64, float64, and string types are supported.
func (r *Rules) DefineVariable(name string, value interface{}) (err error) {
	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))
	switch value.(type) {
	case bool:
		var v int
		if value.(bool) {
			v = 1
		}
		err = newError(C.yr_rules_define_boolean_variable(
			r.cptr, cname, C.int(v)))
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		value := toint64(value)
		err = newError(C.yr_rules_define_integer_variable(
			r.cptr, cname, C.int64_t(value)))
	case float64:
		err = newError(C.yr_rules_define_float_variable(
			r.cptr, cname, C.double(value.(float64))))
	case string:
		cvalue := C.CString(value.(string))
		defer C.free(unsafe.Pointer(cvalue))
		err = newError(C.yr_rules_define_string_variable(
			r.cptr, cname, cvalue))
	default:
		err = errors.New("wrong value type passed to DefineVariable; bool, int64, float64, string are accepted")
	}
	return
}
<|endoftext|>


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

package s3

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/url"
	"strings"
	"time"

	"github.com/alecthomas/template"
	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
)

type Link struct {
	Name         string
	URL          string
	LastModified string
}

func WriteHTML(path string, bucketName string, prefix string, suffix string) error {
	auth, err := aws.EnvAuth()
	if err != nil {
		return err
	}
	client := s3.New(auth, aws.USEast)
	bucket := client.Bucket(bucketName)
	if bucket == nil {
		return fmt.Errorf("Bucket %s not found", bucketName)
	}
	resp, err := bucket.List(prefix, "", "", 0)
	if err != nil {
		return err
	}

	var links []Link
	for _, k := range resp.Contents {
		if strings.HasSuffix(k.Key, suffix) {
			name := k.Key
			urlString := fmt.Sprintf("https://s3.amazonaws.com/%s/%s", bucketName, url.QueryEscape(k.Key))

			lastModfified, err := time.Parse(time.RFC3339, k.LastModified)
			if err != nil {
				return err
			}

			links = append(links, Link{Name: name, URL: urlString, LastModified: lastModfified.Format("Mon Jan _2 15:04:05 2006")})
		}
	}

	return WriteHTMLForLinks(path, bucketName, bucketName, links)
}

func reverse(a []Link) []Link {
	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
		a[left], a[right] = a[right], a[left]
	}
	return a
}

var htmlTemplate = `
<!doctype html>

  <title>{{ .Title }}</title>

{{ .Header }}

  {{ range $index, $value := .Links }}

{{ $value.Name }} {{ $value.LastModified }}

  {{ end }}

`

func WriteHTMLForLinks(path string, title string, header string, links []Link) error {
	vars := map[string]interface{}{
		"Title":  title,
		"Header": header,
		"Links":  reverse(links),
	}

	t, err := template.New("t").Parse(htmlTemplate)
	if err != nil {
		return err
	}

	if path != "" {
		var data bytes.Buffer
		err = t.Execute(&data, vars)
		if err != nil {
			return err
		}
		return ioutil.WriteFile(path, data.Bytes(), 0644)
	}
	return nil
}
<commit_msg>More info for index html<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package s3

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/url"
	"strings"
	"time"

	"github.com/alecthomas/template"
	"github.com/blang/semver"
	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
)

type Release struct {
	Name    string
	URL     string
	Version string
	Date    string
	Commit  string
}

func WriteHTML(path string, bucketName string, prefix string, suffix string) error {
	auth, err := aws.EnvAuth()
	if err != nil {
		return err
	}
	client := s3.New(auth, aws.USEast)
	bucket := client.Bucket(bucketName)
	if bucket == nil {
		return fmt.Errorf("Bucket %s not found", bucketName)
	}
	resp, err := bucket.List(prefix, "", "", 0)
	if err != nil {
		return err
	}

	var releases []Release
	for _, k := range resp.Contents {
		if strings.HasSuffix(k.Key, suffix) {
			name := k.Key
			urlString := fmt.Sprintf("https://s3.amazonaws.com/%s/%s", bucketName, url.QueryEscape(name))
			version, date, commit, err := parseName(name, prefix, suffix)
			if err != nil {
				return err
			}
			releases = append(releases,
				Release{
					Name:    name,
					URL:     urlString,
					Version: version,
					Date:    date.Format("Mon Jan _2 15:04:05 MST 2006"),
					Commit:  commit,
				})
		}
	}

	return WriteHTMLForLinks(path, bucketName, bucketName, releases)
}

func parseName(name string, prefix string, suffix string) (version string, t time.Time, commit string, err error) {
	t = time.Unix(0, 0)

	verstr := name[len(prefix) : len(name)-len(suffix)]
	sversion, err := semver.Make(verstr)
	if err != nil {
		return
	}
	version = fmt.Sprintf("%d.%d.%d", sversion.Major, sversion.Minor, sversion.Patch)

	if len(sversion.Pre) != 1 {
		err = fmt.Errorf("Invalid prerelease")
		return
	}

	commit = strings.Join(sversion.Build, " ")

	d := fmt.Sprintf("%d", sversion.Pre[0].VersionNum)
	t, err = time.Parse("20060102150405", d)
	if err != nil {
		return
	}

	return
}

func reverse(a []Release) []Release {
	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
		a[left], a[right] = a[right], a[left]
	}
	return a
}

var htmlTemplate = `
<!doctype html>

  <title>{{ .Title }}</title>

{{ .Header }}

  {{ range $index, $value := .Releases }}

{{ $value.Name }} {{ $value.Version }} {{ $value.Date }} {{ $value.Commit }}

  {{ end }}

`

func WriteHTMLForLinks(path string, title string, header string, releases []Release) error {
	vars := map[string]interface{}{
		"Title":    title,
		"Header":   header,
		"Releases": reverse(releases),
	}

	t, err := template.New("t").Parse(htmlTemplate)
	if err != nil {
		return err
	}

	if path != "" {
		var data bytes.Buffer
		err = t.Execute(&data, vars)
		if err != nil {
			return err
		}
		return ioutil.WriteFile(path, data.Bytes(), 0644)
	}
	return nil
}
<|endoftext|>


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

package s3

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"sort"
	"strings"
	"time"

	"github.com/alecthomas/template"
	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
	keybase1 "github.com/keybase/client/go/protocol"
	"github.com/keybase/release/update"
	"github.com/keybase/release/version"
)

type Section struct {
	Header   string
	Releases []Release
}

type Release struct {
	Name       string
	Key        s3.Key
	URL        string
	Version    string
	DateString string
	Date       time.Time
	Commit     string
}

type ByRelease []Release

func (s ByRelease) Len() int {
	return len(s)
}

func (s ByRelease) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s ByRelease) Less(i, j int) bool {
	// Reverse date order
	return s[j].Date.Before(s[i].Date)
}

type Client struct {
	s3 *s3.S3
}

func NewClient() (*Client, error) {
	auth, err := aws.EnvAuth()
	if err != nil {
		return nil, err
	}
	s3 := s3.New(auth, aws.USEast)
	return &Client{s3: s3}, nil
}

func convertEastern(t time.Time) time.Time {
	locationNewYork, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Printf("Couldn't load location: %s", err)
	}
	return t.In(locationNewYork)
}

func loadReleases(keys []s3.Key, bucketName string, prefix string, suffix string, truncate int) []Release {
	var releases []Release
	for _, k := range keys {
		if strings.HasSuffix(k.Key, suffix) {
			urlString, name := urlStringForKey(k, bucketName, prefix)
			version, date, commit, err := version.Parse(name)
			if err != nil {
				log.Printf("Couldn't get version from name: %s\n", name)
			}
			date = convertEastern(date)
			releases = append(releases,
				Release{
					Name:       name,
					Key:        k,
					URL:        urlString,
					Version:    version,
					Date:       date,
					DateString: date.Format("Mon Jan _2 15:04:05 MST 2006"),
					Commit:     commit,
				})
		}
	}
	// TODO: Should also sanity check that version sort is same as time sort
	// otherwise something got messed up
	sort.Sort(ByRelease(releases))
	if truncate > 0 && len(releases) > truncate {
		releases = releases[0:truncate]
	}
	return releases
}

func WriteHTML(path string, bucketName string, prefixes string, suffix string) error {
	client, err := NewClient()
	if err != nil {
		return err
	}
	bucket := client.s3.Bucket(bucketName)
	if bucket == nil {
		return fmt.Errorf("Bucket %s not found", bucketName)
	}

	var sections []Section
	for _, prefix := range strings.Split(prefixes, ",") {
		resp, err := bucket.List(prefix, "", "", 0)
		if err != nil {
			return err
		}

		releases := loadReleases(resp.Contents, bucketName, prefix, suffix, 20)
		if len(releases) > 0 {
			log.Printf("Found %d release(s) at %s\n", len(releases), prefix)
			for _, release := range releases {
				log.Printf(" %s %s %s\n", release.Name, release.Version, release.DateString)
			}
		}
		sections = append(sections, Section{
			Header:   prefix,
			Releases: releases,
		})
	}

	return WriteHTMLForLinks(path, bucketName, sections)
}

var htmlTemplate = `
<!doctype html>

  <title>{{ .Title }}</title>

	{{ range $index, $sec := .Sections }}

{{ $sec.Header }}

		{{ range $index2, $rel := $sec.Releases }}

{{ $rel.Name }} {{ $rel.Version }} {{ $rel.Date }} {{ $rel.Commit }}

		{{ end }}

	{{ end }}

`

func WriteHTMLForLinks(path string, title string, sections []Section) error {
	vars := map[string]interface{}{
		"Title":    title,
		"Sections": sections,
	}

	t, err := template.New("t").Parse(htmlTemplate)
	if err != nil {
		return err
	}

	if path != "" {
		var data bytes.Buffer
		err = t.Execute(&data, vars)
		if err != nil {
			return err
		}
		err := makeParentDirs(path)
		if err != nil {
			return err
		}
		return ioutil.WriteFile(path, data.Bytes(), 0644)
	}
	return nil
}

type Platform struct {
	Name          string
	Prefix        string
	PrefixSupport string
	Suffix        string
	LatestName    string
}

func CopyLatest(bucketName string) error {
	client, err := NewClient()
	if err != nil {
		return err
	}
	return client.CopyLatest(bucketName)
}

func Platforms() []Platform {
	return []Platform{
		Platform{Name: "darwin", Prefix: "darwin/", PrefixSupport: "darwin-support/", LatestName: "Keybase.dmg"},
		Platform{Name: "deb", Prefix: "linux_binaries/deb/", Suffix: "_amd64.deb", LatestName: "keybase_amd64.deb"},
		Platform{Name: "rpm", Prefix: "linux_binaries/rpm/", Suffix: ".x86_64.rpm", LatestName: "keybase_amd64.rpm"},
		Platform{Name: "windows", Prefix: "windows/", Suffix: ".386.exe", LatestName: "keybase_setup_386.exe"},
	}
}

func FindPlatform(name string) *Platform {
	platforms := Platforms()
	for _, p := range platforms {
		if p.Name == name {
			return &p
		}
	}
	return nil
}

func (p *Platform) FindRelease(bucket s3.Bucket, f func(r Release) bool) (*Release, error) {
	resp, err := bucket.List(p.Prefix, "", "", 0)
	if err != nil {
		return nil, err
	}
	releases := loadReleases(resp.Contents, bucket.Name, p.Prefix, p.Suffix, 0)
	for _, release := range releases {
		k := release.Key
		if !strings.HasSuffix(k.Key, p.Suffix) {
			continue
		}
		if f(release) {
			return &release, nil
		}
	}
	return nil, nil
}

func (c *Client) CopyLatest(bucketName string) error {
	bucket := c.s3.Bucket(bucketName)

	platforms := Platforms()

	for _, platform := range platforms {
		release, err := platform.FindRelease(*bucket, func(r Release) bool { return true })
		if err != nil {
			return err
		}
		if release == nil {
			continue
		}
		k := release.Key
		url, _ := urlStringForKey(k, bucketName, platform.Prefix)
		// Instead of linking, we're making copies. S3 linking has some issues.
		// headers := map[string][]string{
		// 	"x-amz-website-redirect-location": []string{url},
		// }
		//err = bucket.PutHeader(name, []byte{}, headers, s3.PublicRead)
		log.Printf("Copying %s from %s (latest)\n", platform.LatestName, k.Key)
		_, err = bucket.PutCopy(platform.LatestName, s3.PublicRead, s3.CopyOptions{}, url)
		if err != nil {
			return err
		}
	}
	return nil
}

func (c *Client) CurrentUpdate(bucketName string, platform string, env string) (currentUpdate *keybase1.Update, err error) {
	bucket := c.s3.Bucket(bucketName)

	data, err := bucket.Get(fmt.Sprintf("update-%s-%s.json", platform, env))
	if err != nil {
		return
	}
	currentUpdate, err = update.DecodeJSON(data)
	return
}

func PromoteRelease(bucketName string, delay time.Duration, hourEastern int, channel string, platform string, env string) (*Release, error) {
	client, err := NewClient()
	if err != nil {
		return nil, err
	}
	return client.PromoteRelease(bucketName, delay, hourEastern, channel, platform, env)
}

func updateJSONName(channel string, platformName string, env string) string {
	if channel == "" {
		return fmt.Sprintf("update-%s-%s.json", platformName, env)
	}
	return fmt.Sprintf("update-%s-%s-%s.json", platformName, env, channel)
}

func (c *Client) PromoteRelease(bucketName string, delay time.Duration, beforeHourEastern int, channel string, platformName string, env string) (*Release, error) {
	if channel == "" {
		log.Printf("Finding release to promote for public (%s delay, < %dam)", delay, beforeHourEastern)
	} else {
		log.Printf("Finding release to promote for %s channel (%s delay)", channel, delay)
	}
	bucket := c.s3.Bucket(bucketName)

	platform := FindPlatform(platformName)
	if platform == nil {
		return nil, fmt.Errorf("Unsupported platform")
	}
	release, err := platform.FindRelease(*bucket, func(r Release) bool {
		if delay != 0 && time.Since(r.Date) < delay {
			return false
		}
		hour, _, _ := r.Date.Clock()
		if beforeHourEastern != 0 && hour >= beforeHourEastern {
			return false
		}
		return true
	})
	if err != nil {
		return nil, err
	}

	if release == nil {
		return nil, nil
	}
	log.Printf("Found release %s (%s), %s", release.Name, time.Since(release.Date), release.Version)

	jsonName := updateJSONName(channel, platformName, env)
	jsonURL := urlString(bucketName, platform.PrefixSupport, fmt.Sprintf("update-%s-%s-%s.json", platformName, env, release.Version))
	log.Printf("Promoting %s to %s", jsonURL, jsonName)
	_, err = bucket.PutCopy(jsonName, s3.PublicRead, s3.CopyOptions{}, jsonURL)
	if err != nil {
		return nil, err
	}
	return release, nil
}
<commit_msg>Re-enable version check (so we don't re-promote existing)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package s3

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"sort"
	"strings"
	"time"

	"github.com/alecthomas/template"
	"github.com/blang/semver"
	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
	keybase1 "github.com/keybase/client/go/protocol"
	"github.com/keybase/release/update"
	"github.com/keybase/release/version"
)

type Section struct {
	Header   string
	Releases []Release
}

type Release struct {
	Name       string
	Key        s3.Key
	URL        string
	Version    string
	DateString string
	Date       time.Time
	Commit     string
}

type ByRelease []Release

func (s ByRelease) Len() int {
	return len(s)
}

func (s ByRelease) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s ByRelease) Less(i, j int) bool {
	// Reverse date order
	return s[j].Date.Before(s[i].Date)
}

type Client struct {
	s3 *s3.S3
}

func NewClient() (*Client, error) {
	auth, err := aws.EnvAuth()
	if err != nil {
		return nil, err
	}
	s3 := s3.New(auth, aws.USEast)
	return &Client{s3: s3}, nil
}

func convertEastern(t time.Time) time.Time {
	locationNewYork, err := time.LoadLocation("America/New_York")
	if err != nil {
		log.Printf("Couldn't load location: %s", err)
	}
	return t.In(locationNewYork)
}

func loadReleases(keys []s3.Key, bucketName string, prefix string, suffix string, truncate int) []Release {
	var releases []Release
	for _, k := range keys {
		if strings.HasSuffix(k.Key, suffix) {
			urlString, name := urlStringForKey(k, bucketName, prefix)
			version, date, commit, err := version.Parse(name)
			if err != nil {
				log.Printf("Couldn't get version from name: %s\n", name)
			}
			date = convertEastern(date)
			releases = append(releases,
				Release{
					Name:       name,
					Key:        k,
					URL:        urlString,
					Version:    version,
					Date:       date,
					DateString: date.Format("Mon Jan _2 15:04:05 MST 2006"),
					Commit:     commit,
				})
		}
	}
	// TODO: Should also sanity check that version sort is same as time sort
	// otherwise something got messed up
	sort.Sort(ByRelease(releases))
	if truncate > 0 && len(releases) > truncate {
		releases = releases[0:truncate]
	}
	return releases
}

func WriteHTML(path string, bucketName string, prefixes string, suffix string) error {
	client, err := NewClient()
	if err != nil {
		return err
	}
	bucket := client.s3.Bucket(bucketName)
	if bucket == nil {
		return fmt.Errorf("Bucket %s not found", bucketName)
	}

	var sections []Section
	for _, prefix := range strings.Split(prefixes, ",") {
		resp, err := bucket.List(prefix, "", "", 0)
		if err != nil {
			return err
		}

		releases := loadReleases(resp.Contents, bucketName, prefix, suffix, 20)
		if len(releases) > 0 {
			log.Printf("Found %d release(s) at %s\n", len(releases), prefix)
			for _, release := range releases {
				log.Printf(" %s %s %s\n", release.Name, release.Version, release.DateString)
			}
		}
		sections = append(sections, Section{
			Header:   prefix,
			Releases: releases,
		})
	}

	return WriteHTMLForLinks(path, bucketName, sections)
}

var htmlTemplate = `
<!doctype html>

  <title>{{ .Title }}</title>

	{{ range $index, $sec := .Sections }}

{{ $sec.Header }}

		{{ range $index2, $rel := $sec.Releases }}

{{ $rel.Name }} {{ $rel.Version }} {{ $rel.Date }} {{ $rel.Commit }}

		{{ end }}

	{{ end }}

`

func WriteHTMLForLinks(path string, title string, sections []Section) error {
	vars := map[string]interface{}{
		"Title":    title,
		"Sections": sections,
	}

	t, err := template.New("t").Parse(htmlTemplate)
	if err != nil {
		return err
	}

	if path != "" {
		var data bytes.Buffer
		err = t.Execute(&data, vars)
		if err != nil {
			return err
		}
		err := makeParentDirs(path)
		if err != nil {
			return err
		}
		return ioutil.WriteFile(path, data.Bytes(), 0644)
	}
	return nil
}

type Platform struct {
	Name          string
	Prefix        string
	PrefixSupport string
	Suffix        string
	LatestName    string
}

func CopyLatest(bucketName string) error {
	client, err := NewClient()
	if err != nil {
		return err
	}
	return client.CopyLatest(bucketName)
}

func Platforms() []Platform {
	return []Platform{
		Platform{Name: "darwin", Prefix: "darwin/", PrefixSupport: "darwin-support/", LatestName: "Keybase.dmg"},
		Platform{Name: "deb", Prefix: "linux_binaries/deb/", Suffix: "_amd64.deb", LatestName: "keybase_amd64.deb"},
		Platform{Name: "rpm", Prefix: "linux_binaries/rpm/", Suffix: ".x86_64.rpm", LatestName: "keybase_amd64.rpm"},
		Platform{Name: "windows", Prefix: "windows/", Suffix: ".386.exe", LatestName: "keybase_setup_386.exe"},
	}
}

func FindPlatform(name string) *Platform {
	platforms := Platforms()
	for _, p := range platforms {
		if p.Name == name {
			return &p
		}
	}
	return nil
}

func (p *Platform) FindRelease(bucket s3.Bucket, f func(r Release) bool) (*Release, error) {
	resp, err := bucket.List(p.Prefix, "", "", 0)
	if err != nil {
		return nil, err
	}
	releases := loadReleases(resp.Contents, bucket.Name, p.Prefix, p.Suffix, 0)
	for _, release := range releases {
		k := release.Key
		if !strings.HasSuffix(k.Key, p.Suffix) {
			continue
		}
		if f(release) {
			return &release, nil
		}
	}
	return nil, nil
}

func (c *Client) CopyLatest(bucketName string) error {
	bucket := c.s3.Bucket(bucketName)

	platforms := Platforms()

	for _, platform := range platforms {
		release, err := platform.FindRelease(*bucket, func(r Release) bool { return true })
		if err != nil {
			return err
		}
		if release == nil {
			continue
		}
		k := release.Key
		url, _ := urlStringForKey(k, bucketName, platform.Prefix)
		// Instead of linking, we're making copies. S3 linking has some issues.
		// headers := map[string][]string{
		// 	"x-amz-website-redirect-location": []string{url},
		// }
		//err = bucket.PutHeader(name, []byte{}, headers, s3.PublicRead)
		log.Printf("Copying %s from %s (latest)\n", platform.LatestName, k.Key)
		_, err = bucket.PutCopy(platform.LatestName, s3.PublicRead, s3.CopyOptions{}, url)
		if err != nil {
			return err
		}
	}
	return nil
}

func (c *Client) CurrentUpdate(bucketName string, channel string, platformName string, env string) (currentUpdate *keybase1.Update, err error) {
	bucket := c.s3.Bucket(bucketName)

	data, err := bucket.Get(updateJSONName(channel, platformName, env))
	if err != nil {
		return
	}
	currentUpdate, err = update.DecodeJSON(data)
	return
}

func PromoteRelease(bucketName string, delay time.Duration, hourEastern int, channel string, platform string, env string) (*Release, error) {
	client, err := NewClient()
	if err != nil {
		return nil, err
	}
	return client.PromoteRelease(bucketName, delay, hourEastern, channel, platform, env)
}

func updateJSONName(channel string, platformName string, env string) string {
	if channel == "" {
		return fmt.Sprintf("update-%s-%s.json", platformName, env)
	}
	return fmt.Sprintf("update-%s-%s-%s.json", platformName, env, channel)
}

func (c *Client) PromoteRelease(bucketName string, delay time.Duration, beforeHourEastern int, channel string, platformName string, env string) (*Release, error) {
	if channel == "" {
		log.Printf("Finding release to promote for public (%s delay, < %dam)", delay, beforeHourEastern)
	} else {
		log.Printf("Finding release to promote for %s channel (%s delay)", channel, delay)
	}
	bucket := c.s3.Bucket(bucketName)

	platform := FindPlatform(platformName)
	if platform == nil {
		return nil, fmt.Errorf("Unsupported platform")
	}
	release, err := platform.FindRelease(*bucket, func(r Release) bool {
		if delay != 0 && time.Since(r.Date) < delay {
			return false
		}
		hour, _, _ := r.Date.Clock()
		if beforeHourEastern != 0 && hour >= beforeHourEastern {
			return false
		}
		return true
	})
	if err != nil {
		return nil, err
	}

	if release == nil {
		log.Printf("No matching release found")
		return nil, nil
	}
	log.Printf("Found release %s (%s), %s", release.Name, time.Since(release.Date), release.Version)

	currentUpdate, err := c.CurrentUpdate(bucketName, channel, platformName, env)
	if err != nil {
		log.Printf("Error looking for current update: %s", err)
	}
	if currentUpdate != nil {
		log.Printf("Found update: %s", currentUpdate.Version)
		currentVer, err := semver.Make(currentUpdate.Version)
		if err != nil {
			return nil, err
		}
		releaseVer, err := semver.Make(release.Version)
		if err != nil {
			return nil, err
		}

		if releaseVer.Equals(currentVer) {
			log.Printf("Release unchanged")
			return nil, nil
		} else if releaseVer.LT(currentVer) {
			log.Printf("Release older than current update")
			return nil, nil
		}
	}

	jsonName := updateJSONName(channel, platformName, env)
	jsonURL := urlString(bucketName, platform.PrefixSupport, fmt.Sprintf("update-%s-%s-%s.json", platformName, env, release.Version))
	log.Printf("Promoting %s to %s", jsonURL, jsonName)
	_, err = bucket.PutCopy(jsonName, s3.PublicRead, s3.CopyOptions{}, jsonURL)
	if err != nil {
		return nil, err
	}
	return release, nil
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/astaxie/beego"
    "github.com/lfq7413/tomato/orm"
    "github.com/lfq7413/tomato/utils"
    // "gopkg.in/mgo.v2/bson"
    "encoding/json"
    "log"
    "time"
)

// ObjectsController ...
type ObjectsController struct {
	beego.Controller
}

// Post ...
// @router /:className [post]
func (o *ObjectsController) Post() {
    className := o.Ctx.Input.Param(":className")

    var cls map[string]interface{}
    json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

    objectId := utils.CreateObjectId()
    now := time.Now().UTC()
    cls["objectId"] = objectId
    cls["createdAt"] = now
    cls["updatedAt"] = now

    err := orm.TomatoDB.Insert(className, cls)
    if err != nil {
        log.Fatal(err)
    }

    data := make(map[string]string)
    data["objectId"] = objectId
    data["createdAt"] = utils.TimetoString(now)

	o.Data["json"] = data
	o.ServeJSON()
}

// Get ...
// @router /:className/:objectId [get]
func (o *ObjectsController) Get() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")

    cls := make(map[string]interface{})
    cls["objectId"] = objectId

    data, err := orm.TomatoDB.FindOne(className, cls)
    if err != nil {
        log.Fatal(err)
    }

    delete(data, "_id")
    if createdAt, ok := data["createdAt"].(time.Time); ok{
        data["createdAt"] = utils.TimetoString(createdAt.UTC())
    }
    if updatedAt, ok := data["updatedAt"].(time.Time); ok{
        data["updatedAt"] = utils.TimetoString(updatedAt.UTC())
    }

	o.Data["json"] = data
	o.ServeJSON()
}

// Put ...
// @router /:className/:objectId [put]
func (o *ObjectsController) Put() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")
    data := make(map[string]string)
    data["method"] = "Put"
    data["className"] = className
    data["objectId"] = objectId
	o.Data["json"] = data
	o.ServeJSON()
}

// GetAll ...
// @router /:className [get]
func (o *ObjectsController) GetAll() {
    className := o.Ctx.Input.Param(":className")
    data := make(map[string]string)
    data["method"] = "GetAll"
    data["className"] = className
	o.Data["json"] = data
	o.ServeJSON()
}

// Delete ...
// @router /:className/:objectId [delete]
func (o *ObjectsController) Delete() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")
    data := make(map[string]string)
    data["method"] = "Delete"
    data["className"] = className
    data["objectId"] = objectId
	o.Data["json"] = data
	o.ServeJSON()
}
<commit_msg>修改post请求返回头<commit_after>package controllers

import (
	"github.com/astaxie/beego"
    "github.com/lfq7413/tomato/orm"
    "github.com/lfq7413/tomato/utils"
    // "gopkg.in/mgo.v2/bson"
    "encoding/json"
    "log"
    "time"
)

// ObjectsController ...
type ObjectsController struct {
	beego.Controller
}

// Post ...
// @router /:className [post]
func (o *ObjectsController) Post() {
    className := o.Ctx.Input.Param(":className")

    var cls map[string]interface{}
    json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

    objectId := utils.CreateObjectId()
    now := time.Now().UTC()
    cls["objectId"] = objectId
    cls["createdAt"] = now
    cls["updatedAt"] = now

    err := orm.TomatoDB.Insert(className, cls)
    if err != nil {
        log.Fatal(err)
    }

    data := make(map[string]string)
    data["objectId"] = objectId
    data["createdAt"] = utils.TimetoString(now)

	o.Data["json"] = data
    o.Ctx.Output.SetStatus(201)
    o.Ctx.Output.Header("Location", beego.AppConfig.String("myhttpurl") + "classes/" + className + "/" + objectId)
	o.ServeJSON()
}

// Get ...
// @router /:className/:objectId [get]
func (o *ObjectsController) Get() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")

    cls := make(map[string]interface{})
    cls["objectId"] = objectId

    data, err := orm.TomatoDB.FindOne(className, cls)
    if err != nil {
        log.Fatal(err)
    }

    delete(data, "_id")
    if createdAt, ok := data["createdAt"].(time.Time); ok{
        data["createdAt"] = utils.TimetoString(createdAt.UTC())
    }
    if updatedAt, ok := data["updatedAt"].(time.Time); ok{
        data["updatedAt"] = utils.TimetoString(updatedAt.UTC())
    }

	o.Data["json"] = data
	o.ServeJSON()
}

// Put ...
// @router /:className/:objectId [put]
func (o *ObjectsController) Put() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")
    data := make(map[string]string)
    data["method"] = "Put"
    data["className"] = className
    data["objectId"] = objectId
	o.Data["json"] = data
	o.ServeJSON()
}

// GetAll ...
// @router /:className [get]
func (o *ObjectsController) GetAll() {
    className := o.Ctx.Input.Param(":className")
    data := make(map[string]string)
    data["method"] = "GetAll"
    data["className"] = className
	o.Data["json"] = data
	o.ServeJSON()
}

// Delete ...
// @router /:className/:objectId [delete]
func (o *ObjectsController) Delete() {
    className := o.Ctx.Input.Param(":className")
    objectId := o.Ctx.Input.Param(":objectId")
    data := make(map[string]string)
    data["method"] = "Delete"
    data["className"] = className
    data["objectId"] = objectId
	o.Data["json"] = data
	o.ServeJSON()
}
<|endoftext|>