<commit_before>package main

import (
	"log"
	"time"

	"github.com/d2r2/go-max7219/max7219"
)

func main() {
	mtx := max7219.NewMatrix(1)
	err := mtx.Open(0, 0, 7)
	if err != nil {
		log.Fatal(err)
	}
	defer mtx.Close()
	var font max7219.Font
	// font = max7219.FontCP437
	// font = max7219.FontLCD
	// font = max7219.FontMSXRus
	// font = max7219.FontZXSpectrumRus
	// font = max7219.FontSinclair
	// font = max7219.FontTiny
	// font = max7219.FontVestaPK8000Rus
	font = max7219.FontCP437
	mtx.SlideMessage("Hello world!!! Hey Beavis, let's rock!",
		font, true, 50*time.Millisecond)
	time.Sleep(1 * time.Second)
	font = max7219.FontVestaPK8000Rus
	mtx.SlideMessage("Привет мир!!! Шарик - ты балбес!!!",
		font, true, 50*time.Millisecond)
	time.Sleep(1 * time.Second)
}
<commit_msg>Initial commit<commit_after>package main

import (
	"log"
	"time"

	"github.com/d2r2/go-max7219/max7219"
)

func main() {
	mtx := max7219.NewMatrix(1)
	err := mtx.Open(0, 0, 7)
	if err != nil {
		log.Fatal(err)
	}
	defer mtx.Close()
	var font max7219.Font
	// font = max7219.FontCP437
	// font = max7219.FontLCD
	// font = max7219.FontMSXRus
	// font = max7219.FontZXSpectrumRus
	// font = max7219.FontSinclair
	// font = max7219.FontTiny
	// font = max7219.FontVestaPK8000Rus
	font = max7219.FontCP437
	mtx.SlideMessage("Hello world!!! Hey Beavis, let's rock!",
		font, true, 50*time.Millisecond)
	time.Sleep(1 * time.Second)
	font = max7219.FontZXSpectrumRus
	mtx.SlideMessage("Привет мир!!! Шарик - ты балбес!!!",
		font, true, 50*time.Millisecond)
	time.Sleep(1 * time.Second)
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"sync"
	"time"

	"github.com/seletskiy/hierr"
	"github.com/theairkit/runcmd"
)

type distributedLock struct {
	nodes []*distributedLockNode

	failOnError bool
}

func (lock *distributedLock) addNodeRunner(
	runner runcmd.Runner,
	address address,
) {
	lock.nodes = append(lock.nodes, &distributedLockNode{
		address: address,
		runner:  runner,
	})
}

func (lock *distributedLock) acquire(filename string) error {
	for nodeIndex, node := range lock.nodes {
		tracef(
			"%4d/%d locking node: '%s'",
			nodeIndex+1,
			len(lock.nodes),
			node.String(),
		)

		err := node.lock(filename)
		if err != nil {
			if lock.failOnError {
				warningf(
					hierr.Errorf(
						err,
						`failed to acquire lock, but continuing execution`,
					).Error(),
				)

				continue
			}

			nodes := []string{}
			for _, node := range lock.nodes {
				nodes = append(nodes, node.String())
			}

			return hierr.Errorf(
				err,
				"failed to lock %d nodes: %s",
				len(lock.nodes),
				strings.Join(nodes, ", "),
			)
		}
	}

	return nil
}

func (lock *distributedLock) runHeartbeats(
	period time.Duration,
	canceler *sync.Cond,
) {
	for _, node := range lock.nodes {
		if node.connection != nil {
			go heartbeat(period, node, canceler)
		}
	}
}
<commit_msg>reword error message about lock failure<commit_after>package main

import (
	"strings"
	"sync"
	"time"

	"github.com/seletskiy/hierr"
	"github.com/theairkit/runcmd"
)

type distributedLock struct {
	nodes []*distributedLockNode

	failOnError bool
}

func (lock *distributedLock) addNodeRunner(
	runner runcmd.Runner,
	address address,
) {
	lock.nodes = append(lock.nodes, &distributedLockNode{
		address: address,
		runner:  runner,
	})
}

func (lock *distributedLock) acquire(filename string) error {
	for nodeIndex, node := range lock.nodes {
		tracef(
			"%4d/%d locking node: '%s'",
			nodeIndex+1,
			len(lock.nodes),
			node.String(),
		)

		err := node.lock(filename)
		if err != nil {
			if lock.failOnError {
				warningf(
					hierr.Errorf(
						err,
						`failed to acquire lock, `+
							`but proceeding with execution`,
					).Error(),
				)

				continue
			}

			nodes := []string{}
			for _, node := range lock.nodes {
				nodes = append(nodes, node.String())
			}

			return hierr.Errorf(
				err,
				"failed to lock %d nodes: %s",
				len(lock.nodes),
				strings.Join(nodes, ", "),
			)
		}
	}

	return nil
}

func (lock *distributedLock) runHeartbeats(
	period time.Duration,
	canceler *sync.Cond,
) {
	for _, node := range lock.nodes {
		if node.connection != nil {
			go heartbeat(period, node, canceler)
		}
	}
}
<|endoftext|>


<commit_before>// Package response defines the how the default microservice response must look and behave like.
package response

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

	"github.com/LUSHDigital/microservice-core-golang/pagination"
)

// Standard response statuses.
const (
	StatusOk   = "ok"
	StatusFail = "fail"
)

// Responder - Responder for microservice responses.
type Responder interface {
	// ExtractData returns a particular item of data from the response.
	ExtractData(srcKey string, dst interface{}) error

	// GetCode returns the response code.
	GetCode() int

	// WriteTo writes back to the network connection.
	WriteTo(w http.ResponseWriter) error
}

// Response - A standardised response format for a microservice.
type Response struct {
	Status  string `json:"status"`         // Can be 'ok' or 'fail'
	Code    int    `json:"code"`           // Any valid HTTP response code
	Message string `json:"message"`        // Any relevant message (optional)
	Data    *Data  `json:"data,omitempty"` // Data to pass along to the response (optional)
}

// New returns a new Response for a microservice endpoint
// This ensures that all API endpoints return data in a standardised format:
//
//    {
//       "status": "ok or fail",
//       "code": any HTTP response code,
//       "message": "any relevant message (optional)",
//       "data": {[
//          ...
//       ]}
//    }
func New(code int, message string, data *Data) *Response {
	var status string
	switch {
	case code >= http.StatusOK && code < http.StatusBadRequest:
		status = StatusOk
	default:
		status = StatusFail
	}
	return &Response{
		Code:    code,
		Status:  status,
		Message: message,
		Data:    data,
	}
}

// DBError returns a prepared 503 Service Unavailable response.
func DBError(err error) *Response {
	return DBErrorf("", err)
}

// DBErrorf returns a prepared 503 Service Unavailable response,
// using the user provided formatted message.
func DBErrorf(format string, err error) *Response {
	var msg string
	switch format {
	case "":
		msg = fmt.Sprintf("db error: %v", err)
	default:
		msg = fmt.Sprintf(format, err)
	}
	return New(http.StatusInternalServerError, msg, nil)
}

// SQLError - currently only wraps DBError
//
// Deprecated: This function has been made redundant by the more generic DBError
func SQLError(err error) *Response {
	return DBError(err)
}

// SQLErrorf - currently only wraps DBErrorf
//
// Deprecated: This function has been made redundant by the more generic DBErrorf
func SQLErrorf(format string, err error) *Response {
	return DBErrorf(format, err)
}

// JSONError returns a prepared 422 Unprocessable Entity response if the JSON is found to
// contain syntax errors, or invalid values for types.
func JSONError(err error) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("json error: %v", err), nil)
}

// ParamError returns a prepared 422 Unprocessable Entity response, including the name of
// the failing parameter in the message field of the response object.
func ParamError(name string) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("invalid or missing parameter: %v", name), nil)
}

// ValidationError returns a prepared 422 Unprocessable Entity response, including the name of
// the failing validation/validator in the message field of the response object.
func ValidationError(err error, name string) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("validation error on %s: %v", name, err), nil)
}

// NotFoundErr returns a prepared 404 Not Found response, including the message passed by the user
// in the message field of the response object.
func NotFoundErr(msg string) *Response {
	return New(http.StatusNotFound, msg, nil)
}

// ConflictErr returns a prepared 409 Conflict response, including the message passed by the user
// in the message field of the response object.
func ConflictErr(msg string) *Response {
	return New(http.StatusConflict, msg, nil)
}

// InternalError returns a prepared 500 Internal Server Error, including the error
// message in the message field of the response object
func InternalError(err error) *Response {
	return New(http.StatusInternalServerError, fmt.Sprintf("internal server error: %v", err), nil)
}

// WriteTo - pick a response writer to write the default json response to.
func (r *Response) WriteTo(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(r.Code)

	// Don't attempt to write a body for 204s.
	if r.Code == http.StatusNoContent {
		return nil
	}

	j, err := json.Marshal(r)
	if err != nil {
		return err
	}
	_, err = w.Write(j)
	return err
}

// ExtractData returns a particular item of data from the response.
func (r *Response) ExtractData(srcKey string, dst interface{}) error {
	if !r.Data.Valid() {
		return fmt.Errorf("invalid data provided: %v", r.Data)
	}
	for key, value := range r.Data.Map() {
		if key != srcKey {
			continue
		}

		// Get the raw JSON just for the endpoints.
		rawJSON, err := json.Marshal(value)
		if err != nil {
			return err
		}

		// Decode the raw JSON.
		json.Unmarshal(rawJSON, &dst)
	}

	return nil
}

// GetCode returns the response code.
func (r *Response) GetCode() int {
	return r.Code
}

// PaginatedResponse - A paginated response format for a microservice.
type PaginatedResponse struct {
	Status     string               `json:"status"`         // Can be 'ok' or 'fail'
	Code       int                  `json:"code"`           // Any valid HTTP response code
	Message    string               `json:"message"`        // Any relevant message (optional)
	Data       *Data                `json:"data,omitempty"` // Data to pass along to the response (optional)
	Pagination *pagination.Response `json:"pagination"`     // Pagination data
}

// NewPaginated returns a new PaginatedResponse for a microservice endpoint
func NewPaginated(paginator *pagination.Paginator, code int, message string, data *Data) *PaginatedResponse {
	var status string
	switch {
	case code >= http.StatusOK && code < http.StatusBadRequest:
		status = StatusOk
	default:
		status = StatusFail
	}
	return &PaginatedResponse{
		Code:       code,
		Status:     status,
		Message:    message,
		Data:       data,
		Pagination: paginator.PrepareResponse(),
	}
}

// WriteTo - pick a response writer to write the default json response to.
func (p *PaginatedResponse) WriteTo(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(p.Code)

	// Don't attempt to write a body for 204s.
	if p.Code == http.StatusNoContent {
		return nil
	}

	j, err := json.Marshal(p)
	if err != nil {
		return err
	}
	_, err = w.Write(j)
	return err
}

// ExtractData returns a particular item of data from the response.
func (p *PaginatedResponse) ExtractData(srcKey string, dst interface{}) error {
	if !p.Data.Valid() {
		return fmt.Errorf("invalid data provided: %v", p.Data)
	}
	for key, value := range p.Data.Map() {
		if key != srcKey {
			continue
		}

		// Get the raw JSON just for the endpoints.
		rawJSON, err := json.Marshal(value)
		if err != nil {
			return err
		}

		// Decode the raw JSON.
		json.Unmarshal(rawJSON, &dst)
	}

	return nil
}

// GetCode returns the response code.
func (p *PaginatedResponse) GetCode() int {
	return p.Code
}

// Data represents the collection data the the response will return to the consumer.
// Type ends up being the name of the key containing the collection of Content
type Data struct {
	Type    string
	Content interface{}
}

// UnmarshalJSON implements the Unmarshaler interface
// this implementation will fill the type in the case we're been provided a valid single collection
// and set the content to the contents of said collection.
// for every other options, it behaves like normal.
// Despite the fact that we are not supposed to marshal without a type set,
// this is purposefully left open to unmarshal without a collection name set, in case you may want to set it later,
// and for interop with other systems which may not send the collection properly.
func (d *Data) UnmarshalJSON(b []byte) error {
	if err := json.Unmarshal(b, &d.Content); err != nil {
		log.Printf("cannot unmarshal data: %v", err)
	}

	data, ok := d.Content.(map[string]interface{})
	if !ok {
		return nil
	}
	// count how many collections were provided
	var count int
	for _, value := range data {
		switch value.(type) {
		case map[string]interface{}, []interface{}:
			count++
		}
	}
	if count > 1 {
		// we can stop there since this is not a single collection
		return nil
	}
	for key, value := range data {
		switch value.(type) {
		case map[string]interface{}, []interface{}:
			d.Type = key
			d.Content = data[key]
		}
	}

	return nil
}

// Valid ensures the Data passed to the response is correct (it must contain a Type along with the data).
func (d *Data) Valid() bool {
	return d.Type != ""
}

// MarshalJSON implements the Marshaler interface and is there to ensure the output
// is correct when we return data to the consumer
func (d *Data) MarshalJSON() ([]byte, error) {
	return json.Marshal(d.Map())
}

// Map returns a version of the data as a map
func (d *Data) Map() map[string]interface{} {
	if !d.Valid() {
		return nil
	}
	d.Type = strings.Replace(strings.ToLower(d.Type), " ", "-", -1)

	return map[string]interface{}{
		d.Type: d.Content,
	}
}
<commit_msg>Response returns 503 as intended instead of 500<commit_after>// Package response defines the how the default microservice response must look and behave like.
package response

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

	"github.com/LUSHDigital/microservice-core-golang/pagination"
)

// Standard response statuses.
const (
	StatusOk   = "ok"
	StatusFail = "fail"
)

// Responder - Responder for microservice responses.
type Responder interface {
	// ExtractData returns a particular item of data from the response.
	ExtractData(srcKey string, dst interface{}) error

	// GetCode returns the response code.
	GetCode() int

	// WriteTo writes back to the network connection.
	WriteTo(w http.ResponseWriter) error
}

// Response - A standardised response format for a microservice.
type Response struct {
	Status  string `json:"status"`         // Can be 'ok' or 'fail'
	Code    int    `json:"code"`           // Any valid HTTP response code
	Message string `json:"message"`        // Any relevant message (optional)
	Data    *Data  `json:"data,omitempty"` // Data to pass along to the response (optional)
}

// New returns a new Response for a microservice endpoint
// This ensures that all API endpoints return data in a standardised format:
//
//    {
//       "status": "ok or fail",
//       "code": any HTTP response code,
//       "message": "any relevant message (optional)",
//       "data": {[
//          ...
//       ]}
//    }
func New(code int, message string, data *Data) *Response {
	var status string
	switch {
	case code >= http.StatusOK && code < http.StatusBadRequest:
		status = StatusOk
	default:
		status = StatusFail
	}
	return &Response{
		Code:    code,
		Status:  status,
		Message: message,
		Data:    data,
	}
}

// DBError returns a prepared 503 Service Unavailable response.
func DBError(err error) *Response {
	return DBErrorf("", err)
}

// DBErrorf returns a prepared 503 Service Unavailable response,
// using the user provided formatted message.
func DBErrorf(format string, err error) *Response {
	var msg string
	switch format {
	case "":
		msg = fmt.Sprintf("db error: %v", err)
	default:
		msg = fmt.Sprintf(format, err)
	}
	return New(http.StatusServiceUnavailable, msg, nil)
}

// SQLError - currently only wraps DBError
//
// Deprecated: This function has been made redundant by the more generic DBError
func SQLError(err error) *Response {
	return DBError(err)
}

// SQLErrorf - currently only wraps DBErrorf
//
// Deprecated: This function has been made redundant by the more generic DBErrorf
func SQLErrorf(format string, err error) *Response {
	return DBErrorf(format, err)
}

// JSONError returns a prepared 422 Unprocessable Entity response if the JSON is found to
// contain syntax errors, or invalid values for types.
func JSONError(err error) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("json error: %v", err), nil)
}

// ParamError returns a prepared 422 Unprocessable Entity response, including the name of
// the failing parameter in the message field of the response object.
func ParamError(name string) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("invalid or missing parameter: %v", name), nil)
}

// ValidationError returns a prepared 422 Unprocessable Entity response, including the name of
// the failing validation/validator in the message field of the response object.
func ValidationError(err error, name string) *Response {
	return New(http.StatusUnprocessableEntity, fmt.Sprintf("validation error on %s: %v", name, err), nil)
}

// NotFoundErr returns a prepared 404 Not Found response, including the message passed by the user
// in the message field of the response object.
func NotFoundErr(msg string) *Response {
	return New(http.StatusNotFound, msg, nil)
}

// ConflictErr returns a prepared 409 Conflict response, including the message passed by the user
// in the message field of the response object.
func ConflictErr(msg string) *Response {
	return New(http.StatusConflict, msg, nil)
}

// InternalError returns a prepared 500 Internal Server Error, including the error
// message in the message field of the response object
func InternalError(err error) *Response {
	return New(http.StatusInternalServerError, fmt.Sprintf("internal server error: %v", err), nil)
}

// WriteTo - pick a response writer to write the default json response to.
func (r *Response) WriteTo(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(r.Code)

	// Don't attempt to write a body for 204s.
	if r.Code == http.StatusNoContent {
		return nil
	}

	j, err := json.Marshal(r)
	if err != nil {
		return err
	}
	_, err = w.Write(j)
	return err
}

// ExtractData returns a particular item of data from the response.
func (r *Response) ExtractData(srcKey string, dst interface{}) error {
	if !r.Data.Valid() {
		return fmt.Errorf("invalid data provided: %v", r.Data)
	}
	for key, value := range r.Data.Map() {
		if key != srcKey {
			continue
		}

		// Get the raw JSON just for the endpoints.
		rawJSON, err := json.Marshal(value)
		if err != nil {
			return err
		}

		// Decode the raw JSON.
		json.Unmarshal(rawJSON, &dst)
	}

	return nil
}

// GetCode returns the response code.
func (r *Response) GetCode() int {
	return r.Code
}

// PaginatedResponse - A paginated response format for a microservice.
type PaginatedResponse struct {
	Status     string               `json:"status"`         // Can be 'ok' or 'fail'
	Code       int                  `json:"code"`           // Any valid HTTP response code
	Message    string               `json:"message"`        // Any relevant message (optional)
	Data       *Data                `json:"data,omitempty"` // Data to pass along to the response (optional)
	Pagination *pagination.Response `json:"pagination"`     // Pagination data
}

// NewPaginated returns a new PaginatedResponse for a microservice endpoint
func NewPaginated(paginator *pagination.Paginator, code int, message string, data *Data) *PaginatedResponse {
	var status string
	switch {
	case code >= http.StatusOK && code < http.StatusBadRequest:
		status = StatusOk
	default:
		status = StatusFail
	}
	return &PaginatedResponse{
		Code:       code,
		Status:     status,
		Message:    message,
		Data:       data,
		Pagination: paginator.PrepareResponse(),
	}
}

// WriteTo - pick a response writer to write the default json response to.
func (p *PaginatedResponse) WriteTo(w http.ResponseWriter) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(p.Code)

	// Don't attempt to write a body for 204s.
	if p.Code == http.StatusNoContent {
		return nil
	}

	j, err := json.Marshal(p)
	if err != nil {
		return err
	}
	_, err = w.Write(j)
	return err
}

// ExtractData returns a particular item of data from the response.
func (p *PaginatedResponse) ExtractData(srcKey string, dst interface{}) error {
	if !p.Data.Valid() {
		return fmt.Errorf("invalid data provided: %v", p.Data)
	}
	for key, value := range p.Data.Map() {
		if key != srcKey {
			continue
		}

		// Get the raw JSON just for the endpoints.
		rawJSON, err := json.Marshal(value)
		if err != nil {
			return err
		}

		// Decode the raw JSON.
		json.Unmarshal(rawJSON, &dst)
	}

	return nil
}

// GetCode returns the response code.
func (p *PaginatedResponse) GetCode() int {
	return p.Code
}

// Data represents the collection data the the response will return to the consumer.
// Type ends up being the name of the key containing the collection of Content
type Data struct {
	Type    string
	Content interface{}
}

// UnmarshalJSON implements the Unmarshaler interface
// this implementation will fill the type in the case we're been provided a valid single collection
// and set the content to the contents of said collection.
// for every other options, it behaves like normal.
// Despite the fact that we are not supposed to marshal without a type set,
// this is purposefully left open to unmarshal without a collection name set, in case you may want to set it later,
// and for interop with other systems which may not send the collection properly.
func (d *Data) UnmarshalJSON(b []byte) error {
	if err := json.Unmarshal(b, &d.Content); err != nil {
		log.Printf("cannot unmarshal data: %v", err)
	}

	data, ok := d.Content.(map[string]interface{})
	if !ok {
		return nil
	}
	// count how many collections were provided
	var count int
	for _, value := range data {
		switch value.(type) {
		case map[string]interface{}, []interface{}:
			count++
		}
	}
	if count > 1 {
		// we can stop there since this is not a single collection
		return nil
	}
	for key, value := range data {
		switch value.(type) {
		case map[string]interface{}, []interface{}:
			d.Type = key
			d.Content = data[key]
		}
	}

	return nil
}

// Valid ensures the Data passed to the response is correct (it must contain a Type along with the data).
func (d *Data) Valid() bool {
	return d.Type != ""
}

// MarshalJSON implements the Marshaler interface and is there to ensure the output
// is correct when we return data to the consumer
func (d *Data) MarshalJSON() ([]byte, error) {
	return json.Marshal(d.Map())
}

// Map returns a version of the data as a map
func (d *Data) Map() map[string]interface{} {
	if !d.Valid() {
		return nil
	}
	d.Type = strings.Replace(strings.ToLower(d.Type), " ", "-", -1)

	return map[string]interface{}{
		d.Type: d.Content,
	}
}
<|endoftext|>


<commit_before>package junos

import (
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/Juniper/go-netconf/netconf"
	"io/ioutil"
	"log"
)

// Session holds the connection information to our Junos device.
type Session struct {
	Conn *netconf.Session
}

// rollbackXML parses our rollback diff configuration.
type rollbackXML struct {
	XMLName xml.Name `xml:"rollback-information"`
	Config  string   `xml:"configuration-information>configuration-output"`
}

// CommandXML parses our operational command responses.
type commandXML struct {
	Config string `xml:",innerxml"`
}

// NewSession establishes a new connection to a Junos device that we will use
// to run our commands against.
func NewSession(host, user, password string) *Session {
	s, err := netconf.DialSSH(host, netconf.SSHConfigPassword(user, password))
	if err != nil {
		log.Fatal(err)
	}

	return &Session{
		Conn: s,
	}
}

// Commit commits the configuration.
func (s *Session) Commit() error {
	reply, err := s.Conn.Exec(rpcCommand["commit"])
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Lock locks the candidate configuration.
func (s *Session) Lock() error {
	reply, err := s.Conn.Exec(rpcCommand["lock"])
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Unlock unlocks the candidate configuration.
func (s *Session) Unlock() error {
	resp, err := s.Conn.Exec(rpcCommand["unlock"])
	if err != nil {
		log.Fatal(err)
	}

	if resp.Ok == false {
		for _, m := range resp.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Configure loads a configuration file in "set" format.
func (s *Session) Configure(file string) error {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	command := fmt.Sprintf(rpcCommand["configure-set"], string(data))
	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// RollbackConfig loads and commits the configuration of a given rollback or rescue state.
func (s *Session) RollbackConfig(option interface{}) error {
	var command string
	switch option.(type) {
	case int:
		command = fmt.Sprintf(rpcCommand["rollback-config"], option)
	case string:
		command = fmt.Sprintf(rpcCommand["rescue-config"])
	}

	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	err = s.Commit()
	if err != nil {
		return err
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// RollbackDiff compares the current active configuration to a given rollback configuration.
func (s *Session) RollbackDiff(compare int) (string, error) {
	rb := &rollbackXML{}
	command := fmt.Sprintf(rpcCommand["get-rollback-information-compare"], compare)
	reply, err := s.Conn.Exec(command)

	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return "", errors.New(m.Message)
		}
	}

	err = xml.Unmarshal([]byte(reply.Data), rb)
	if err != nil {
		log.Fatal(err)
	}

	return rb.Config, nil
}

// Command runs any operational mode command, such as "show" or "request."
// Format is either "text" or "xml".
func (s *Session) Command(cmd, format string) (string, error) {
	c := &commandXML{}
	var command string

	switch format {
	case "xml":
		command = fmt.Sprintf(rpcCommand["command-xml"], cmd)
	default:
		command = fmt.Sprintf(rpcCommand["command"], cmd)
	}
	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return "", errors.New(m.Message)
		}
	}

	err = xml.Unmarshal([]byte(reply.Data), &c)
	if err != nil {
		log.Fatal(err)
	}

	if c.Config == "" {
		return "No output available.", nil
	}

	return c.Config, nil
}

// Close disconnects our session to the device.
func (s *Session) Close() {
	s.Conn.Close()
}
<commit_msg>Updated documentation<commit_after>package junos

import (
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/Juniper/go-netconf/netconf"
	"io/ioutil"
	"log"
)

// Session holds the connection information to our Junos device.
type Session struct {
	Conn *netconf.Session
}

// rollbackXML parses our rollback diff configuration.
type rollbackXML struct {
	XMLName xml.Name `xml:"rollback-information"`
	Config  string   `xml:"configuration-information>configuration-output"`
}

// CommandXML parses our operational command responses.
type commandXML struct {
	Config string `xml:",innerxml"`
}

// NewSession establishes a new connection to a Junos device that we will use
// to run our commands against.
func NewSession(host, user, password string) *Session {
	s, err := netconf.DialSSH(host, netconf.SSHConfigPassword(user, password))
	if err != nil {
		log.Fatal(err)
	}

	return &Session{
		Conn: s,
	}
}

// Commit commits the configuration.
func (s *Session) Commit() error {
	reply, err := s.Conn.Exec(rpcCommand["commit"])
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Lock locks the candidate configuration.
func (s *Session) Lock() error {
	reply, err := s.Conn.Exec(rpcCommand["lock"])
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Unlock unlocks the candidate configuration.
func (s *Session) Unlock() error {
	resp, err := s.Conn.Exec(rpcCommand["unlock"])
	if err != nil {
		log.Fatal(err)
	}

	if resp.Ok == false {
		for _, m := range resp.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// Configure loads a given configuration file where the commands are
// in "set" format.
func (s *Session) Configure(file string) error {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	command := fmt.Sprintf(rpcCommand["configure-set"], string(data))
	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// RollbackConfig loads and commits the configuration of a given rollback or rescue state.
func (s *Session) RollbackConfig(option interface{}) error {
	var command string
	switch option.(type) {
	case int:
		command = fmt.Sprintf(rpcCommand["rollback-config"], option)
	case string:
		command = fmt.Sprintf(rpcCommand["rescue-config"])
	}

	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	err = s.Commit()
	if err != nil {
		return err
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return errors.New(m.Message)
		}
	}

	return nil
}

// RollbackDiff compares the current active configuration to a given rollback configuration.
func (s *Session) RollbackDiff(compare int) (string, error) {
	rb := &rollbackXML{}
	command := fmt.Sprintf(rpcCommand["get-rollback-information-compare"], compare)
	reply, err := s.Conn.Exec(command)

	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return "", errors.New(m.Message)
		}
	}

	err = xml.Unmarshal([]byte(reply.Data), rb)
	if err != nil {
		log.Fatal(err)
	}

	return rb.Config, nil
}

// Command runs any operational mode command, such as "show" or "request."
// Format is either "text" or "xml".
func (s *Session) Command(cmd, format string) (string, error) {
	c := &commandXML{}
	var command string

	switch format {
	case "xml":
		command = fmt.Sprintf(rpcCommand["command-xml"], cmd)
	default:
		command = fmt.Sprintf(rpcCommand["command"], cmd)
	}
	reply, err := s.Conn.Exec(command)
	if err != nil {
		log.Fatal(err)
	}

	if reply.Ok == false {
		for _, m := range reply.Errors {
			return "", errors.New(m.Message)
		}
	}

	err = xml.Unmarshal([]byte(reply.Data), &c)
	if err != nil {
		log.Fatal(err)
	}

	if c.Config == "" {
		return "No output available.", nil
	}

	return c.Config, nil
}

// Close disconnects our session to the device.
func (s *Session) Close() {
	s.Conn.Close()
}
<|endoftext|>


<commit_before>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// EventResponse is sent by the charm store in response to charm-event requests.
type EventResponse struct {
	Kind     string   `json:"kind"`
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
	Time     string   `json:"time,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// NotFoundError represents an error indicating that the requested data wasn't found.
type NotFoundError struct {
	msg string
}

func (e *NotFoundError) Error() string {
	return e.msg
}

// CharmStore is a Repository that provides access to the public juju charm store.
type CharmStore struct {
	baseURL string
}

//var Store = &CharmStore{"https://store.juju.ubuntu.com"}
var Store = &CharmStore{"http://localhost:8080"}

// Info returns details for a charm in the charm store.
func (s *CharmStore) Info(curl *URL) (*InfoResponse, error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return nil, err
	}
	info, found := infos[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(info.Errors) == 1 && info.Errors[0] == "entry not found" {
		return nil, &NotFoundError{fmt.Sprintf("charm not found: %s", curl)}
	}
	return info, nil
}

// Event returns details for a charm event in the charm store.
//
// If digest is empty, the latest event is returned.
func (s *CharmStore) Event(curl *URL, digest string) (*EventResponse, error) {
	key := curl.String()
	query := key
	if digest != "" {
		query += "@" + digest
	}
	resp, err := http.Get(s.baseURL + "/charm-event?charms=" + url.QueryEscape(query))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	events := make(map[string]*EventResponse)
	if err = json.Unmarshal(body, &events); err != nil {
		return nil, err
	}
	event, found := events[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(event.Errors) == 1 && event.Errors[0] == "entry not found" {
		if digest == "" {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q", curl)}
		} else {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q with digest %q", curl, digest)}
		}
	}
	return event, nil
}

// revision returns the revision and SHA256 digest of the charm referenced by curl.
func (s *CharmStore) revision(curl *URL) (revision int, digest string, err error) {
	info, err := s.Info(curl)
	if err != nil {
		return 0, "", err
	}
	for _, w := range info.Warnings {
		log.Warningf("charm: charm store reports for %q: %s", curl, w)
	}
	if info.Errors != nil {
		return 0, "", fmt.Errorf("charm info errors for %q: %s", curl, strings.Join(info.Errors, "; "))
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *CharmStore) Latest(curl *URL) (int, error) {
	rev, _, err := s.revision(curl.WithRevision(-1))
	return rev, err
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	h := sha256.New()
	if _, err := io.Copy(h, f); err != nil {
		return err
	}
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
func (s *CharmStore) Get(curl *URL) (Charm, error) {
	cachePath := config.JujuHomePath("cache")
	if err := os.MkdirAll(cachePath, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.revision(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(cachePath, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(cachePath, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series. For example:
//
//   /path/to/repository/oneiric/mongodb/
//   /path/to/repository/precise/mongodb.charm
//   /path/to/repository/precise/wordpress/
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return &NotFoundError{fmt.Sprintf("no repository found at %q", path)}
}

func charmNotFound(curl *URL, repoPath string) error {
	return &NotFoundError{fmt.Sprintf("no charms found matching %q in %s", curl, repoPath)}
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl, r.Path)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Warningf("charm: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl, r.Path)
}
<commit_msg>Fix debugging left-over.<commit_after>package charm

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// InfoResponse is sent by the charm store in response to charm-info requests.
type InfoResponse struct {
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Sha256   string   `json:"sha256,omitempty"`
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
}

// EventResponse is sent by the charm store in response to charm-event requests.
type EventResponse struct {
	Kind     string   `json:"kind"`
	Revision int      `json:"revision"` // Zero is valid. Can't omitempty.
	Digest   string   `json:"digest,omitempty"`
	Errors   []string `json:"errors,omitempty"`
	Warnings []string `json:"warnings,omitempty"`
	Time     string   `json:"time,omitempty"`
}

// Repository respresents a collection of charms.
type Repository interface {
	Get(curl *URL) (Charm, error)
	Latest(curl *URL) (int, error)
}

// NotFoundError represents an error indicating that the requested data wasn't found.
type NotFoundError struct {
	msg string
}

func (e *NotFoundError) Error() string {
	return e.msg
}

// CharmStore is a Repository that provides access to the public juju charm store.
type CharmStore struct {
	baseURL string
}

var Store = &CharmStore{"https://store.juju.ubuntu.com"}

// Info returns details for a charm in the charm store.
func (s *CharmStore) Info(curl *URL) (*InfoResponse, error) {
	key := curl.String()
	resp, err := http.Get(s.baseURL + "/charm-info?charms=" + url.QueryEscape(key))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	infos := make(map[string]*InfoResponse)
	if err = json.Unmarshal(body, &infos); err != nil {
		return nil, err
	}
	info, found := infos[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(info.Errors) == 1 && info.Errors[0] == "entry not found" {
		return nil, &NotFoundError{fmt.Sprintf("charm not found: %s", curl)}
	}
	return info, nil
}

// Event returns details for a charm event in the charm store.
//
// If digest is empty, the latest event is returned.
func (s *CharmStore) Event(curl *URL, digest string) (*EventResponse, error) {
	key := curl.String()
	query := key
	if digest != "" {
		query += "@" + digest
	}
	resp, err := http.Get(s.baseURL + "/charm-event?charms=" + url.QueryEscape(query))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	events := make(map[string]*EventResponse)
	if err = json.Unmarshal(body, &events); err != nil {
		return nil, err
	}
	event, found := events[key]
	if !found {
		return nil, fmt.Errorf("charm: charm store returned response without charm %q", key)
	}
	if len(event.Errors) == 1 && event.Errors[0] == "entry not found" {
		if digest == "" {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q", curl)}
		} else {
			return nil, &NotFoundError{fmt.Sprintf("charm event not found for %q with digest %q", curl, digest)}
		}
	}
	return event, nil
}

// revision returns the revision and SHA256 digest of the charm referenced by curl.
func (s *CharmStore) revision(curl *URL) (revision int, digest string, err error) {
	info, err := s.Info(curl)
	if err != nil {
		return 0, "", err
	}
	for _, w := range info.Warnings {
		log.Warningf("charm: charm store reports for %q: %s", curl, w)
	}
	if info.Errors != nil {
		return 0, "", fmt.Errorf("charm info errors for %q: %s", curl, strings.Join(info.Errors, "; "))
	}
	return info.Revision, info.Sha256, nil
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (s *CharmStore) Latest(curl *URL) (int, error) {
	rev, _, err := s.revision(curl.WithRevision(-1))
	return rev, err
}

// verify returns an error unless a file exists at path with a hex-encoded
// SHA256 matching digest.
func verify(path, digest string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	h := sha256.New()
	if _, err := io.Copy(h, f); err != nil {
		return err
	}
	if hex.EncodeToString(h.Sum(nil)) != digest {
		return fmt.Errorf("bad SHA256 of %q", path)
	}
	return nil
}

// Get returns the charm referenced by curl.
func (s *CharmStore) Get(curl *URL) (Charm, error) {
	cachePath := config.JujuHomePath("cache")
	if err := os.MkdirAll(cachePath, 0755); err != nil {
		return nil, err
	}
	rev, digest, err := s.revision(curl)
	if err != nil {
		return nil, err
	}
	if curl.Revision == -1 {
		curl = curl.WithRevision(rev)
	} else if curl.Revision != rev {
		return nil, fmt.Errorf("charm: store returned charm with wrong revision for %q", curl.String())
	}
	path := filepath.Join(cachePath, Quote(curl.String())+".charm")
	if verify(path, digest) != nil {
		resp, err := http.Get(s.baseURL + "/charm/" + url.QueryEscape(curl.Path()))
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		f, err := ioutil.TempFile(cachePath, "charm-download")
		if err != nil {
			return nil, err
		}
		dlPath := f.Name()
		_, err = io.Copy(f, resp.Body)
		if cerr := f.Close(); err == nil {
			err = cerr
		}
		if err != nil {
			os.Remove(dlPath)
			return nil, err
		}
		if err := os.Rename(dlPath, path); err != nil {
			return nil, err
		}
	}
	if err := verify(path, digest); err != nil {
		return nil, err
	}
	return ReadBundle(path)
}

// LocalRepository represents a local directory containing subdirectories
// named after an Ubuntu series, each of which contains charms targeted for
// that series. For example:
//
//   /path/to/repository/oneiric/mongodb/
//   /path/to/repository/precise/mongodb.charm
//   /path/to/repository/precise/wordpress/
type LocalRepository struct {
	Path string
}

// Latest returns the latest revision of the charm referenced by curl, regardless
// of the revision set on curl itself.
func (r *LocalRepository) Latest(curl *URL) (int, error) {
	ch, err := r.Get(curl.WithRevision(-1))
	if err != nil {
		return 0, err
	}
	return ch.Revision(), nil
}

func repoNotFound(path string) error {
	return &NotFoundError{fmt.Sprintf("no repository found at %q", path)}
}

func charmNotFound(curl *URL, repoPath string) error {
	return &NotFoundError{fmt.Sprintf("no charms found matching %q in %s", curl, repoPath)}
}

func mightBeCharm(info os.FileInfo) bool {
	if info.IsDir() {
		return !strings.HasPrefix(info.Name(), ".")
	}
	return strings.HasSuffix(info.Name(), ".charm")
}

// Get returns a charm matching curl, if one exists. If curl has a revision of
// -1, it returns the latest charm that matches curl. If multiple candidates
// satisfy the foregoing, the first one encountered will be returned.
func (r *LocalRepository) Get(curl *URL) (Charm, error) {
	if curl.Schema != "local" {
		return nil, fmt.Errorf("local repository got URL with non-local schema: %q", curl)
	}
	info, err := os.Stat(r.Path)
	if err != nil {
		if os.IsNotExist(err) {
			err = repoNotFound(r.Path)
		}
		return nil, err
	}
	if !info.IsDir() {
		return nil, repoNotFound(r.Path)
	}
	path := filepath.Join(r.Path, curl.Series)
	infos, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, charmNotFound(curl, r.Path)
	}
	var latest Charm
	for _, info := range infos {
		if !mightBeCharm(info) {
			continue
		}
		chPath := filepath.Join(path, info.Name())
		if ch, err := Read(chPath); err != nil {
			log.Warningf("charm: failed to load charm at %q: %s", chPath, err)
		} else if ch.Meta().Name == curl.Name {
			if ch.Revision() == curl.Revision {
				return ch, nil
			}
			if latest == nil || ch.Revision() > latest.Revision() {
				latest = ch
			}
		}
	}
	if curl.Revision == -1 && latest != nil {
		return latest, nil
	}
	return nil, charmNotFound(curl, r.Path)
}
<|endoftext|>


<commit_before>// Response package provides the core functionality of handling
// the client connection, chunked response and other features
package response
import (
	"net"
	"log"
	"net/http"
	"bufio"
	"fmt"
	"os"
	"crypto/md5"
	"io"
	"strconv"
	"encoding/json"
	"encoding/hex"
	"time"
	header "github.com/DronRathore/goexpress/header"
	cookie "github.com/DronRathore/goexpress/cookie"
	utils "github.com/DronRathore/go-mimes"
)

type NextFunc func(NextFunc)

// Response Structure extends basic http.ResponseWriter interface
// It encapsulates Header and Cookie class for direct access
type Response struct{
	response http.ResponseWriter
	Header *header.Header
	Cookie *cookie.Cookie
	Locals map[string]interface{}
	writer *bufio.ReadWriter
	connection net.Conn
	ended bool
	props *map[string]interface{}
	url string
	method string
}
// Intialise the Response Struct, requires the Hijacked buffer,
// connection and Response interface
func (res *Response) Init(rs http.ResponseWriter, r *http.Request, w *bufio.ReadWriter, con net.Conn, props *map[string]interface{}) *Response{
	res.response = rs
	res.writer = w
	res.connection = con
	res.Header = &header.Header{}
	res.Header.Init(rs, r, w)
	res.Cookie = &cookie.Cookie{}
	res.Cookie.Init(res, r)
	res.Locals = make(map[string]interface{})
	res.url = r.URL.Path
	res.ended = false
	res.props = props
	res.method = r.Method
	return res
}

// This function is for internal Use by Cookie Struct
func (res *Response) AddCookie(key string, value string){
	res.Header.AppendCookie(key, value)
}

// Writes a string content to the buffer and immediately flushes the same
func (res *Response) Write(content string) *Response{
	if res.Header.BasicSent() == false && res.Header.CanSendHeader() == true {
		res.Cookie.Finish()
		if sent := res.Header.FlushHeaders(); sent == false {
			log.Print("Failed to push headers")
		}
	}
	var bytes = []byte(content)
	res.WriteBytes(bytes)
	return res
}

// Writes an array of bytes to the socket
func (res *Response) WriteBytes(bytes []byte) *Response {
	var chunkSize = fmt.Sprintf("%x", len(bytes))
	res.writer.WriteString(chunkSize + "\r\n")
	res.writer.Write(bytes)
	res.writer.WriteString("\r\n")
	res.writer.Flush()
	return res
}

func (res *Response) sendContent(status int, content_type string, content []byte) {
	if res.Header.BasicSent() == false {
		res.Header.SetStatus(status)
	}
	if res.Header.CanSendHeader() == true {
		res.Header.Set("Content-Type", content_type)
		res.Cookie.Finish()
		if sent := res.Header.FlushHeaders(); sent == false {
			log.Print("Failed to write headers")
		}
	}
	var chunkSize = fmt.Sprintf("%x", len(content))
	res.writer.WriteString(chunkSize + "\r\n")
	res.writer.Write(content)
	res.writer.WriteString("\r\n")
	res.writer.Writer.Flush()
	res.End()
}
// Reads a file in buffer and writes it to the socket
// It also checks with the existing E-Tags list
// so as to provide caching.
func (res *Response) SendFile(url string, noCache bool) bool {
	if len(url) == 0 {
		// no need to panic ?
		return false
	}
	file, err := os.OpenFile(url, os.O_RDONLY, 0644)
	if err != nil {
		// panic and return false
		log.Print("File not found ", url, err)
		res.Header.SetStatus(404)
		res.Header.FlushHeaders()
		res.End()
		return false
	}
	stat, err := file.Stat()
	if err != nil {
		log.Print("Couldn't get fstat of ", url)
		return false
	}
	if stat.IsDir() == true {
		// cannot send dir, abort
		return false
	}
	var modTime = stat.ModTime().Unix()
	var currTime = (time.Now()).Format(time.RFC1123)
	var etag = res.Header.GetRequestHeader("If-None-Match")
	var ext = utils.GetMimeType(url)
	if res.Header.CanSendHeader() {
		if ext == "" {
			res.Header.Set("Content-Type", "none")
		} else {
			res.Header.Set("Content-Type", ext)
		}
	}
	if noCache == false {
		hasher := md5.New()
		io.WriteString(hasher, strconv.FormatInt(modTime, 10))
		hash := hex.EncodeToString(hasher.Sum(nil))
		var miss bool = true
		// do we have an etag
		if len(etag) == 1 {
			if etag[0] == hash {
				// its a hit!
				if res.Header.CanSendHeader() == true {
					res.Header.SetStatus(304)
					res.Header.Set("Cache-Control", "max-age=300000")
					miss = false
				} else {
					res.End()
					log.Print("Cannot write header after being sent")
					return false
				}
			} // a miss
		}

		if miss == true {
			if res.Header.CanSendHeader() == true {
				res.Header.Set("Etag", hash)
			} else {
				res.End()
				log.Print("Cannot write header after being flushed")
				return false
			}
		}

		if res.Header.CanSendHeader() == true {
			res.Header.Set("Date", currTime)
			res.Cookie.Finish()
			res.Header.FlushHeaders()
		} else {
			res.End()
			log.Print("Cannot write header after being flushed")
			return false
		}
		if miss == false {
			// empty response for cache hit
			res.End()
			return true
		}
	} else {
		res.Cookie.Finish()
		res.Header.FlushHeaders()
	}

	var offset int64 = 0
	// async read and write
	var reader NextFunc
	var channel = make(chan bool)
	reader = func(reader NextFunc){
		go func(channel chan bool){
			var data = make([]byte, 1500)
			n, err := file.ReadAt(data, offset)
			if err != nil {
				if err == io.EOF {
					res.WriteBytes(data[:n])
					res.End()
					channel<-true
					return
				}
				log.Print("Error while reading ", url, err)
				res.End()
				channel<-true
				return
			} else {
				if n == 0 {
					res.End()
					channel<-true
					return
				}
				res.WriteBytes(data)
				offset = offset + int64(n)
				reader(reader)
				return
			}
		}(channel)
	}
	reader(reader)
	<-channel
	return true
}
// Send a download file to the client
func (res *Response) Download(path string, file_name string) bool {
	if res.Header.CanSendHeader() == true {
		res.Header.Set("Content-Disposition", "attachment; filename=\"" + file_name+ "\"")
		return res.SendFile(path, false)
	} else {
		log.Print("Cannot Send header after being flushed")
		res.End()
		return false
	}
}

// Ends a response and drops the connection with client
func (res *Response) End(){
	res.writer.WriteString("0\r\n\r\n")
	res.writer.Flush()
	err := res.connection.Close()
	res.ended = true
	if err != nil {
		log.Print("Couldn't close the connection, already lost?")
	} else if (*res.props)["log"] == true {
		log.Print(res.method, " ", res.url, " ", res.Header.StatusCode)
	}
}

// Redirects a request, takes the url as the Location
func (res *Response) Redirect(url string) *Response{
	res.Header.SetStatus(301)
	res.Header.Set("Location", url)
	res.Header.FlushHeaders()
	res.ended = true
	res.End()
	return res
}

// An internal package use function to check the state of connection
func (res *Response) HasEnded() bool{
	return res.ended
}

// A helper for middlewares to get the original http.ResponseWriter
func (res *Response) GetRaw () http.ResponseWriter{
	return res.response
}

// A helper for middlewares to get the original net.Conn
func (res *Response) GetConnection () net.Conn {
	return res.connection
}

// A helper for middlewares to get the original Request buffer
func (res *Response) GetBuffer () *bufio.ReadWriter {
	return res.writer
}

// Send Error, takes HTTP status and a string content
func (res *Response) Error (status int, str string) {
	res.sendContent(status, "text/html", []byte(str))
}

// Send JSON response, takes interface as input
func (res *Response) JSON(content interface{}){
	output, err := json.Marshal(content)
	if err != nil {
		res.sendContent(500, "application/json", []byte(""))
	} else {
		res.sendContent(200, "application/json", output)
	}
}
<commit_msg>[bug] Fix cookie flush bug on redirect<commit_after>// Response package provides the core functionality of handling
// the client connection, chunked response and other features
package response
import (
	"net"
	"log"
	"net/http"
	"bufio"
	"fmt"
	"os"
	"crypto/md5"
	"io"
	"strconv"
	"encoding/json"
	"encoding/hex"
	"time"
	header "github.com/DronRathore/goexpress/header"
	cookie "github.com/DronRathore/goexpress/cookie"
	utils "github.com/DronRathore/go-mimes"
)

type NextFunc func(NextFunc)

// Response Structure extends basic http.ResponseWriter interface
// It encapsulates Header and Cookie class for direct access
type Response struct{
	response http.ResponseWriter
	Header *header.Header
	Cookie *cookie.Cookie
	Locals map[string]interface{}
	writer *bufio.ReadWriter
	connection net.Conn
	ended bool
	props *map[string]interface{}
	url string
	method string
}
// Intialise the Response Struct, requires the Hijacked buffer,
// connection and Response interface
func (res *Response) Init(rs http.ResponseWriter, r *http.Request, w *bufio.ReadWriter, con net.Conn, props *map[string]interface{}) *Response{
	res.response = rs
	res.writer = w
	res.connection = con
	res.Header = &header.Header{}
	res.Header.Init(rs, r, w)
	res.Cookie = &cookie.Cookie{}
	res.Cookie.Init(res, r)
	res.Locals = make(map[string]interface{})
	res.url = r.URL.Path
	res.ended = false
	res.props = props
	res.method = r.Method
	return res
}

// This function is for internal Use by Cookie Struct
func (res *Response) AddCookie(key string, value string){
	res.Header.AppendCookie(key, value)
}

// Writes a string content to the buffer and immediately flushes the same
func (res *Response) Write(content string) *Response{
	if res.Header.BasicSent() == false && res.Header.CanSendHeader() == true {
		res.Cookie.Finish()
		if sent := res.Header.FlushHeaders(); sent == false {
			log.Print("Failed to push headers")
		}
	}
	var bytes = []byte(content)
	res.WriteBytes(bytes)
	return res
}

// Writes an array of bytes to the socket
func (res *Response) WriteBytes(bytes []byte) *Response {
	var chunkSize = fmt.Sprintf("%x", len(bytes))
	res.writer.WriteString(chunkSize + "\r\n")
	res.writer.Write(bytes)
	res.writer.WriteString("\r\n")
	res.writer.Flush()
	return res
}

func (res *Response) sendContent(status int, content_type string, content []byte) {
	if res.Header.BasicSent() == false {
		res.Header.SetStatus(status)
	}
	if res.Header.CanSendHeader() == true {
		res.Header.Set("Content-Type", content_type)
		res.Cookie.Finish()
		if sent := res.Header.FlushHeaders(); sent == false {
			log.Print("Failed to write headers")
		}
	}
	var chunkSize = fmt.Sprintf("%x", len(content))
	res.writer.WriteString(chunkSize + "\r\n")
	res.writer.Write(content)
	res.writer.WriteString("\r\n")
	res.writer.Writer.Flush()
	res.End()
}
// Reads a file in buffer and writes it to the socket
// It also checks with the existing E-Tags list
// so as to provide caching.
func (res *Response) SendFile(url string, noCache bool) bool {
	if len(url) == 0 {
		// no need to panic ?
		return false
	}
	file, err := os.OpenFile(url, os.O_RDONLY, 0644)
	if err != nil {
		// panic and return false
		log.Print("File not found ", url, err)
		res.Header.SetStatus(404)
		res.Header.FlushHeaders()
		res.End()
		return false
	}
	stat, err := file.Stat()
	if err != nil {
		log.Print("Couldn't get fstat of ", url)
		return false
	}
	if stat.IsDir() == true {
		// cannot send dir, abort
		return false
	}
	var modTime = stat.ModTime().Unix()
	var currTime = (time.Now()).Format(time.RFC1123)
	var etag = res.Header.GetRequestHeader("If-None-Match")
	var ext = utils.GetMimeType(url)
	if res.Header.CanSendHeader() {
		if ext == "" {
			res.Header.Set("Content-Type", "none")
		} else {
			res.Header.Set("Content-Type", ext)
		}
	}
	if noCache == false {
		hasher := md5.New()
		io.WriteString(hasher, strconv.FormatInt(modTime, 10))
		hash := hex.EncodeToString(hasher.Sum(nil))
		var miss bool = true
		// do we have an etag
		if len(etag) == 1 {
			if etag[0] == hash {
				// its a hit!
				if res.Header.CanSendHeader() == true {
					res.Header.SetStatus(304)
					res.Header.Set("Cache-Control", "max-age=300000")
					miss = false
				} else {
					res.End()
					log.Print("Cannot write header after being sent")
					return false
				}
			} // a miss
		}

		if miss == true {
			if res.Header.CanSendHeader() == true {
				res.Header.Set("Etag", hash)
			} else {
				res.End()
				log.Print("Cannot write header after being flushed")
				return false
			}
		}

		if res.Header.CanSendHeader() == true {
			res.Header.Set("Date", currTime)
			res.Cookie.Finish()
			res.Header.FlushHeaders()
		} else {
			res.End()
			log.Print("Cannot write header after being flushed")
			return false
		}
		if miss == false {
			// empty response for cache hit
			res.End()
			return true
		}
	} else {
		res.Cookie.Finish()
		res.Header.FlushHeaders()
	}

	var offset int64 = 0
	// async read and write
	var reader NextFunc
	var channel = make(chan bool)
	reader = func(reader NextFunc){
		go func(channel chan bool){
			var data = make([]byte, 1500)
			n, err := file.ReadAt(data, offset)
			if err != nil {
				if err == io.EOF {
					res.WriteBytes(data[:n])
					res.End()
					channel<-true
					return
				}
				log.Print("Error while reading ", url, err)
				res.End()
				channel<-true
				return
			} else {
				if n == 0 {
					res.End()
					channel<-true
					return
				}
				res.WriteBytes(data)
				offset = offset + int64(n)
				reader(reader)
				return
			}
		}(channel)
	}
	reader(reader)
	<-channel
	return true
}
// Send a download file to the client
func (res *Response) Download(path string, file_name string) bool {
	if res.Header.CanSendHeader() == true {
		res.Header.Set("Content-Disposition", "attachment; filename=\"" + file_name+ "\"")
		return res.SendFile(path, false)
	} else {
		log.Print("Cannot Send header after being flushed")
		res.End()
		return false
	}
}

// Ends a response and drops the connection with client
func (res *Response) End(){
	res.writer.WriteString("0\r\n\r\n")
	res.writer.Flush()
	err := res.connection.Close()
	res.ended = true
	if err != nil {
		log.Print("Couldn't close the connection, already lost?")
	} else if (*res.props)["log"] == true {
		log.Print(res.method, " ", res.url, " ", res.Header.StatusCode)
	}
}

// Redirects a request, takes the url as the Location
func (res *Response) Redirect(url string) *Response{
	res.Header.SetStatus(301)
	res.Header.Set("Location", url)
	res.Cookie.Finish()
	res.Header.FlushHeaders()
	res.ended = true
	res.End()
	return res
}

// An internal package use function to check the state of connection
func (res *Response) HasEnded() bool{
	return res.ended
}

// A helper for middlewares to get the original http.ResponseWriter
func (res *Response) GetRaw () http.ResponseWriter{
	return res.response
}

// A helper for middlewares to get the original net.Conn
func (res *Response) GetConnection () net.Conn {
	return res.connection
}

// A helper for middlewares to get the original Request buffer
func (res *Response) GetBuffer () *bufio.ReadWriter {
	return res.writer
}

// Send Error, takes HTTP status and a string content
func (res *Response) Error (status int, str string) {
	res.sendContent(status, "text/html", []byte(str))
}

// Send JSON response, takes interface as input
func (res *Response) JSON(content interface{}){
	output, err := json.Marshal(content)
	if err != nil {
		res.sendContent(500, "application/json", []byte(""))
	} else {
		res.sendContent(200, "application/json", output)
	}
}
<|endoftext|>


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

// The template uses the function "code" to inject program
// source into the output by extracting code from files and
// injecting them as HTML-escaped
 blocks.
//
// The syntax is simple: 1, 2, or 3 space-separated arguments:
//
// Whole file:
//	{{code "foo.go"}}
// One line (here the signature of main):
//	{{code "foo.go" `/^func.main/`}}
// Block of text, determined by start and end (here the body of main):
//	{{code "foo.go" `/^func.main/` `/^}/`
//
// Patterns can be `/regular expression/`, a decimal number, or "$"
// to signify the end of the file.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"text/template"
)

func Usage() {
	fmt.Fprintf(os.Stderr, "usage: tmpltohtml file\n")
	os.Exit(2)
}

func main() {
	flag.Usage = Usage
	flag.Parse()
	if len(flag.Args()) != 1 {
		Usage()
	}

	// Read and parse the input.
	name := flag.Args()[0]
	tmpl := template.New(name).Funcs(template.FuncMap{"code": code})
	if _, err := tmpl.ParseFiles(name); err != nil {
		log.Fatal(err)
	}

	// Execute the template.
	if err := tmpl.Execute(os.Stdout, 0); err != nil {
		log.Fatal(err)
	}
}

// contents reads a file by name and returns its contents as a string.
func contents(name string) string {
	file, err := ioutil.ReadFile(name)
	if err != nil {
		log.Fatal(err)
	}
	return string(file)
}

// format returns a textual representation of the arg, formatted according to its nature.
func format(arg interface{}) string {
	switch arg := arg.(type) {
	case int:
		return fmt.Sprintf("%d", arg)
	case string:
		if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
			return fmt.Sprintf("%#q", arg)
		}
		return fmt.Sprintf("%q", arg)
	default:
		log.Fatalf("unrecognized argument: %v type %T", arg, arg)
	}
	return ""
}

func code(file string, arg ...interface{}) (string, error) {
	text := contents(file)
	var command string
	switch len(arg) {
	case 0:
		// text is already whole file.
		command = fmt.Sprintf("code %q", file)
	case 1:
		command = fmt.Sprintf("code %q %s", file, format(arg[0]))
		text = oneLine(file, text, arg[0])
	case 2:
		command = fmt.Sprintf("code %q %s %s", file, format(arg[0]), format(arg[1]))
		text = multipleLines(file, text, arg[0], arg[1])
	default:
		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
	}
	// Replace tabs by spaces, which work better in HTML.
	text = strings.Replace(text, "\t", "    ", -1)
	// Escape the program text for HTML.
	text = template.HTMLEscapeString(text)
	// Include the command as a comment.
	text = fmt.Sprintf("
%s
", command, text)
	return text, nil
}

// parseArg returns the integer or string value of the argument and tells which it is.
func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
	switch n := arg.(type) {
	case int:
		if n <= 0 || n > max {
			log.Fatalf("%q:%d is out of range", file, n)
		}
		return n, "", true
	case string:
		return 0, n, false
	}
	log.Fatalf("unrecognized argument %v type %T", arg, arg)
	return
}

// oneLine returns the single line generated by a two-argument code invocation.
func oneLine(file, text string, arg interface{}) string {
	lines := strings.SplitAfter(contents(file), "\n")
	line, pattern, isInt := parseArg(arg, file, len(lines))
	if isInt {
		return lines[line-1]
	}
	return lines[match(file, 0, lines, pattern)-1]
}

// multipleLines returns the text generated by a three-argument code invocation.
func multipleLines(file, text string, arg1, arg2 interface{}) string {
	lines := strings.SplitAfter(contents(file), "\n")
	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
	if !isInt1 {
		line1 = match(file, 0, lines, pattern1)
	}
	if !isInt2 {
		line2 = match(file, line1, lines, pattern2)
	} else if line2 < line1 {
		log.Fatal("lines out of order for %q: %d %d", line1, line2)
	}
	return strings.Join(lines[line1-1:line2], "")
}

// match identifies the input line that matches the pattern in a code invocation.
// If start>0, match lines starting there rather than at the beginning.
// The return value is 1-indexed.
func match(file string, start int, lines []string, pattern string) int {
	// $ matches the end of the file.
	if pattern == "$" {
		if len(lines) == 0 {
			log.Fatal("%q: empty file", file)
		}
		return len(lines)
	}
	// /regexp/ matches the line that matches the regexp.
	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
		if err != nil {
			log.Fatal(err)
		}
		for i := start; i < len(lines); i++ {
			if re.MatchString(lines[i]) {
				return i + 1
			}
		}
		log.Fatalf("%s: no match for %#q", file, pattern)
	}
	log.Fatalf("unrecognized pattern: %q", pattern)
	return 0
}
<commit_msg>doc/tmptohtml: output fix<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The template uses the function "code" to inject program
// source into the output by extracting code from files and
// injecting them as HTML-escaped
 blocks.
//
// The syntax is simple: 1, 2, or 3 space-separated arguments:
//
// Whole file:
//	{{code "foo.go"}}
// One line (here the signature of main):
//	{{code "foo.go" `/^func.main/`}}
// Block of text, determined by start and end (here the body of main):
//	{{code "foo.go" `/^func.main/` `/^}/`
//
// Patterns can be `/regular expression/`, a decimal number, or "$"
// to signify the end of the file.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"text/template"
)

func Usage() {
	fmt.Fprintf(os.Stderr, "usage: tmpltohtml file\n")
	os.Exit(2)
}

func main() {
	flag.Usage = Usage
	flag.Parse()
	if len(flag.Args()) != 1 {
		Usage()
	}

	// Read and parse the input.
	name := flag.Args()[0]
	tmpl := template.New(name).Funcs(template.FuncMap{"code": code})
	if _, err := tmpl.ParseFiles(name); err != nil {
		log.Fatal(err)
	}

	// Execute the template.
	if err := tmpl.Execute(os.Stdout, 0); err != nil {
		log.Fatal(err)
	}
}

// contents reads a file by name and returns its contents as a string.
func contents(name string) string {
	file, err := ioutil.ReadFile(name)
	if err != nil {
		log.Fatal(err)
	}
	return string(file)
}

// format returns a textual representation of the arg, formatted according to its nature.
func format(arg interface{}) string {
	switch arg := arg.(type) {
	case int:
		return fmt.Sprintf("%d", arg)
	case string:
		if len(arg) > 2 && arg[0] == '/' && arg[len(arg)-1] == '/' {
			return fmt.Sprintf("%#q", arg)
		}
		return fmt.Sprintf("%q", arg)
	default:
		log.Fatalf("unrecognized argument: %v type %T", arg, arg)
	}
	return ""
}

func code(file string, arg ...interface{}) (string, error) {
	text := contents(file)
	var command string
	switch len(arg) {
	case 0:
		// text is already whole file.
		command = fmt.Sprintf("code %q", file)
	case 1:
		command = fmt.Sprintf("code %q %s", file, format(arg[0]))
		text = oneLine(file, text, arg[0])
	case 2:
		command = fmt.Sprintf("code %q %s %s", file, format(arg[0]), format(arg[1]))
		text = multipleLines(file, text, arg[0], arg[1])
	default:
		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
	}
	// Replace tabs by spaces, which work better in HTML.
	text = strings.Replace(text, "\t", "    ", -1)
	// Escape the program text for HTML.
	text = template.HTMLEscapeString(text)
	// Include the command as a comment.
	text = fmt.Sprintf("
%s
", command, text)
	return text, nil
}

// parseArg returns the integer or string value of the argument and tells which it is.
func parseArg(arg interface{}, file string, max int) (ival int, sval string, isInt bool) {
	switch n := arg.(type) {
	case int:
		if n <= 0 || n > max {
			log.Fatalf("%q:%d is out of range", file, n)
		}
		return n, "", true
	case string:
		return 0, n, false
	}
	log.Fatalf("unrecognized argument %v type %T", arg, arg)
	return
}

// oneLine returns the single line generated by a two-argument code invocation.
func oneLine(file, text string, arg interface{}) string {
	lines := strings.SplitAfter(contents(file), "\n")
	line, pattern, isInt := parseArg(arg, file, len(lines))
	if isInt {
		return lines[line-1]
	}
	return lines[match(file, 0, lines, pattern)-1]
}

// multipleLines returns the text generated by a three-argument code invocation.
func multipleLines(file, text string, arg1, arg2 interface{}) string {
	lines := strings.SplitAfter(contents(file), "\n")
	line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
	line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
	if !isInt1 {
		line1 = match(file, 0, lines, pattern1)
	}
	if !isInt2 {
		line2 = match(file, line1, lines, pattern2)
	} else if line2 < line1 {
		log.Fatalf("lines out of order for %q: %d %d", text, line1, line2)
	}
	return strings.Join(lines[line1-1:line2], "")
}

// match identifies the input line that matches the pattern in a code invocation.
// If start>0, match lines starting there rather than at the beginning.
// The return value is 1-indexed.
func match(file string, start int, lines []string, pattern string) int {
	// $ matches the end of the file.
	if pattern == "$" {
		if len(lines) == 0 {
			log.Fatalf("%q: empty file", file)
		}
		return len(lines)
	}
	// /regexp/ matches the line that matches the regexp.
	if len(pattern) > 2 && pattern[0] == '/' && pattern[len(pattern)-1] == '/' {
		re, err := regexp.Compile(pattern[1 : len(pattern)-1])
		if err != nil {
			log.Fatal(err)
		}
		for i := start; i < len(lines); i++ {
			if re.MatchString(lines[i]) {
				return i + 1
			}
		}
		log.Fatalf("%s: no match for %#q", file, pattern)
	}
	log.Fatalf("unrecognized pattern: %q", pattern)
	return 0
}
<|endoftext|>


<commit_before>package dcnet

import (
	"crypto/rand"
	"crypto/sha256"
	"github.com/lbarman/prifi/prifi-lib/config"
	"gopkg.in/dedis/crypto.v0/abstract"
	"gopkg.in/dedis/onet.v1/log"
)

// Clients compute:
// kappa_i = k_i + h * SUM_j(q_ij), where q_ij = H(p_ij) in group
// c' = k_i + c
//
// Trustees compute:
// sigma_i = SUM_i(q_ij), where q_ij = H(s_ij) in group
//
// Relay compute:
// k_i = SUM_i(kappa_i) - h * (SUM_j(sigma_i))
//     = SUM_i(h * SUM_j(q_ij)) + k_i - h * SUM_j(SUM_i(q_ij))
// c = k_i + c'
//

// Equivocation holds the functions needed for equivocation protection
type EquivocationProtection struct {
	history    abstract.Scalar
	randomness abstract.Cipher
	suite      abstract.Suite
}

// NewEquivocation creates the structure that handle equivocation protection
func NewEquivocation() *EquivocationProtection {
	e := new(EquivocationProtection)
	e.suite = config.CryptoSuite
	e.history = e.suite.Scalar().One()

	randomKey := make([]byte, e.suite.Cipher(nil).KeySize())
	rand.Read(randomKey)
	e.randomness = e.suite.Cipher(randomKey)

	return e
}

func (e *EquivocationProtection) randomScalar() abstract.Scalar {
	return e.suite.Scalar().Pick(e.randomness)
}

func (e *EquivocationProtection) hashInGroup(data []byte) abstract.Scalar {
	return e.suite.Scalar().SetBytes(data)
}

// Update History adds those bits to the history hash chain
func (e *EquivocationProtection) UpdateHistory(data []byte) {
	historyB := e.history.Bytes()
	toBeHashed := make([]byte, len(historyB)+len(data))
	newPayload := sha256.Sum256(toBeHashed)
	e.history.SetBytes(newPayload[:])
}

// a function that takes a payload x, encrypt it as x' = x + k, and returns x' and kappa = k + history * (sum of the (hashes of pads))
func (e *EquivocationProtection) ClientEncryptPayload(slotOwner bool, x []byte, p_j [][]byte) ([]byte, []byte) {

	// hash the pads p_i into q_i
	q_j := make([]abstract.Scalar, len(p_j))
	for trustee_j := range q_j {
		q_j[trustee_j] = e.hashInGroup(p_j[trustee_j])
	}

	// sum of q_i
	sum := e.suite.Scalar().Zero()
	for _, p := range q_j {
		sum = sum.Add(sum, p)
	}

	product := sum.Mul(sum, e.history)

	//we're not the slot owner
	if !slotOwner {
		kappa_i := product
		return x, kappa_i.Bytes()
	}

	k_i := e.randomScalar()
	k_i_bytes := k_i.Bytes()

	// encrypt payload
	for i := range x {
		x[i] ^= k_i_bytes[i%len(k_i_bytes)]
	}

	// compute kappa
	kappa_i := k_i.Add(k_i, product)
	return x, kappa_i.Bytes()
}

// a function that takes returns the byte[] version of sigma_j
func (e *EquivocationProtection) TrusteeGetContribution(s_i [][]byte) []byte {

	// hash the pads p_i into q_i
	q_i := make([]abstract.Scalar, len(s_i))
	for client_i := range q_i {
		q_i[client_i] = e.hashInGroup(s_i[client_i])
	}

	// sum of q_i
	sum := e.suite.Scalar().Zero()
	for _, p := range q_i {
		sum = sum.Add(sum, p)
	}

	kappa_j := sum

	return kappa_j.Bytes()
}

// given all contributions, decodes the payload
func (e *EquivocationProtection) RelayDecode(encryptedPayload []byte, trusteesContributions [][]byte, clientsContributions [][]byte) []byte {

	//reconstitute the abstract.Point values
	trustee_kappa_j := make([]abstract.Scalar, len(trusteesContributions))
	for k, v := range trusteesContributions {
		trustee_kappa_j[k] = e.suite.Scalar().SetBytes(v)
	}
	client_kappa_i := make([]abstract.Scalar, len(clientsContributions))
	for k, v := range clientsContributions {
		client_kappa_i[k] = e.suite.Scalar().SetBytes(v)
	}

	// compute sum of trustees contribs
	sumTrustees := e.suite.Scalar().Zero()
	for _, v := range trustee_kappa_j {
		sumTrustees = sumTrustees.Add(sumTrustees, v)
	}

	// compute sum of clients contribs
	sumClients := e.suite.Scalar().Zero()
	for _, v := range client_kappa_i {
		sumClients = sumClients.Add(sumClients, v)
	}

	prod := sumTrustees.Mul(sumTrustees, e.history)
	k_i := sumClients.Sub(sumClients, prod)

	//now use k to decrypt the payload
	k_bytes := k_i.Bytes()

	if len(k_bytes) == 0 {
		log.Lvl1("Error: Equivocation couldn't recover the k_bytes value")
		log.Lvl1("encryptedPayload:", encryptedPayload)
		for k, v := range trusteesContributions {
			log.Lvl1("trusteesContributions:", v, "mapped to", trustee_kappa_j[k])
		}
		for k, v := range clientsContributions {
			log.Lvl1("clientsContributions:", v, "mapped to", client_kappa_i[k])
		}
		log.Lvl1("sumTrustees:", sumTrustees)
		log.Lvl1("sumClients:", sumClients)
		log.Lvl1("prod:", prod)
		log.Lvl1("k_i:", k_i)
		return make([]byte, 0)
	}

	// decrypt the payload
	for i := range encryptedPayload {
		encryptedPayload[i] ^= k_bytes[i%len(k_bytes)]
	}

	return encryptedPayload
}
<commit_msg>Add logging to Equivocaiton<commit_after>package dcnet

import (
	"crypto/rand"
	"crypto/sha256"
	"github.com/lbarman/prifi/prifi-lib/config"
	"gopkg.in/dedis/crypto.v0/abstract"
	"gopkg.in/dedis/onet.v1/log"
)

// Clients compute:
// kappa_i = k_i + h * SUM_j(q_ij), where q_ij = H(p_ij) in group
// c' = k_i + c
//
// Trustees compute:
// sigma_i = SUM_i(q_ij), where q_ij = H(s_ij) in group
//
// Relay compute:
// k_i = SUM_i(kappa_i) - h * (SUM_j(sigma_i))
//     = SUM_i(h * SUM_j(q_ij)) + k_i - h * SUM_j(SUM_i(q_ij))
// c = k_i + c'
//

// Equivocation holds the functions needed for equivocation protection
type EquivocationProtection struct {
	history    abstract.Scalar
	randomness abstract.Cipher
	suite      abstract.Suite
}

// NewEquivocation creates the structure that handle equivocation protection
func NewEquivocation() *EquivocationProtection {
	e := new(EquivocationProtection)
	e.suite = config.CryptoSuite
	e.history = e.suite.Scalar().One()

	randomKey := make([]byte, e.suite.Cipher(nil).KeySize())
	rand.Read(randomKey)
	e.randomness = e.suite.Cipher(randomKey)

	return e
}

func (e *EquivocationProtection) randomScalar() abstract.Scalar {
	return e.suite.Scalar().Pick(e.randomness)
}

func (e *EquivocationProtection) hashInGroup(data []byte) abstract.Scalar {
	return e.suite.Scalar().SetBytes(data)
}

// Update History adds those bits to the history hash chain
func (e *EquivocationProtection) UpdateHistory(data []byte) {
	historyB := e.history.Bytes()
	toBeHashed := make([]byte, len(historyB)+len(data))
	newPayload := sha256.Sum256(toBeHashed)
	e.history.SetBytes(newPayload[:])
}

// a function that takes a payload x, encrypt it as x' = x + k, and returns x' and kappa = k + history * (sum of the (hashes of pads))
func (e *EquivocationProtection) ClientEncryptPayload(slotOwner bool, x []byte, p_j [][]byte) ([]byte, []byte) {

	// hash the pads p_i into q_i
	q_j := make([]abstract.Scalar, len(p_j))
	for trustee_j := range q_j {
		q_j[trustee_j] = e.hashInGroup(p_j[trustee_j])
	}

	// sum of q_i
	sum := e.suite.Scalar().Zero()
	for _, p := range q_j {
		sum = sum.Add(sum, p)
	}

	product := sum.Mul(sum, e.history)

	//we're not the slot owner
	if !slotOwner {
		kappa_i := product
		return x, kappa_i.Bytes()
	}

	k_i := e.randomScalar()
	k_i_bytes := k_i.Bytes()

	// encrypt payload
	for i := range x {
		x[i] ^= k_i_bytes[i%len(k_i_bytes)]
	}

	// compute kappa
	kappa_i := k_i.Add(k_i, product)
	return x, kappa_i.Bytes()
}

// a function that takes returns the byte[] version of sigma_j
func (e *EquivocationProtection) TrusteeGetContribution(s_i [][]byte) []byte {

	// hash the pads p_i into q_i
	q_i := make([]abstract.Scalar, len(s_i))
	for client_i := range q_i {
		q_i[client_i] = e.hashInGroup(s_i[client_i])
	}

	// sum of q_i
	sum := e.suite.Scalar().Zero()
	for _, p := range q_i {
		sum = sum.Add(sum, p)
	}

	kappa_j := sum

	return kappa_j.Bytes()
}

// given all contributions, decodes the payload
func (e *EquivocationProtection) RelayDecode(encryptedPayload []byte, trusteesContributions [][]byte, clientsContributions [][]byte) []byte {

	//reconstitute the abstract.Point values
	trustee_kappa_j := make([]abstract.Scalar, len(trusteesContributions))
	for k, v := range trusteesContributions {
		trustee_kappa_j[k] = e.suite.Scalar().SetBytes(v)
	}
	client_kappa_i := make([]abstract.Scalar, len(clientsContributions))
	for k, v := range clientsContributions {
		client_kappa_i[k] = e.suite.Scalar().SetBytes(v)
	}

	// compute sum of trustees contribs
	sumTrustees := e.suite.Scalar().Zero()
	for _, v := range trustee_kappa_j {
		sumTrustees = sumTrustees.Add(sumTrustees, v)
	}

	// compute sum of clients contribs
	sumClients := e.suite.Scalar().Zero()
	for _, v := range client_kappa_i {
		log.Lvl1("Adding in", v, "value is now", sumClients)
		sumClients = sumClients.Add(sumClients, v)
	}

	prod := sumTrustees.Mul(sumTrustees, e.history)
	k_i := sumClients.Sub(sumClients, prod)

	//now use k to decrypt the payload
	k_bytes := k_i.Bytes()

	if len(k_bytes) == 0 {
		log.Lvl1("Error: Equivocation couldn't recover the k_bytes value")
		log.Lvl1("encryptedPayload:", encryptedPayload)
		for k, v := range trusteesContributions {
			log.Lvl1("trusteesContributions:", v, "mapped to", trustee_kappa_j[k])
		}
		for k, v := range clientsContributions {
			log.Lvl1("clientsContributions:", v, "mapped to", client_kappa_i[k])
		}
		log.Lvl1("sumTrustees:", sumTrustees)
		log.Lvl1("sumClients:", sumClients)
		log.Lvl1("history:", e.history)
		log.Lvl1("prod:", prod)
		log.Lvl1("k_i:", k_i)
		return make([]byte, 0)
	}

	// decrypt the payload
	for i := range encryptedPayload {
		encryptedPayload[i] ^= k_bytes[i%len(k_bytes)]
	}

	return encryptedPayload
}
<|endoftext|>


<commit_before>package outgoing

import (
	"strings"
)

type Request struct {
	Token       string `json:"token"`
	Timestamp   int    `json:"ts"`
	Text        string `json:"text"`
	TriggerWord string `json:"trigger_word"`
	Subdomain   string `json:"subdomain"`
	ChannelName string `json:"channel_name"`
	UserName    string `json:"user_name"`
}

func (p *Request) Args() []string {

	strArgs := strings.TrimSpace(strings.TrimLeft(p.Text, p.TriggerWord))

	if len(strArgs) == 0 {
		return nil
	}

	var retArgs []string
	args := strings.Split(strArgs, " ")

	for i := 0; i < len(args); i++ {
		s := strings.TrimSpace(args[i])
		if len(s) != 0 {
			retArgs = append(retArgs, s)
		}
	}
	return retArgs
}

type Image struct {
	URL string `json:"url"`
}

type Attachment struct {
	Title  string  `json:"title"`
	Text   string  `json:"text"`
	Color  string  `json:"color"`
	Images []Image `json:"images"`
}

type Response struct {
	Text        string       `json:"text"`
	Attachments []Attachment `json:"attachments"`
}
<commit_msg>fix args issue<commit_after>package outgoing

import (
	"strings"
)

type Request struct {
	Token       string `json:"token"`
	Timestamp   int    `json:"ts"`
	Text        string `json:"text"`
	TriggerWord string `json:"trigger_word"`
	Subdomain   string `json:"subdomain"`
	ChannelName string `json:"channel_name"`
	UserName    string `json:"user_name"`
}

func (p *Request) Args() []string {

	strArgs := strings.TrimSpace(strings.TrimPrefix(p.Text, p.TriggerWord))

	if len(strArgs) == 0 {
		return nil
	}

	var retArgs []string
	args := strings.Split(strArgs, " ")

	for i := 0; i < len(args); i++ {
		s := strings.TrimSpace(args[i])
		if len(s) != 0 {
			retArgs = append(retArgs, s)
		}
	}
	return retArgs
}

type Image struct {
	URL string `json:"url"`
}

type Attachment struct {
	Title  string  `json:"title"`
	Text   string  `json:"text"`
	Color  string  `json:"color"`
	Images []Image `json:"images"`
}

type Response struct {
	Text        string       `json:"text"`
	Attachments []Attachment `json:"attachments"`
}
<|endoftext|>