<commit_before>package container

import (
	"encoding/json"
	"io"
	"time"

	"github.com/Sirupsen/logrus"
	engineapi "github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/events"
	"github.com/docker/swarm-v2/api"
	"github.com/docker/swarm-v2/log"
	"golang.org/x/net/context"
)

// containerController conducts remote operations for a container. All calls
// are mostly naked calls to the client API, seeded with information from
// containerConfig.
type containerController struct {
	container *containerConfig
}

func newContainerController(task *api.Task) (*containerController, error) {
	ctnr, err := newContainerConfig(task)
	if err != nil {
		return nil, err
	}

	return &containerController{
		container: ctnr,
	}, nil
}

func noopPrivilegeFn() (string, error) { return "", nil }

func (c *containerController) pullImage(ctx context.Context, client engineapi.APIClient) error {

	rc, err := client.ImagePull(ctx, c.container.pullOptions(), noopPrivilegeFn)
	if err != nil {
		return err
	}

	dec := json.NewDecoder(rc)
	for {
		m := map[string]interface{}{}
		if err := dec.Decode(&m); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		// TOOD(stevvooe): Report this status somewhere.
		logrus.Debugln("pull progress", m)
	}

	return nil
}

func (c *containerController) create(ctx context.Context, client engineapi.APIClient) error {
	if _, err := client.ContainerCreate(ctx,
		c.container.config(),
		c.container.hostConfig(),
		c.container.networkingConfig(),
		c.container.name()); err != nil {
		return err
	}

	return nil
}

func (c *containerController) start(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerStart(ctx, c.container.name())
}

func (c *containerController) inspect(ctx context.Context, client engineapi.APIClient) (types.ContainerJSON, error) {
	return client.ContainerInspect(ctx, c.container.name())
}

// events issues a call to the events API and returns a channel with all
// events. The stream of events can be shutdown by cancelling the context.
//
// A chan struct{} is returned that will be closed if the event procressing
// fails and needs to be restarted.
func (c *containerController) events(ctx context.Context, client engineapi.APIClient) (<-chan events.Message, <-chan struct{}, error) {
	// TODO(stevvooe): Move this to a single, global event dispatch. For
	// now, we create a connection per container.
	var (
		eventsq = make(chan events.Message)
		closed  = make(chan struct{})
	)

	log.G(ctx).Debugf("waiting on events")
	// TODO(stevvooe): For long running tasks, it is likely that we will have
	// to restart this under failure.
	rc, err := client.Events(ctx, types.EventsOptions{
		Since:   "0",
		Filters: c.container.eventFilter(),
	})
	if err != nil {
		return nil, nil, err
	}

	go func(rc io.ReadCloser) {
		defer rc.Close()
		defer close(closed)

		select {
		case <-ctx.Done():
			// exit
			return
		default:
		}

		dec := json.NewDecoder(rc)

		for {
			var event events.Message
			if err := dec.Decode(&event); err != nil {
				// TODO(stevvooe): This error handling isn't quite right.
				if err == io.EOF {
					return
				}

				log.G(ctx).Errorf("error decoding event: %v", err)
				return
			}

			select {
			case eventsq <- event:
			case <-ctx.Done():
				return
			}
		}
	}(rc)

	return eventsq, closed, nil
}

func (c *containerController) shutdown(ctx context.Context, client engineapi.APIClient) error {
	timeout, err := resolveTimeout(ctx)
	if err != nil {
		return err
	}

	// TODO(stevvooe): Sending Stop isn't quite right. The timeout is actually
	// a grace period between SIGTERM and SIGKILL. We'll have to play with this
	// a little but to figure how much we defer to the engine.
	return client.ContainerStop(ctx, c.container.name(), timeout)
}

func (c *containerController) terminate(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerKill(ctx, c.container.name(), "")
}

func (c *containerController) remove(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerRemove(ctx, types.ContainerRemoveOptions{
		ContainerID:   c.container.name(),
		RemoveVolumes: true,
		Force:         true,
	})
}

// resolveTimeout calculates the timeout for second granularity timeout using
// the context's deadline.
func resolveTimeout(ctx context.Context) (int, error) {
	timeout := 10 // we need to figure out how to pick this value.
	if deadline, ok := ctx.Deadline(); ok {
		left := deadline.Sub(time.Now())

		if left <= 0 {
			<-ctx.Done()
			return 0, ctx.Err()
		}

		timeout = int(left.Seconds())
	}
	return timeout, nil
}
<commit_msg>Returning error message when image pull fails<commit_after>package container

import (
	"encoding/json"
	"fmt"
	"io"
	"time"

	"github.com/Sirupsen/logrus"
	engineapi "github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/events"
	"github.com/docker/swarm-v2/api"
	"github.com/docker/swarm-v2/log"
	"golang.org/x/net/context"
)

// containerController conducts remote operations for a container. All calls
// are mostly naked calls to the client API, seeded with information from
// containerConfig.
type containerController struct {
	container *containerConfig
}

func newContainerController(task *api.Task) (*containerController, error) {
	ctnr, err := newContainerConfig(task)
	if err != nil {
		return nil, err
	}

	return &containerController{
		container: ctnr,
	}, nil
}

func noopPrivilegeFn() (string, error) { return "", nil }

func (c *containerController) pullImage(ctx context.Context, client engineapi.APIClient) error {

	rc, err := client.ImagePull(ctx, c.container.pullOptions(), noopPrivilegeFn)
	if err != nil {
		return err
	}

	dec := json.NewDecoder(rc)
	m := map[string]interface{}{}
	for {
		if err := dec.Decode(&m); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		// TOOD(stevvooe): Report this status somewhere.
		logrus.Debugln("pull progress", m)
	}
	// if the final stream object contained an error, return it
	if errMsg, ok := m["error"]; ok {
		return fmt.Errorf("%v", errMsg)
	}
	return nil
}

func (c *containerController) create(ctx context.Context, client engineapi.APIClient) error {
	if _, err := client.ContainerCreate(ctx,
		c.container.config(),
		c.container.hostConfig(),
		c.container.networkingConfig(),
		c.container.name()); err != nil {
		return err
	}

	return nil
}

func (c *containerController) start(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerStart(ctx, c.container.name())
}

func (c *containerController) inspect(ctx context.Context, client engineapi.APIClient) (types.ContainerJSON, error) {
	return client.ContainerInspect(ctx, c.container.name())
}

// events issues a call to the events API and returns a channel with all
// events. The stream of events can be shutdown by cancelling the context.
//
// A chan struct{} is returned that will be closed if the event procressing
// fails and needs to be restarted.
func (c *containerController) events(ctx context.Context, client engineapi.APIClient) (<-chan events.Message, <-chan struct{}, error) {
	// TODO(stevvooe): Move this to a single, global event dispatch. For
	// now, we create a connection per container.
	var (
		eventsq = make(chan events.Message)
		closed  = make(chan struct{})
	)

	log.G(ctx).Debugf("waiting on events")
	// TODO(stevvooe): For long running tasks, it is likely that we will have
	// to restart this under failure.
	rc, err := client.Events(ctx, types.EventsOptions{
		Since:   "0",
		Filters: c.container.eventFilter(),
	})
	if err != nil {
		return nil, nil, err
	}

	go func(rc io.ReadCloser) {
		defer rc.Close()
		defer close(closed)

		select {
		case <-ctx.Done():
			// exit
			return
		default:
		}

		dec := json.NewDecoder(rc)

		for {
			var event events.Message
			if err := dec.Decode(&event); err != nil {
				// TODO(stevvooe): This error handling isn't quite right.
				if err == io.EOF {
					return
				}

				log.G(ctx).Errorf("error decoding event: %v", err)
				return
			}

			select {
			case eventsq <- event:
			case <-ctx.Done():
				return
			}
		}
	}(rc)

	return eventsq, closed, nil
}

func (c *containerController) shutdown(ctx context.Context, client engineapi.APIClient) error {
	timeout, err := resolveTimeout(ctx)
	if err != nil {
		return err
	}

	// TODO(stevvooe): Sending Stop isn't quite right. The timeout is actually
	// a grace period between SIGTERM and SIGKILL. We'll have to play with this
	// a little but to figure how much we defer to the engine.
	return client.ContainerStop(ctx, c.container.name(), timeout)
}

func (c *containerController) terminate(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerKill(ctx, c.container.name(), "")
}

func (c *containerController) remove(ctx context.Context, client engineapi.APIClient) error {
	return client.ContainerRemove(ctx, types.ContainerRemoveOptions{
		ContainerID:   c.container.name(),
		RemoveVolumes: true,
		Force:         true,
	})
}

// resolveTimeout calculates the timeout for second granularity timeout using
// the context's deadline.
func resolveTimeout(ctx context.Context) (int, error) {
	timeout := 10 // we need to figure out how to pick this value.
	if deadline, ok := ctx.Deadline(); ok {
		left := deadline.Sub(time.Now())

		if left <= 0 {
			<-ctx.Done()
			return 0, ctx.Err()
		}

		timeout = int(left.Seconds())
	}
	return timeout, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Simon Zimmermann. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

/*
Package util/handler is a collection of HTTP handlers for net/http package
*/

package handler

import (
	"fmt"
	"net/http"
	"time"
	"net/http/httputil"

	"git.tideland.biz/goas/monitoring"
	"github.com/gorilla/context"
	"github.com/simonz05/util/log"
	"github.com/simonz05/util/session"
)

// Creates a stack of HTTP handlers. Each HTTP handler is responsible for
// calling the next. The handlers are executed in reverse order, the last is
// called first.
func Use(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
	for _, m := range middleware {
		handler = m(handler)
	}
	return handler
}

// LogHandler adds logging to http requests
func LogHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		log.Printf("%s %s", r.Method, r.URL.Path)
		h.ServeHTTP(w, r)
		//log.Println(r.Method, r.URL, r.Form, time.Since(start))
		log.Printf("%s %s in %v\n", r.Method, r.URL.Path, time.Since(start))
	})
}

// DebugHandle
func DebugHandle(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		data, err := httputil.DumpRequest(r, true)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		log.Print(data)
		h.ServeHTTP(w, r)
	})
}

// MeasureHandler adds measuring to http requests
func MeasureHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m := monitoring.BeginMeasuring(r.URL.Path)
		h.ServeHTTP(w, r)
		m.EndMeasuring()
	})
}

func RecoveryHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if rec := recover(); rec != nil {
				log.Errorln("Recovered:", rec)
				w.WriteHeader(http.StatusInternalServerError)
			}
		}()
		h.ServeHTTP(w, r)
	})
}

type contextKey int

const (
	sessionKey contextKey = iota
	tokenKey
)

const (
	SessionHeader = "Authorization-Session"
	TokenHeader   = "Authorization-Token"
)

type authHandler struct {
	handler    http.Handler
	backend    session.Storage
	contextKey contextKey
	headerKey  string
	mustAuth   bool
}

func (a *authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := a.loadSession(r); err != nil {
		log.Error(err)

		if a.mustAuth {
			w.WriteHeader(http.StatusUnauthorized)
			return
		}
	}

	a.handler.ServeHTTP(w, r)
	//rec := httptest.NewRecorder()
	//a.handler.ServeHTTP(rec, r)

	//for k, v := range rec.Header() {
	//	w.Header()[k] = v
	//}

	//w.Header().Set("X-Authenticated-By", "kogama")
	//w.WriteHeader(rec.Code)
	//rec.Body.WriteTo(w)
}

// Tries to load a session from the auth backend for the given authentication
func (a *authHandler) loadSession(r *http.Request) error {
	value := r.Header[a.headerKey]

	if len(value) == 0 {
		return fmt.Errorf("Header %s was empty", a.headerKey)
	}

	id := value[0]

	if id == "" {
		return fmt.Errorf("Header %s was empty", a.headerKey)
	}

	ses, err := a.backend.Read(id)

	if err != nil {
		return err
	}

	context.Set(r, a.contextKey, ses)
	return nil
}

// NewAuthSessionHandler creates a AuthSessionHandler for the specified
// backend. It loads a session from a session key.
func NewAuthSessionHandler(sessionStorage session.Storage) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		return &authHandler{
			handler:    h,
			backend:    sessionStorage,
			contextKey: sessionKey,
			headerKey:  SessionHeader,
			mustAuth:   false,
		}
	}
}

// NewAuthTokenHandler creates a AuthTokenHandler for the specified
// It loads a session from a token key.
func NewAuthTokenHandler(tokenStorage session.Storage) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		return &authHandler{
			handler:    h,
			backend:    tokenStorage,
			contextKey: tokenKey,
			headerKey:  TokenHeader,
			mustAuth:   true,
		}
	}
}

// CurrentSession returns the matched session for the current request, if any.
func CurrentSession(r *http.Request) *session.Session {
	if rv := context.Get(r, sessionKey); rv != nil {
		return rv.(*session.Session)
	}

	return nil
}

// CurrentToken returns the matched token for the current request, if any.
func CurrentToken(r *http.Request) *session.Session {
	if rv := context.Get(r, tokenKey); rv != nil {
		return rv.(*session.Session)
	}

	return nil
}
<commit_msg>handler: tostring<commit_after>// Copyright 2014 Simon Zimmermann. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

/*
Package util/handler is a collection of HTTP handlers for net/http package
*/

package handler

import (
	"fmt"
	"net/http"
	"time"
	"net/http/httputil"

	"git.tideland.biz/goas/monitoring"
	"github.com/gorilla/context"
	"github.com/simonz05/util/log"
	"github.com/simonz05/util/session"
)

// Creates a stack of HTTP handlers. Each HTTP handler is responsible for
// calling the next. The handlers are executed in reverse order, the last is
// called first.
func Use(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
	for _, m := range middleware {
		handler = m(handler)
	}
	return handler
}

// LogHandler adds logging to http requests
func LogHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		log.Printf("%s %s", r.Method, r.URL.Path)
		h.ServeHTTP(w, r)
		//log.Println(r.Method, r.URL, r.Form, time.Since(start))
		log.Printf("%s %s in %v\n", r.Method, r.URL.Path, time.Since(start))
	})
}

// DebugHandle
func DebugHandle(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		data, err := httputil.DumpRequest(r, true)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		log.Print(string(data))
		h.ServeHTTP(w, r)
	})
}

// MeasureHandler adds measuring to http requests
func MeasureHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m := monitoring.BeginMeasuring(r.URL.Path)
		h.ServeHTTP(w, r)
		m.EndMeasuring()
	})
}

func RecoveryHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if rec := recover(); rec != nil {
				log.Errorln("Recovered:", rec)
				w.WriteHeader(http.StatusInternalServerError)
			}
		}()
		h.ServeHTTP(w, r)
	})
}

type contextKey int

const (
	sessionKey contextKey = iota
	tokenKey
)

const (
	SessionHeader = "Authorization-Session"
	TokenHeader   = "Authorization-Token"
)

type authHandler struct {
	handler    http.Handler
	backend    session.Storage
	contextKey contextKey
	headerKey  string
	mustAuth   bool
}

func (a *authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := a.loadSession(r); err != nil {
		log.Error(err)

		if a.mustAuth {
			w.WriteHeader(http.StatusUnauthorized)
			return
		}
	}

	a.handler.ServeHTTP(w, r)
	//rec := httptest.NewRecorder()
	//a.handler.ServeHTTP(rec, r)

	//for k, v := range rec.Header() {
	//	w.Header()[k] = v
	//}

	//w.Header().Set("X-Authenticated-By", "kogama")
	//w.WriteHeader(rec.Code)
	//rec.Body.WriteTo(w)
}

// Tries to load a session from the auth backend for the given authentication
func (a *authHandler) loadSession(r *http.Request) error {
	value := r.Header[a.headerKey]

	if len(value) == 0 {
		return fmt.Errorf("Header %s was empty", a.headerKey)
	}

	id := value[0]

	if id == "" {
		return fmt.Errorf("Header %s was empty", a.headerKey)
	}

	ses, err := a.backend.Read(id)

	if err != nil {
		return err
	}

	context.Set(r, a.contextKey, ses)
	return nil
}

// NewAuthSessionHandler creates a AuthSessionHandler for the specified
// backend. It loads a session from a session key.
func NewAuthSessionHandler(sessionStorage session.Storage) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		return &authHandler{
			handler:    h,
			backend:    sessionStorage,
			contextKey: sessionKey,
			headerKey:  SessionHeader,
			mustAuth:   false,
		}
	}
}

// NewAuthTokenHandler creates a AuthTokenHandler for the specified
// It loads a session from a token key.
func NewAuthTokenHandler(tokenStorage session.Storage) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		return &authHandler{
			handler:    h,
			backend:    tokenStorage,
			contextKey: tokenKey,
			headerKey:  TokenHeader,
			mustAuth:   true,
		}
	}
}

// CurrentSession returns the matched session for the current request, if any.
func CurrentSession(r *http.Request) *session.Session {
	if rv := context.Get(r, sessionKey); rv != nil {
		return rv.(*session.Session)
	}

	return nil
}

// CurrentToken returns the matched token for the current request, if any.
func CurrentToken(r *http.Request) *session.Session {
	if rv := context.Get(r, tokenKey); rv != nil {
		return rv.(*session.Session)
	}

	return nil
}
<|endoftext|>


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

// Package handler provides functions for responding to specific client
// requests by the ePoxy boot server.
package handler

import (
	"fmt"
	"log"
	"net/http"
	"path"
	"time"

	"github.com/gorilla/mux"
	"github.com/m-lab/epoxy/storage"
	"github.com/m-lab/epoxy/template"
)

// Config provides access to Host records.
type Config interface {
	Save(host *storage.Host) error
	Load(name string) (*storage.Host, error)
}

// Env holds data necessary for executing handler functions.
type Env struct {
	// Config provides access to Host records.
	Config Config
	// ServerAddr is the host:port of the public service. Used to generate absolute URLs.
	ServerAddr string
}

// GenerateStage1IPXE creates the stage1 iPXE script for booting machines.
// func (env *Env) GenerateStage1IPXE(rw http.ResponseWriter, req *http.Request) (int, error) {
func (env *Env) GenerateStage1IPXE(rw http.ResponseWriter, req *http.Request) {
	hostname := mux.Vars(req)["hostname"]

	// Use hostname as key to load record from Datastore.
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}
	// TODO(soltesz):
	// * Verify that the source IP maches the host IP.
	// * Save information sent in PostForm.

	// Generate new session IDs.
	host.GenerateSessionIDs()

	// Save host record to Datastore to commit session IDs.
	if err := env.Config.Save(host); err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	// Generate iPXE script.
	script := template.FormatStage1IPXEScript(host, env.ServerAddr)

	// Complete request as successful.
	rw.Header().Set("Content-Type", "text/plain; charset=us-ascii")
	rw.WriteHeader(http.StatusOK)
	_, err = fmt.Fprintf(rw, script)
	if err != nil {
		log.Printf("Failed to write response to %q: %v", hostname, err)
	}
	return
}

// GenerateJSONConfig creates and returns a JSON serialized nextboot.Config
// suitable for responding to stage2 or stage3 requests.
func (env *Env) GenerateJSONConfig(rw http.ResponseWriter, req *http.Request) {
	hostname := mux.Vars(req)["hostname"]
	// TODO: Verify that the sessionID matches the host.CurrentSessionIDs.Stage2ID.
	// sessionID := mux.Vars(req)["sessionID"]

	// Use hostname as key to load record from Datastore.
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}
	// TODO(soltesz):
	// * Verify that the source IP maches the host IP.
	// * Save information sent in PostForm, e.g. ssh host key.
	stage := path.Base(req.URL.Path)

	script := template.FormatJSONConfig(host, stage)

	// Complete request as successful.
	rw.Header().Set("Content-Type", "application/json; charset=utf-8")
	rw.WriteHeader(http.StatusOK)
	_, err = fmt.Fprintf(rw, script)
	if err != nil {
		log.Printf("Failed to write response to %q: %v", hostname, err)
	}
	return
}

// ReceiveReport handles the last step of a boot sequence when the epoxy client reports
// success or failure. In both cases, the session ids are invalidated. In all cases,
// epoxy_client is expected to report the server's public host key.
func (env *Env) ReceiveReport(rw http.ResponseWriter, req *http.Request) {
	// TODO: log or save values where appropriate.
	req.ParseForm()

	// Use hostname as key to load record from Datastore.
	hostname := mux.Vars(req)["hostname"]
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}

	// Verify sessionID matches the host record (i.e. request is authorized).
	sessionID := mux.Vars(req)["sessionID"]
	if sessionID != host.CurrentSessionIDs.ReportID {
		http.Error(rw, "Given session ID does not match host record", http.StatusForbidden)
		return
	}

	host.LastReport = time.Now()
	status := req.PostForm.Get("message")
	fmt.Println("status:", status)
	fmt.Println(req.PostForm)
	if status == "success" {
		// When the status is success, disable the "update" and mark the time.
		host.LastSuccess = host.LastReport
		host.UpdateEnabled = false
		// TODO: invalidate session ids.
	}

	// Save the new host state.
	if err := env.Config.Save(host); err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	// TODO: log using structured JSON.
	log.Println(req.PostForm)

	// Report success with no content.
	rw.WriteHeader(http.StatusNoContent)
	return
}
<commit_msg>Remove unused logs<commit_after>// Copyright 2016 ePoxy Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//////////////////////////////////////////////////////////////////////////////

// Package handler provides functions for responding to specific client
// requests by the ePoxy boot server.
package handler

import (
	"fmt"
	"log"
	"net/http"
	"path"
	"time"

	"github.com/gorilla/mux"
	"github.com/m-lab/epoxy/storage"
	"github.com/m-lab/epoxy/template"
)

// Config provides access to Host records.
type Config interface {
	Save(host *storage.Host) error
	Load(name string) (*storage.Host, error)
}

// Env holds data necessary for executing handler functions.
type Env struct {
	// Config provides access to Host records.
	Config Config
	// ServerAddr is the host:port of the public service. Used to generate absolute URLs.
	ServerAddr string
}

// GenerateStage1IPXE creates the stage1 iPXE script for booting machines.
// func (env *Env) GenerateStage1IPXE(rw http.ResponseWriter, req *http.Request) (int, error) {
func (env *Env) GenerateStage1IPXE(rw http.ResponseWriter, req *http.Request) {
	hostname := mux.Vars(req)["hostname"]

	// Use hostname as key to load record from Datastore.
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}
	// TODO(soltesz):
	// * Verify that the source IP maches the host IP.
	// * Save information sent in PostForm.

	// Generate new session IDs.
	host.GenerateSessionIDs()

	// Save host record to Datastore to commit session IDs.
	if err := env.Config.Save(host); err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	// Generate iPXE script.
	script := template.FormatStage1IPXEScript(host, env.ServerAddr)

	// Complete request as successful.
	rw.Header().Set("Content-Type", "text/plain; charset=us-ascii")
	rw.WriteHeader(http.StatusOK)
	_, err = fmt.Fprintf(rw, script)
	if err != nil {
		log.Printf("Failed to write response to %q: %v", hostname, err)
	}
	return
}

// GenerateJSONConfig creates and returns a JSON serialized nextboot.Config
// suitable for responding to stage2 or stage3 requests.
func (env *Env) GenerateJSONConfig(rw http.ResponseWriter, req *http.Request) {
	hostname := mux.Vars(req)["hostname"]
	// TODO: Verify that the sessionID matches the host.CurrentSessionIDs.Stage2ID.
	// sessionID := mux.Vars(req)["sessionID"]

	// Use hostname as key to load record from Datastore.
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}
	// TODO(soltesz):
	// * Verify that the source IP maches the host IP.
	// * Save information sent in PostForm, e.g. ssh host key.
	stage := path.Base(req.URL.Path)

	script := template.FormatJSONConfig(host, stage)

	// Complete request as successful.
	rw.Header().Set("Content-Type", "application/json; charset=utf-8")
	rw.WriteHeader(http.StatusOK)
	_, err = fmt.Fprintf(rw, script)
	if err != nil {
		log.Printf("Failed to write response to %q: %v", hostname, err)
	}
	return
}

// ReceiveReport handles the last step of a boot sequence when the epoxy client reports
// success or failure. In both cases, the session ids are invalidated. In all cases,
// epoxy_client is expected to report the server's public host key.
func (env *Env) ReceiveReport(rw http.ResponseWriter, req *http.Request) {
	// TODO: log or save values where appropriate.
	req.ParseForm()

	// Use hostname as key to load record from Datastore.
	hostname := mux.Vars(req)["hostname"]
	host, err := env.Config.Load(hostname)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusNotFound)
		return
	}

	// Verify sessionID matches the host record (i.e. request is authorized).
	sessionID := mux.Vars(req)["sessionID"]
	if sessionID != host.CurrentSessionIDs.ReportID {
		http.Error(rw, "Given session ID does not match host record", http.StatusForbidden)
		return
	}

	host.LastReport = time.Now()
	status := req.PostForm.Get("message")
	if status == "success" {
		// When the status is success, disable the "update" and mark the time.
		host.LastSuccess = host.LastReport
		host.UpdateEnabled = false
		// TODO: invalidate session ids.
	}

	// Save the new host state.
	if err := env.Config.Save(host); err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	// TODO: log using structured JSON.
	log.Println(req.PostForm)

	// Report success with no content.
	rw.WriteHeader(http.StatusNoContent)
	return
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"

	"github.com/strava/go.strava"
)

// StravaAuth will render a request to authorize strava user with Bestrida
func StravaAuth(w http.ResponseWriter, r *http.Request) {
	// define a strava.OAuthAuthenticator to hold state.
	// The callback url is used to generate an AuthorizationURL.
	// The RequestClientGenerator can be used to generate an http.RequestClient.
	// This is usually when running on the Google App Engine platform.
	authenticator = &strava.OAuthAuthenticator{
		CallbackURL:            fmt.Sprintf("http://localhost:%d/exchange_token", port),
		RequestClientGenerator: nil,
	}

	path, err := authenticator.CallbackPath()
	if err != nil {
		// possibly that the callback url set above is invalid
		fmt.Println(err)
		os.Exit(1)
	}
	http.HandleFunc(path, authenticator.HandlerFunc(oAuthSuccess, oAuthFailure))
}

// AuthHandler Route to display Auth button
func AuthHandler(w http.ResponseWriter, r *http.Request) {
	// you should make this a template in your real application
	fmt.Fprintf(w, `<a href="%s">`, authenticator.AuthorizationURL("state1", strava.Permissions.Public, true))
	fmt.Fprint(w, `<img src="http://strava.github.io/api/images/ConnectWithStrava.png" />`)
	fmt.Fprint(w, `</a>`)
}

func oAuthSuccess(auth *strava.AuthorizationResponse, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "SUCCESS:\nAt this point you can use this information to create a new user or link the account to one of your existing users\n")
	fmt.Fprintf(w, "State: %s\n\n", auth.State)
	fmt.Fprintf(w, "Access Token: %s\n\n", auth.AccessToken)

	fmt.Fprintf(w, "The Authenticated Athlete (you):\n")
	content, _ := json.MarshalIndent(auth.Athlete, "", " ")
	fmt.Fprint(w, string(content))
}

func oAuthFailure(err error, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Authorization Failure:\n")

	// some standard error checking
	if err == strava.OAuthAuthorizationDeniedErr {
		fmt.Fprint(w, "The user clicked the 'Do not Authorize' button on the previous page.\n")
		fmt.Fprint(w, "This is the main error your application should handle.")
	} else if err == strava.OAuthInvalidCredentialsErr {
		fmt.Fprint(w, "You provided an incorrect client_id or client_secret.\nDid you remember to set them at the begininng of this file?")
	} else if err == strava.OAuthInvalidCodeErr {
		fmt.Fprint(w, "The temporary token was not recognized, this shouldn't happen normally")
	} else if err == strava.OAuthServerErr {
		fmt.Fprint(w, "There was some sort of server error, try again to see if the problem continues")
	} else {
		fmt.Fprint(w, err)
	}
}
<commit_msg>update auth handler<commit_after>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"

	"github.com/strava/go.strava"
)

// StravaAuth will render a request to authorize strava user with Bestrida
func StravaAuth(w http.ResponseWriter, r *http.Request) {
	// define a strava.OAuthAuthenticator to hold state.
	// The callback url is used to generate an AuthorizationURL.
	// The RequestClientGenerator can be used to generate an http.RequestClient.
	// This is usually when running on the Google App Engine platform.
	authenticator = &strava.OAuthAuthenticator{
		CallbackURL:            fmt.Sprintf("http://localhost:%d/exchange_token", port),
		RequestClientGenerator: nil,
	}

	path, err := authenticator.CallbackPath()
	if err != nil {
		// possibly that the callback url set above is invalid
		fmt.Println(err)
		os.Exit(1)
	}
	http.HandleFunc(path, authenticator.HandlerFunc(oAuthSuccess, oAuthFailure))
}

// AuthHandler Route to display Auth button
func AuthHandler(w http.ResponseWriter, r *http.Request) {
	// you should make this a template in your real application
	fmt.Fprintf(w, `<a href="%s">`, authenticator.AuthorizationURL("", strava.Permissions.Public, false))
	fmt.Fprint(w, `<img src="http://strava.github.io/api/images/ConnectWithStrava.png" />`)
	fmt.Fprint(w, `</a>`)
}

func oAuthSuccess(auth *strava.AuthorizationResponse, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "SUCCESS:\nAt this point you can use this information to create a new user or link the account to one of your existing users\n")
	fmt.Fprintf(w, "State: %s\n\n", auth.State)
	fmt.Fprintf(w, "Access Token: %s\n\n", auth.AccessToken)

	fmt.Fprintf(w, "The Authenticated Athlete (you):\n")
	content, _ := json.MarshalIndent(auth.Athlete, "", " ")
	fmt.Fprint(w, string(content))
}

func oAuthFailure(err error, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Authorization Failure:\n")

	// some standard error checking
	if err == strava.OAuthAuthorizationDeniedErr {
		fmt.Fprint(w, "The user clicked the 'Do not Authorize' button on the previous page.\n")
		fmt.Fprint(w, "This is the main error your application should handle.")
	} else if err == strava.OAuthInvalidCredentialsErr {
		fmt.Fprint(w, "You provided an incorrect client_id or client_secret.\nDid you remember to set them at the begininng of this file?")
	} else if err == strava.OAuthInvalidCodeErr {
		fmt.Fprint(w, "The temporary token was not recognized, this shouldn't happen normally")
	} else if err == strava.OAuthServerErr {
		fmt.Fprint(w, "There was some sort of server error, try again to see if the problem continues")
	} else {
		fmt.Fprint(w, err)
	}
}
<|endoftext|>


<commit_before>package test

import "testing"

// func TestConnectTCP(t *testing.T) {
// 	s := NewTCPServerHelper(t)
// 	defer s.Close()
// 	c := s.GetTCPClient()
// 	defer c.Close()
// }

func TestConnectTLS(t *testing.T) {
	sh := NewTLSServerHelper(t)
	defer sh.Close()
	// sh.GetTLSClient(true)
	// defer ch.Close()

	// msg := []byte("test message")
	//
	// sh.Server.MiddlewareIn(middleware.Echo)
	// ch.Client.MiddlewareIn(func(ctx *client.Ctx) {
	// 	if !reflect.DeepEqual(ctx.Msg, msg) {
	// 		t.Fatalf("expected: '%s', got: '%s'", msg, ctx.Msg)
	// 	}
	// 	ctx.Next()
	// })
	//
	// ch.Client.Send(msg) // todo: use fail-safe ClientHelper.Send instead
}
<commit_msg>add test todo<commit_after>package test

import "testing"

// func TestConnectTCP(t *testing.T) {
// 	s := NewTCPServerHelper(t)
// 	defer s.Close()
// 	c := s.GetTCPClient()
// 	defer c.Close()
// }

func TestConnectTLS(t *testing.T) {
	sh := NewTLSServerHelper(t)
	defer sh.Close()
	ch := sh.GetTLSClient(true)
	defer ch.Close()

	// todo: solve multiple close error messages first

	// var wg sync.WaitGroup
	// msg := []byte("test message")
	//
	// sh.Server.MiddlewareIn(middleware.Echo)
	// ch.Client.MiddlewareIn(func(ctx *client.Ctx) {
	// 	defer wg.Done()
	// 	if !reflect.DeepEqual(ctx.Msg, msg) {
	// 		t.Fatalf("expected: '%s', got: '%s'", msg, ctx.Msg)
	// 	}
	// 	ctx.Next()
	// })
	//
	// wg.Add(1)
	// ch.Client.Send(msg) // todo: use fail-safe ClientHelper.Send instead
	// wg.Wait()
}
<|endoftext|>


<commit_before>// Copyright e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sys

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/e-XpertSolutions/f5-rest-client/f5"
)

// FileSSLCertConfigList holds a list of FileSSLCert configuration.
type FileSSLCertConfigList struct {
	Items    []FileSSLCertConfig `json:"items"`
	Kind     string              `json:"kind"`
	SelfLink string              `json:"selflink"`
}

// FileSSLCertConfig holds the configuration of a single FileSSLCert.
type FileSSLCertConfig struct {
	BundleCertificatesReference struct {
		IsSubcollection bool   `json:"isSubcollection"`
		Link            string `json:"link"`
	} `json:"bundleCertificatesReference"`
	CertificateKeyCurveName string `json:"certificateKeyCurveName"`
	CertificateKeySize      int    `json:"certificateKeySize"`
	Checksum                string `json:"checksum"`
	CreateTime              string `json:"createTime"`
	CreatedBy               string `json:"createdBy"`
	ExpirationDate          int    `json:"expirationDate"`
	ExpirationString        string `json:"expirationString"`
	FullPath                string `json:"fullPath"`
	Generation              int    `json:"generation"`
	IsBundle                string `json:"isBundle"`
	Issuer                  string `json:"issuer"`
	KeyType                 string `json:"keyType"`
	Kind                    string `json:"kind"`
	LastUpdateTime          string `json:"lastUpdateTime"`
	Mode                    int    `json:"mode"`
	Name                    string `json:"name"`
	Partition               string `json:"partition"`
	Revision                int    `json:"revision"`
	SelfLink                string `json:"selfLink"`
	SerialNumber            string `json:"serialNumber"`
	Size                    int    `json:"size"`
	Subject                 string `json:"subject"`
	SystemPath              string `json:"systemPath"`
	UpdatedBy               string `json:"updatedBy"`
	Version                 int    `json:"version"`
}

// FileSSLCertEndpoint represents the REST resource for managing FileSSLCert.
const FileSSLCertEndpoint = "/file/ssl-cert"

// FileSSLCertResource provides an API to manage FileSSLCert configurations.
type FileSSLCertResource struct {
	c f5.Client
}

// ListAll  lists all the FileSSLCert configurations.
func (r *FileSSLCertResource) ListAll() (*FileSSLCertConfigList, error) {
	var list FileSSLCertConfigList
	if err := r.c.ReadQuery(BasePath+FileSSLCertEndpoint, &list); err != nil {
		return nil, err
	}
	return &list, nil
}

// Get a single FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Get(id string) (*FileSSLCertConfig, error) {
	var item FileSSLCertConfig
	if err := r.c.ReadQuery(BasePath+FileSSLCertEndpoint, &item); err != nil {
		return nil, err
	}
	return &item, nil
}

// Create a new FileSSLCert configuration.
func (r *FileSSLCertResource) Create(name, path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("failed to gather information about '%s': %v", path, err)
	}
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to read file from path: %v", err)
	}
	defer f.Close()

	req, err := r.c.MakeUploadRequest(f5.UploadRESTPath+"/"+filepath.Base(path), f, info.Size())
	if err != nil {
		return fmt.Errorf("failed to create upload request: %v", err)
	}
	resp, err := r.c.Do(req)
	if err != nil {
		return fmt.Errorf("failed to upload file '%s': %v", path, err)
	}
	defer resp.Body.Close()

	bs, _ := ioutil.ReadAll(resp.Body)
	log.Print("DEBUG resp=", string(bs))

	data := map[string]string{
		"name":        name,
		"source-path": "file://localhost/var/config/rest/downloads/" + filepath.Base(path),
	}
	if err := r.c.ModQuery("POST", BasePath+FileSSLCertEndpoint, data); err != nil {
		return fmt.Errorf("failed to create FileSSLCert configuration: %v", err)
	}

	return nil
}

// Edit a FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Edit(id, path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("failed to gather information about '%s': %v", path, err)
	}
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to read file from path: %v", err)
	}
	defer f.Close()

	req, err := r.c.MakeUploadRequest(f5.UploadRESTPath+"/"+filepath.Base(path), f, info.Size())
	if err != nil {
		return fmt.Errorf("failed to create upload request: %v", err)
	}
	resp, err := r.c.Do(req)
	if err != nil {
		return fmt.Errorf("failed to upload file '%s': %v", path, err)
	}
	defer resp.Body.Close()

	bs, _ := ioutil.ReadAll(resp.Body)
	log.Print("DEBUG resp=", string(bs))

	data := map[string]string{
		"source-path": "file://localhost/var/config/rest/downloads/" + filepath.Base(path),
	}
	if err := r.c.ModQuery("PUT", BasePath+FileSSLCertEndpoint+"/"+id, data); err != nil {
		return fmt.Errorf("failed to create FileSSLCert configuration: %v", err)
	}

	return nil
}

// Delete a single FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Delete(id string) error {
	if err := r.c.ModQuery("DELETE", BasePath+FileSSLCertEndpoint+"/"+id, nil); err != nil {
		return err
	}
	return nil
}
<commit_msg>f5/sys/ssl: List Expired certificates with ListExpired function<commit_after>// Copyright e-Xpert Solutions SA. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sys

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/e-XpertSolutions/f5-rest-client/f5"
)

// FileSSLCertConfigList holds a list of FileSSLCert configuration.
type FileSSLCertConfigList struct {
	Items    []FileSSLCertConfig `json:"items"`
	Kind     string              `json:"kind"`
	SelfLink string              `json:"selflink"`
}

// FileSSLCertConfig holds the configuration of a single FileSSLCert.
type FileSSLCertConfig struct {
	BundleCertificatesReference struct {
		IsSubcollection bool   `json:"isSubcollection"`
		Link            string `json:"link"`
	} `json:"bundleCertificatesReference"`
	CertificateKeyCurveName string `json:"certificateKeyCurveName"`
	CertificateKeySize      int    `json:"certificateKeySize"`
	Checksum                string `json:"checksum"`
	CreateTime              string `json:"createTime"`
	CreatedBy               string `json:"createdBy"`
	ExpirationDate          int64  `json:"expirationDate"`
	ExpirationString        string `json:"expirationString"`
	FullPath                string `json:"fullPath"`
	Generation              int    `json:"generation"`
	IsBundle                string `json:"isBundle"`
	Issuer                  string `json:"issuer"`
	KeyType                 string `json:"keyType"`
	Kind                    string `json:"kind"`
	LastUpdateTime          string `json:"lastUpdateTime"`
	Mode                    int    `json:"mode"`
	Name                    string `json:"name"`
	Partition               string `json:"partition"`
	Revision                int    `json:"revision"`
	SelfLink                string `json:"selfLink"`
	SerialNumber            string `json:"serialNumber"`
	Size                    int    `json:"size"`
	Subject                 string `json:"subject"`
	SystemPath              string `json:"systemPath"`
	UpdatedBy               string `json:"updatedBy"`
	Version                 int    `json:"version"`
}

// FileSSLCertEndpoint represents the REST resource for managing FileSSLCert.
const FileSSLCertEndpoint = "/file/ssl-cert"

// FileSSLCertResource provides an API to manage FileSSLCert configurations.
type FileSSLCertResource struct {
	c f5.Client
}

// ListAll  lists all the FileSSLCert configurations.
func (r *FileSSLCertResource) ListAll() (*FileSSLCertConfigList, error) {
	var list FileSSLCertConfigList
	if err := r.c.ReadQuery(BasePath+FileSSLCertEndpoint, &list); err != nil {
		return nil, err
	}
	return &list, nil
}

// ListExpired lists all expired certificates.
func (r *FileSSLCertResource) ListExpired() (*FileSSLCertConfigList, error) {
	var list FileSSLCertConfigList
	if err := r.c.ReadQuery(BasePath+FileSSLCertEndpoint, &list); err != nil {
		return nil, err
	}

	var expiredList []FileSSLCertConfig

	for _, cert := range list.Items {
		if time.Now().After(time.Unix(cert.ExpirationDate, 0)) {
			expiredList = append(expiredList, cert)
		}
	}

	expConfigList := FileSSLCertConfigList{
		Items:    expiredList,
		Kind:     list.Kind,
		SelfLink: list.SelfLink,
	}

	return &expConfigList, nil
}

// Get a single FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Get(id string) (*FileSSLCertConfig, error) {
	var item FileSSLCertConfig
	if err := r.c.ReadQuery(BasePath+FileSSLCertEndpoint, &item); err != nil {
		return nil, err
	}
	return &item, nil
}

// Create a new FileSSLCert configuration.
func (r *FileSSLCertResource) Create(name, path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("failed to gather information about '%s': %v", path, err)
	}
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to read file from path: %v", err)
	}
	defer f.Close()

	req, err := r.c.MakeUploadRequest(f5.UploadRESTPath+"/"+filepath.Base(path), f, info.Size())
	if err != nil {
		return fmt.Errorf("failed to create upload request: %v", err)
	}
	resp, err := r.c.Do(req)
	if err != nil {
		return fmt.Errorf("failed to upload file '%s': %v", path, err)
	}
	defer resp.Body.Close()

	bs, _ := ioutil.ReadAll(resp.Body)
	log.Print("DEBUG resp=", string(bs))

	data := map[string]string{
		"name":        name,
		"source-path": "file://localhost/var/config/rest/downloads/" + filepath.Base(path),
	}
	if err := r.c.ModQuery("POST", BasePath+FileSSLCertEndpoint, data); err != nil {
		return fmt.Errorf("failed to create FileSSLCert configuration: %v", err)
	}

	return nil
}

// Edit a FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Edit(id, path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return fmt.Errorf("failed to gather information about '%s': %v", path, err)
	}
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to read file from path: %v", err)
	}
	defer f.Close()

	req, err := r.c.MakeUploadRequest(f5.UploadRESTPath+"/"+filepath.Base(path), f, info.Size())
	if err != nil {
		return fmt.Errorf("failed to create upload request: %v", err)
	}
	resp, err := r.c.Do(req)
	if err != nil {
		return fmt.Errorf("failed to upload file '%s': %v", path, err)
	}
	defer resp.Body.Close()

	bs, _ := ioutil.ReadAll(resp.Body)
	log.Print("DEBUG resp=", string(bs))

	data := map[string]string{
		"source-path": "file://localhost/var/config/rest/downloads/" + filepath.Base(path),
	}
	if err := r.c.ModQuery("PUT", BasePath+FileSSLCertEndpoint+"/"+id, data); err != nil {
		return fmt.Errorf("failed to create FileSSLCert configuration: %v", err)
	}

	return nil
}

// Delete a single FileSSLCert configuration identified by id.
func (r *FileSSLCertResource) Delete(id string) error {
	if err := r.c.ModQuery("DELETE", BasePath+FileSSLCertEndpoint+"/"+id, nil); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package sms

import "fmt"

func mmsStat(b bool) string {
	if b {
		return "More messages are waiting"
	}
	return "No more messages are waiting"
}
func lpStat(b bool) string {
	if b {
		return "Forwarded/spawned message"
	}
	return "Not forwarded/spawned message"
}
func sriStat(b bool) string {
	if b {
		return "Status report shall be returned"
	}
	return "Status report shall not be returned"
}
func srqStat(b bool) string {
	if b {
		return "This is result of an SMS-COMMAND"
	}
	return "This is result of a SMS-SUBMIT"
}
func rpStat(b bool) string {
	if b {
		return "Reply Path is set"
	}
	return "Reply Path is not set"
}
func rdStat(b bool) string {
	if b {
		return "Reject duplicate SUBMIT"
	}
	return "Accept duplicate SUBMIT"
}
func srrStat(b bool) string {
	if b {
		return "Status report is requested"
	}
	return "Status report is not requested"
}
func fcsStat(b byte) string {
	switch b {
	case 0x80:
		return "Telematic interworking not supported"
	case 0x81:
		return "Short message Type 0 not supported"
	case 0x82:
		return "Cannot replace short message"
	case 0x8F:
		return "Unspecified TP-PID error"
	case 0x90:
		return "Data coding scheme (alphabet) not supported"
	case 0x91:
		return "Message class not supported"
	case 0x9F:
		return "Unspecified TP-DCS error"
	case 0xA0:
		return "Command cannot be actioned"
	case 0xA1:
		return "Command unsupported"
	case 0xAF:
		return "Unspecified TP-Command error"
	case 0xB0:
		return "TPDU not supported"
	case 0xC0:
		return "SC busy"
	case 0xC1:
		return "No SC subscription"
	case 0xC2:
		return "SC system failure"
	case 0xC3:
		return "Invalid SME address"
	case 0xC4:
		return "Destination SME barred"
	case 0xC5:
		return "SM Rejected-Duplicate SM"
	case 0xC6:
		return "TP-VPF not supported"
	case 0xC7:
		return "TP-VP not supported"
	case 0xD0:
		return "(U)SIM SMS storage full"
	case 0xD1:
		return "No SMS storage capability in (U)SIM"
	case 0xD2:
		return "Error in MS"
	case 0xD3:
		return "Memory Capacity Exceeded"
	case 0xD4:
		return "(U)SIM Application Toolkit Busy"
	case 0xD5:
		return "(U)SIM data download error"
	case 0xFF:
		return "Unspecified error cause"
	}
	return fmt.Sprintf("Reserved(%d)", b)
}
func stStat(b byte) string {
	switch b {
	case 0x00:
		return "Short message received by the SME"
	case 0x01:
		return "Short message forwarded by the SC to the SME" +
			" but the SC is unable to confirm delivery"
	case 0x02:
		return "Short message replaced by the SC"
	case 0x20:
		return "Congestion"
	case 0x21:
		return "SME busy"
	case 0x22:
		return "No response from SME"
	case 0x23:
		return "Service rejected"
	case 0x24:
		return "Quality of service not available"
	case 0x25:
		return "Error in SME"
	case 0x40:
		return "Remote procedure error"
	case 0x41:
		return "Incompatible destination"
	case 0x42:
		return "Connection rejected by SME"
	case 0x43:
		return "Not obtainable"
	case 0x44:
		return "Quality of service not available"
	case 0x45:
		return "No interworking available"
	case 0x46:
		return "SM Validity Period Expired"
	case 0x47:
		return "SM Deleted by originating SME"
	case 0x48:
		return "SM Deleted by SC Administration"
	case 0x49:
		return "SM does not exist"
	case 0x60:
		return "Congestion"
	case 0x61:
		return "SME busy"
	case 0x62:
		return "No response from SME"
	case 0x63:
		return "Service rejected"
	case 0x64:
		return "Quality of service not available"
	case 0x65:
		return "Error in SME"
	}
	return fmt.Sprintf("Reserved(%d)", b)
}
func pidStat(b byte) string {
	switch b {
	case 0:
		return "Default store and forward short message"
	case 32:
		return "implicit telemetic device"
	case 33:
		return "Telex or teletex reduced to telex format"
	case 34:
		return "Group 3 telefax"
	case 35:
		return "Group 4 telefax"
	case 36:
		return "Voice telephone"
	case 37:
		return "ERMES (European Radio Messaging System)"
	case 38:
		return "National Paging system (known to the SC)"
	case 39:
		return "Videotex (T.100 [20] /T.101 [21])"
	case 40:
		return "Teletex, carrier unspecified"
	case 41:
		return "Teletex, in PSPDN"
	case 42:
		return "Teletex, in CSPDN"
	case 43:
		return "Teletex, in analog PSTN"
	case 44:
		return "Teletex, in digital ISDN"
	case 45:
		return "UCI (Universal Computer Interface, ETSI DE/PS 3 01 3)"
	case 48:
		return "A message handling facility (known to the SC)"
	case 49:
		return "Any public X.400 based message handling system"
	case 50:
		return "Internet Electronic Mail"
	case 63:
		return "A GSM/UMTS mobile station"
	case 64:
		return "Short Message Type 0"
	case 65:
		return "Replace Short Message Type 1"
	case 66:
		return "Replace Short Message Type 2"
	case 67:
		return "Replace Short Message Type 3"
	case 68:
		return "Replace Short Message Type 4"
	case 69:
		return "Replace Short Message Type 5"
	case 70:
		return "Replace Short Message Type 6"
	case 71:
		return "Replace Short Message Type 7"
	case 72:
		return "Device Triggering Short Message"
	case 94:
		return "Enhanced Message Service"
	case 95:
		return "Return Call Message"
	case 124:
		return "ANSI-136 R-DATA"
	case 125:
		return "ME Data download"
	case 126:
		return "ME De personalization Short Message"
	case 127:
		return "(U)SIM Data download"
	}
	if b > 0 && b < 32 {
		return "no telematic interworking, but SME to SME protocol"
	}
	if b > 55 && b < 63 {
		return "SC specific use"
	}
	if b > 191 && b <= 255 {
		return "SC specific use"
	}

	return fmt.Sprintf("Reserved(%d)", b)
}
<commit_msg>modify<commit_after>package sms

import "fmt"

func mmsStat(b bool) string {
	if b {
		return "More messages are waiting"
	}
	return "No more messages are waiting"
}
func lpStat(b bool) string {
	if b {
		return "Forwarded/spawned message"
	}
	return "Not forwarded/spawned message"
}
func sriStat(b bool) string {
	if b {
		return "Status report shall be returned"
	}
	return "Status report shall not be returned"
}
func srqStat(b bool) string {
	if b {
		return "This is result of an SMS-COMMAND"
	}
	return "This is result of a SMS-SUBMIT"
}
func rpStat(b bool) string {
	if b {
		return "Reply Path is set"
	}
	return "Reply Path is not set"
}
func rdStat(b bool) string {
	if b {
		return "Reject duplicate SUBMIT"
	}
	return "Accept duplicate SUBMIT"
}
func srrStat(b bool) string {
	if b {
		return "Status report is requested"
	}
	return "Status report is not requested"
}
func fcsStat(b byte) string {
	switch b {
	case 0x80:
		return "Telematic interworking not supported"
	case 0x81:
		return "Short message Type 0 not supported"
	case 0x82:
		return "Cannot replace short message"
	case 0x8F:
		return "Unspecified TP-PID error"
	case 0x90:
		return "Data coding scheme (alphabet) not supported"
	case 0x91:
		return "Message class not supported"
	case 0x9F:
		return "Unspecified TP-DCS error"
	case 0xA0:
		return "Command cannot be actioned"
	case 0xA1:
		return "Command unsupported"
	case 0xAF:
		return "Unspecified TP-Command error"
	case 0xB0:
		return "TPDU not supported"
	case 0xC0:
		return "SC busy"
	case 0xC1:
		return "No SC subscription"
	case 0xC2:
		return "SC system failure"
	case 0xC3:
		return "Invalid SME address"
	case 0xC4:
		return "Destination SME barred"
	case 0xC5:
		return "SM Rejected-Duplicate SM"
	case 0xC6:
		return "TP-VPF not supported"
	case 0xC7:
		return "TP-VP not supported"
	case 0xD0:
		return "(U)SIM SMS storage full"
	case 0xD1:
		return "No SMS storage capability in (U)SIM"
	case 0xD2:
		return "Error in MS"
	case 0xD3:
		return "Memory Capacity Exceeded"
	case 0xD4:
		return "(U)SIM Application Toolkit Busy"
	case 0xD5:
		return "(U)SIM data download error"
	case 0xFF:
		return "Unspecified error cause"
	}
	return fmt.Sprintf("Reserved(%d)", b)
}
func stStat(b byte) string {
	switch b {
	case 0x00:
		return "Short message received by the SME"
	case 0x01:
		return "Short message forwarded by the SC to the SME" +
			" but the SC is unable to confirm delivery"
	case 0x02:
		return "Short message replaced by the SC"
	case 0x20:
		return "Congestion (trying transfer)"
	case 0x21:
		return "SME busy (trying transfer)"
	case 0x22:
		return "No response from SME (trying transfer)"
	case 0x23:
		return "Service rejected (trying transfer)"
	case 0x24:
		return "Quality of service not available (trying transfer)"
	case 0x25:
		return "Error in SME (trying transfer)"
	case 0x40:
		return "Remote procedure error"
	case 0x41:
		return "Incompatible destination"
	case 0x42:
		return "Connection rejected by SME"
	case 0x43:
		return "Not obtainable"
	case 0x44:
		return "Quality of service not available (permanent)"
	case 0x45:
		return "No interworking available"
	case 0x46:
		return "SM Validity Period Expired"
	case 0x47:
		return "SM Deleted by originating SME"
	case 0x48:
		return "SM Deleted by SC Administration"
	case 0x49:
		return "SM does not exist"
	case 0x60:
		return "Congestion"
	case 0x61:
		return "SME busy"
	case 0x62:
		return "No response from SME"
	case 0x63:
		return "Service rejected"
	case 0x64:
		return "Quality of service not available"
	case 0x65:
		return "Error in SME"
	}
	return fmt.Sprintf("Reserved(%d)", b)
}
func pidStat(b byte) string {
	switch b {
	case 0:
		return "Default store and forward short message"
	case 32:
		return "implicit telemetic device"
	case 33:
		return "Telex or teletex reduced to telex format"
	case 34:
		return "Group 3 telefax"
	case 35:
		return "Group 4 telefax"
	case 36:
		return "Voice telephone"
	case 37:
		return "ERMES (European Radio Messaging System)"
	case 38:
		return "National Paging system (known to the SC)"
	case 39:
		return "Videotex (T.100 [20] /T.101 [21])"
	case 40:
		return "Teletex, carrier unspecified"
	case 41:
		return "Teletex, in PSPDN"
	case 42:
		return "Teletex, in CSPDN"
	case 43:
		return "Teletex, in analog PSTN"
	case 44:
		return "Teletex, in digital ISDN"
	case 45:
		return "UCI (Universal Computer Interface, ETSI DE/PS 3 01 3)"
	case 48:
		return "A message handling facility (known to the SC)"
	case 49:
		return "Any public X.400 based message handling system"
	case 50:
		return "Internet Electronic Mail"
	case 63:
		return "A GSM/UMTS mobile station"
	case 64:
		return "Short Message Type 0"
	case 65:
		return "Replace Short Message Type 1"
	case 66:
		return "Replace Short Message Type 2"
	case 67:
		return "Replace Short Message Type 3"
	case 68:
		return "Replace Short Message Type 4"
	case 69:
		return "Replace Short Message Type 5"
	case 70:
		return "Replace Short Message Type 6"
	case 71:
		return "Replace Short Message Type 7"
	case 72:
		return "Device Triggering Short Message"
	case 94:
		return "Enhanced Message Service"
	case 95:
		return "Return Call Message"
	case 124:
		return "ANSI-136 R-DATA"
	case 125:
		return "ME Data download"
	case 126:
		return "ME De personalization Short Message"
	case 127:
		return "(U)SIM Data download"
	}
	if b > 0 && b < 32 {
		return "no telematic interworking, but SME to SME protocol"
	}
	if b > 55 && b < 63 {
		return "SC specific use"
	}
	if b > 191 && b <= 255 {
		return "SC specific use"
	}

	return fmt.Sprintf("Reserved(%d)", b)
}
<|endoftext|>


<commit_before>package formatter

import (
	"testing"

	"github.com/sugilog/ltsv-cli.go/io"
)

func TestFilterFormatter(t *testing.T) {
	tests := []struct {
		Line   string
		Keys   []string
		Expect string
	}{
		{
			Line:   "test:line\tvalid:true",
			Keys:   []string{"test", "valid"},
			Expect: "test:line\tvalid:true",
		},
		{
			Line:   "test:line\tvalid:true",
			Keys:   []string{"test"},
			Expect: "test:line",
		},
		{
			Line:   "test:line\tvalid:true",
			Keys:   []string{"Test", "valid"},
			Expect: "valid:true",
		},
		{
			Line:   "test:line\tvalid:true",
			Keys:   []string{""},
			Expect: "",
		},
	}

	for _, test := range tests {
		formatter := FilterFormatter(test.Keys)
		entry, ok := formatter(io.Entry{Line: test.Line})

		if !ok {
			t.Error("Should be ok")
		}

		if test.Expect != entry.Formatted {
			t.Error("<%s> expected, but was <%s>", test.Expect, entry.Formatted)
		}
	}
}

func TestFilterFunc(t *testing.T) {
	tests := []struct {
		LTSV   map[string]string
		Keys   []string
		Expect string
	}{
		{
			LTSV:   map[string]string{"test": "line", "valid": "true"},
			Keys:   []string{"test", "valid"},
			Expect: "test:line\tvalid:true",
		},
		{
			LTSV:   map[string]string{"test": "line", "valid": "true"},
			Keys:   []string{"test"},
			Expect: "test:line",
		},
		{
			LTSV:   map[string]string{"test": "line", "valid": "true"},
			Keys:   []string{"Test", "valid"},
			Expect: "valid:true",
		},
		{
			LTSV:   map[string]string{"test": "line", "valid": "true"},
			Keys:   []string{""},
			Expect: "",
		},
	}

	for _, test := range tests {
		converted := FilterFunc(test.LTSV, test.Keys)

		if test.Expect != converted {
			t.Error("<%s> expected, but was <%s>", test.Expect, converted)
		}
	}
}
<commit_msg>test rfc<commit_after>package formatter

import (
	"testing"

	"github.com/sugilog/ltsv-cli.go/io"
)

func TestFilterFormatter(t *testing.T) {
	line := "test:line\tvalid:true"

	tests := []struct {
		Keys   []string
		Expect string
	}{
		{
			Keys:   []string{"test", "valid"},
			Expect: "test:line\tvalid:true",
		},
		{
			Keys:   []string{"test"},
			Expect: "test:line",
		},
		{
			Keys:   []string{"Test", "valid"},
			Expect: "valid:true",
		},
		{
			Keys:   []string{""},
			Expect: "",
		},
	}

	for _, test := range tests {
		formatter := FilterFormatter(test.Keys)
		entry, ok := formatter(io.Entry{Line: line})

		if !ok {
			t.Error("Should be ok")
		}

		if test.Expect != entry.Formatted {
			t.Errorf("<%s> expected, but was <%s>", test.Expect, entry.Formatted)
		}
	}
}

func TestFilterFunc(t *testing.T) {
	ltsv := map[string]string{"test": "line", "valid": "true"}

	tests := []struct {
		Keys   []string
		Expect string
	}{
		{
			Keys:   []string{"test", "valid"},
			Expect: "test:line\tvalid:true",
		},
		{
			Keys:   []string{"test"},
			Expect: "test:line",
		},
		{
			Keys:   []string{"Test", "valid"},
			Expect: "valid:true",
		},
		{
			Keys:   []string{""},
			Expect: "",
		},
	}

	for _, test := range tests {
		converted := FilterFunc(ltsv, test.Keys)

		if test.Expect != converted {
			t.Errorf("<%s> expected, but was <%s>", test.Expect, converted)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// Package jpeg implements a JPEG image decoder and encoder.
//
// JPEG is defined in ITU-T T.81: http://www.w3.org/Graphics/JPEG/itu-t81.pdf.
package jpeg

import (
	"bufio"
	"image"
	"image/color"
	"io"
)

// TODO(nigeltao): fix up the doc comment style so that sentences start with
// the name of the type or function that they annotate.

// A FormatError reports that the input is not a valid JPEG.
type FormatError string

func (e FormatError) Error() string { return "invalid JPEG format: " + string(e) }

// An UnsupportedError reports that the input uses a valid but unimplemented JPEG feature.
type UnsupportedError string

func (e UnsupportedError) Error() string { return "unsupported JPEG feature: " + string(e) }

// Component specification, specified in section B.2.2.
type component struct {
	h  int   // Horizontal sampling factor.
	v  int   // Vertical sampling factor.
	c  uint8 // Component identifier.
	tq uint8 // Quantization table destination selector.
}

const (
	dcTable = 0
	acTable = 1
	maxTc   = 1
	maxTh   = 3
	maxTq   = 3

	// A grayscale JPEG image has only a Y component.
	nGrayComponent = 1
	// A color JPEG image has Y, Cb and Cr components.
	nColorComponent = 3

	// We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
	// number of luma samples per chroma sample is at most 2 in the horizontal
	// and 2 in the vertical direction.
	maxH = 2
	maxV = 2
)

const (
	soiMarker   = 0xd8 // Start Of Image.
	eoiMarker   = 0xd9 // End Of Image.
	sof0Marker  = 0xc0 // Start Of Frame (Baseline).
	sof2Marker  = 0xc2 // Start Of Frame (Progressive).
	dhtMarker   = 0xc4 // Define Huffman Table.
	dqtMarker   = 0xdb // Define Quantization Table.
	sosMarker   = 0xda // Start Of Scan.
	driMarker   = 0xdd // Define Restart Interval.
	rst0Marker  = 0xd0 // ReSTart (0).
	rst7Marker  = 0xd7 // ReSTart (7).
	app0Marker  = 0xe0 // APPlication specific (0).
	app15Marker = 0xef // APPlication specific (15).
	comMarker   = 0xfe // COMment.
)

// unzig maps from the zig-zag ordering to the natural ordering. For example,
// unzig[3] is the column and row of the fourth element in zig-zag order. The
// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
var unzig = [blockSize]int{
	0, 1, 8, 16, 9, 2, 3, 10,
	17, 24, 32, 25, 18, 11, 4, 5,
	12, 19, 26, 33, 40, 48, 41, 34,
	27, 20, 13, 6, 7, 14, 21, 28,
	35, 42, 49, 56, 57, 50, 43, 36,
	29, 22, 15, 23, 30, 37, 44, 51,
	58, 59, 52, 45, 38, 31, 39, 46,
	53, 60, 61, 54, 47, 55, 62, 63,
}

// If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
type Reader interface {
	io.Reader
	ReadByte() (c byte, err error)
}

type decoder struct {
	r             Reader
	b             bits
	width, height int
	img1          *image.Gray
	img3          *image.YCbCr
	ri            int // Restart Interval.
	nComp         int
	progressive   bool
	eobRun        uint16 // End-of-Band run, specified in section G.1.2.2.
	comp          [nColorComponent]component
	progCoeffs    [nColorComponent][]block // Saved state between progressive-mode scans.
	huff          [maxTc + 1][maxTh + 1]huffman
	quant         [maxTq + 1]block // Quantization tables, in zig-zag order.
	tmp           [1024]byte
}

// Reads and ignores the next n bytes.
func (d *decoder) ignore(n int) error {
	for n > 0 {
		m := len(d.tmp)
		if m > n {
			m = n
		}
		_, err := io.ReadFull(d.r, d.tmp[0:m])
		if err != nil {
			return err
		}
		n -= m
	}
	return nil
}

// Specified in section B.2.2.
func (d *decoder) processSOF(n int) error {
	switch n {
	case 6 + 3*nGrayComponent:
		d.nComp = nGrayComponent
	case 6 + 3*nColorComponent:
		d.nComp = nColorComponent
	default:
		return UnsupportedError("SOF has wrong length")
	}
	_, err := io.ReadFull(d.r, d.tmp[:n])
	if err != nil {
		return err
	}
	// We only support 8-bit precision.
	if d.tmp[0] != 8 {
		return UnsupportedError("precision")
	}
	d.height = int(d.tmp[1])<<8 + int(d.tmp[2])
	d.width = int(d.tmp[3])<<8 + int(d.tmp[4])
	if int(d.tmp[5]) != d.nComp {
		return UnsupportedError("SOF has wrong number of image components")
	}
	for i := 0; i < d.nComp; i++ {
		hv := d.tmp[7+3*i]
		d.comp[i].h = int(hv >> 4)
		d.comp[i].v = int(hv & 0x0f)
		d.comp[i].c = d.tmp[6+3*i]
		d.comp[i].tq = d.tmp[8+3*i]
		if d.nComp == nGrayComponent {
			continue
		}
		// For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
		// downsampling ratios. This implies that the (h, v) values for the Y
		// component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
		// values for the Cr and Cb components must be (1, 1).
		if i == 0 {
			if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
				return UnsupportedError("luma downsample ratio")
			}
		} else if hv != 0x11 {
			return UnsupportedError("chroma downsample ratio")
		}
	}
	return nil
}

// Specified in section B.2.4.1.
func (d *decoder) processDQT(n int) error {
	const qtLength = 1 + blockSize
	for ; n >= qtLength; n -= qtLength {
		_, err := io.ReadFull(d.r, d.tmp[0:qtLength])
		if err != nil {
			return err
		}
		pq := d.tmp[0] >> 4
		if pq != 0 {
			return UnsupportedError("bad Pq value")
		}
		tq := d.tmp[0] & 0x0f
		if tq > maxTq {
			return FormatError("bad Tq value")
		}
		for i := range d.quant[tq] {
			d.quant[tq][i] = int32(d.tmp[i+1])
		}
	}
	if n != 0 {
		return FormatError("DQT has wrong length")
	}
	return nil
}

// Specified in section B.2.4.4.
func (d *decoder) processDRI(n int) error {
	if n != 2 {
		return FormatError("DRI has wrong length")
	}
	_, err := io.ReadFull(d.r, d.tmp[0:2])
	if err != nil {
		return err
	}
	d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
	return nil
}

// decode reads a JPEG image from r and returns it as an image.Image.
func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
	if rr, ok := r.(Reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	// Check for the Start Of Image marker.
	_, err := io.ReadFull(d.r, d.tmp[0:2])
	if err != nil {
		return nil, err
	}
	if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
		return nil, FormatError("missing SOI marker")
	}

	// Process the remaining segments until the End Of Image marker.
	for {
		_, err := io.ReadFull(d.r, d.tmp[0:2])
		if err != nil {
			return nil, err
		}
		if d.tmp[0] != 0xff {
			return nil, FormatError("missing 0xff marker start")
		}
		marker := d.tmp[1]
		if marker == eoiMarker { // End Of Image.
			break
		}
		if rst0Marker <= marker && marker <= rst7Marker {
			// Figures B.2 and B.16 of the specification suggest that restart markers should
			// only occur between Entropy Coded Segments and not after the final ECS.
			// However, some encoders may generate incorrect JPEGs with a final restart
			// marker. That restart marker will be seen here instead of inside the processSOS
			// method, and is ignored as a harmless error. Restart markers have no extra data,
			// so we check for this before we read the 16-bit length of the segment.
			continue
		}

		// Read the 16-bit length of the segment. The value includes the 2 bytes for the
		// length itself, so we subtract 2 to get the number of remaining bytes.
		_, err = io.ReadFull(d.r, d.tmp[0:2])
		if err != nil {
			return nil, err
		}
		n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2
		if n < 0 {
			return nil, FormatError("short segment length")
		}

		switch {
		case marker == sof0Marker || marker == sof2Marker: // Start Of Frame.
			d.progressive = marker == sof2Marker
			err = d.processSOF(n)
			if configOnly {
				return nil, err
			}
		case marker == dhtMarker: // Define Huffman Table.
			err = d.processDHT(n)
		case marker == dqtMarker: // Define Quantization Table.
			err = d.processDQT(n)
		case marker == sosMarker: // Start Of Scan.
			err = d.processSOS(n)
		case marker == driMarker: // Define Restart Interval.
			err = d.processDRI(n)
		case app0Marker <= marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
			err = d.ignore(n)
		default:
			err = UnsupportedError("unknown marker")
		}
		if err != nil {
			return nil, err
		}
	}
	if d.img1 != nil {
		return d.img1, nil
	}
	if d.img3 != nil {
		return d.img3, nil
	}
	return nil, FormatError("missing SOS marker")
}

// Decode reads a JPEG image from r and returns it as an image.Image.
func Decode(r io.Reader) (image.Image, error) {
	var d decoder
	return d.decode(r, false)
}

// DecodeConfig returns the color model and dimensions of a JPEG image without
// decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, error) {
	var d decoder
	if _, err := d.decode(r, true); err != nil {
		return image.Config{}, err
	}
	switch d.nComp {
	case nGrayComponent:
		return image.Config{
			ColorModel: color.GrayModel,
			Width:      d.width,
			Height:     d.height,
		}, nil
	case nColorComponent:
		return image.Config{
			ColorModel: color.YCbCrModel,
			Width:      d.width,
			Height:     d.height,
		}, nil
	}
	return image.Config{}, FormatError("missing SOF marker")
}

func init() {
	image.RegisterFormat("jpeg", "\xff\xd8", Decode, DecodeConfig)
}
<commit_msg>image/jpeg: handle fill bytes.<commit_after>// Copyright 2009 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.

// Package jpeg implements a JPEG image decoder and encoder.
//
// JPEG is defined in ITU-T T.81: http://www.w3.org/Graphics/JPEG/itu-t81.pdf.
package jpeg

import (
	"bufio"
	"image"
	"image/color"
	"io"
)

// TODO(nigeltao): fix up the doc comment style so that sentences start with
// the name of the type or function that they annotate.

// A FormatError reports that the input is not a valid JPEG.
type FormatError string

func (e FormatError) Error() string { return "invalid JPEG format: " + string(e) }

// An UnsupportedError reports that the input uses a valid but unimplemented JPEG feature.
type UnsupportedError string

func (e UnsupportedError) Error() string { return "unsupported JPEG feature: " + string(e) }

// Component specification, specified in section B.2.2.
type component struct {
	h  int   // Horizontal sampling factor.
	v  int   // Vertical sampling factor.
	c  uint8 // Component identifier.
	tq uint8 // Quantization table destination selector.
}

const (
	dcTable = 0
	acTable = 1
	maxTc   = 1
	maxTh   = 3
	maxTq   = 3

	// A grayscale JPEG image has only a Y component.
	nGrayComponent = 1
	// A color JPEG image has Y, Cb and Cr components.
	nColorComponent = 3

	// We only support 4:4:4, 4:4:0, 4:2:2 and 4:2:0 downsampling, and therefore the
	// number of luma samples per chroma sample is at most 2 in the horizontal
	// and 2 in the vertical direction.
	maxH = 2
	maxV = 2
)

const (
	soiMarker   = 0xd8 // Start Of Image.
	eoiMarker   = 0xd9 // End Of Image.
	sof0Marker  = 0xc0 // Start Of Frame (Baseline).
	sof2Marker  = 0xc2 // Start Of Frame (Progressive).
	dhtMarker   = 0xc4 // Define Huffman Table.
	dqtMarker   = 0xdb // Define Quantization Table.
	sosMarker   = 0xda // Start Of Scan.
	driMarker   = 0xdd // Define Restart Interval.
	rst0Marker  = 0xd0 // ReSTart (0).
	rst7Marker  = 0xd7 // ReSTart (7).
	app0Marker  = 0xe0 // APPlication specific (0).
	app15Marker = 0xef // APPlication specific (15).
	comMarker   = 0xfe // COMment.
)

// unzig maps from the zig-zag ordering to the natural ordering. For example,
// unzig[3] is the column and row of the fourth element in zig-zag order. The
// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
var unzig = [blockSize]int{
	0, 1, 8, 16, 9, 2, 3, 10,
	17, 24, 32, 25, 18, 11, 4, 5,
	12, 19, 26, 33, 40, 48, 41, 34,
	27, 20, 13, 6, 7, 14, 21, 28,
	35, 42, 49, 56, 57, 50, 43, 36,
	29, 22, 15, 23, 30, 37, 44, 51,
	58, 59, 52, 45, 38, 31, 39, 46,
	53, 60, 61, 54, 47, 55, 62, 63,
}

// If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
type Reader interface {
	io.Reader
	ReadByte() (c byte, err error)
}

type decoder struct {
	r             Reader
	b             bits
	width, height int
	img1          *image.Gray
	img3          *image.YCbCr
	ri            int // Restart Interval.
	nComp         int
	progressive   bool
	eobRun        uint16 // End-of-Band run, specified in section G.1.2.2.
	comp          [nColorComponent]component
	progCoeffs    [nColorComponent][]block // Saved state between progressive-mode scans.
	huff          [maxTc + 1][maxTh + 1]huffman
	quant         [maxTq + 1]block // Quantization tables, in zig-zag order.
	tmp           [1024]byte
}

// Reads and ignores the next n bytes.
func (d *decoder) ignore(n int) error {
	for n > 0 {
		m := len(d.tmp)
		if m > n {
			m = n
		}
		_, err := io.ReadFull(d.r, d.tmp[0:m])
		if err != nil {
			return err
		}
		n -= m
	}
	return nil
}

// Specified in section B.2.2.
func (d *decoder) processSOF(n int) error {
	switch n {
	case 6 + 3*nGrayComponent:
		d.nComp = nGrayComponent
	case 6 + 3*nColorComponent:
		d.nComp = nColorComponent
	default:
		return UnsupportedError("SOF has wrong length")
	}
	_, err := io.ReadFull(d.r, d.tmp[:n])
	if err != nil {
		return err
	}
	// We only support 8-bit precision.
	if d.tmp[0] != 8 {
		return UnsupportedError("precision")
	}
	d.height = int(d.tmp[1])<<8 + int(d.tmp[2])
	d.width = int(d.tmp[3])<<8 + int(d.tmp[4])
	if int(d.tmp[5]) != d.nComp {
		return UnsupportedError("SOF has wrong number of image components")
	}
	for i := 0; i < d.nComp; i++ {
		hv := d.tmp[7+3*i]
		d.comp[i].h = int(hv >> 4)
		d.comp[i].v = int(hv & 0x0f)
		d.comp[i].c = d.tmp[6+3*i]
		d.comp[i].tq = d.tmp[8+3*i]
		if d.nComp == nGrayComponent {
			continue
		}
		// For color images, we only support 4:4:4, 4:4:0, 4:2:2 or 4:2:0 chroma
		// downsampling ratios. This implies that the (h, v) values for the Y
		// component are either (1, 1), (1, 2), (2, 1) or (2, 2), and the (h, v)
		// values for the Cr and Cb components must be (1, 1).
		if i == 0 {
			if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
				return UnsupportedError("luma downsample ratio")
			}
		} else if hv != 0x11 {
			return UnsupportedError("chroma downsample ratio")
		}
	}
	return nil
}

// Specified in section B.2.4.1.
func (d *decoder) processDQT(n int) error {
	const qtLength = 1 + blockSize
	for ; n >= qtLength; n -= qtLength {
		_, err := io.ReadFull(d.r, d.tmp[0:qtLength])
		if err != nil {
			return err
		}
		pq := d.tmp[0] >> 4
		if pq != 0 {
			return UnsupportedError("bad Pq value")
		}
		tq := d.tmp[0] & 0x0f
		if tq > maxTq {
			return FormatError("bad Tq value")
		}
		for i := range d.quant[tq] {
			d.quant[tq][i] = int32(d.tmp[i+1])
		}
	}
	if n != 0 {
		return FormatError("DQT has wrong length")
	}
	return nil
}

// Specified in section B.2.4.4.
func (d *decoder) processDRI(n int) error {
	if n != 2 {
		return FormatError("DRI has wrong length")
	}
	_, err := io.ReadFull(d.r, d.tmp[0:2])
	if err != nil {
		return err
	}
	d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
	return nil
}

// decode reads a JPEG image from r and returns it as an image.Image.
func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
	if rr, ok := r.(Reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	// Check for the Start Of Image marker.
	_, err := io.ReadFull(d.r, d.tmp[0:2])
	if err != nil {
		return nil, err
	}
	if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
		return nil, FormatError("missing SOI marker")
	}

	// Process the remaining segments until the End Of Image marker.
	for {
		_, err := io.ReadFull(d.r, d.tmp[0:2])
		if err != nil {
			return nil, err
		}
		if d.tmp[0] != 0xff {
			return nil, FormatError("missing 0xff marker start")
		}
		marker := d.tmp[1]
		for marker == 0xff {
			// Section B.1.1.2 says, "Any marker may optionally be preceded by any
			// number of fill bytes, which are bytes assigned code X'FF'".
			marker, err = d.r.ReadByte()
			if err != nil {
				return nil, err
			}
		}
		if marker == eoiMarker { // End Of Image.
			break
		}
		if rst0Marker <= marker && marker <= rst7Marker {
			// Figures B.2 and B.16 of the specification suggest that restart markers should
			// only occur between Entropy Coded Segments and not after the final ECS.
			// However, some encoders may generate incorrect JPEGs with a final restart
			// marker. That restart marker will be seen here instead of inside the processSOS
			// method, and is ignored as a harmless error. Restart markers have no extra data,
			// so we check for this before we read the 16-bit length of the segment.
			continue
		}

		// Read the 16-bit length of the segment. The value includes the 2 bytes for the
		// length itself, so we subtract 2 to get the number of remaining bytes.
		_, err = io.ReadFull(d.r, d.tmp[0:2])
		if err != nil {
			return nil, err
		}
		n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2
		if n < 0 {
			return nil, FormatError("short segment length")
		}

		switch {
		case marker == sof0Marker || marker == sof2Marker: // Start Of Frame.
			d.progressive = marker == sof2Marker
			err = d.processSOF(n)
			if configOnly {
				return nil, err
			}
		case marker == dhtMarker: // Define Huffman Table.
			err = d.processDHT(n)
		case marker == dqtMarker: // Define Quantization Table.
			err = d.processDQT(n)
		case marker == sosMarker: // Start Of Scan.
			err = d.processSOS(n)
		case marker == driMarker: // Define Restart Interval.
			err = d.processDRI(n)
		case app0Marker <= marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
			err = d.ignore(n)
		default:
			err = UnsupportedError("unknown marker")
		}
		if err != nil {
			return nil, err
		}
	}
	if d.img1 != nil {
		return d.img1, nil
	}
	if d.img3 != nil {
		return d.img3, nil
	}
	return nil, FormatError("missing SOS marker")
}

// Decode reads a JPEG image from r and returns it as an image.Image.
func Decode(r io.Reader) (image.Image, error) {
	var d decoder
	return d.decode(r, false)
}

// DecodeConfig returns the color model and dimensions of a JPEG image without
// decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, error) {
	var d decoder
	if _, err := d.decode(r, true); err != nil {
		return image.Config{}, err
	}
	switch d.nComp {
	case nGrayComponent:
		return image.Config{
			ColorModel: color.GrayModel,
			Width:      d.width,
			Height:     d.height,
		}, nil
	case nColorComponent:
		return image.Config{
			ColorModel: color.YCbCrModel,
			Width:      d.width,
			Height:     d.height,
		}, nil
	}
	return image.Config{}, FormatError("missing SOF marker")
}

func init() {
	image.RegisterFormat("jpeg", "\xff\xd8", Decode, DecodeConfig)
}
<|endoftext|>


<commit_before>// Copy a whole directory tree. Current implementation is a packaged version of Jaybill McCarthy's code which can be found at http://jayblog.jaybill.com/post/id/26
package copyrecur

import (
	"io"
	"io/ioutil"
	"log"
	"os"
)

// Copies file source to destination dest.
func CopyFile(source string, dest string) (err error) {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()
	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err == nil {
		si, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, si.Mode())
		}

	}
	return
}

// Recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
func CopyDir(source string, dest string) (err error) {
	// get properties of source dir
	fi, err := os.Stat(source)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return &CustomError{"Source is not a directory"}
	}
	// ensure dest dir does not already exist
	_, err = os.Open(dest)
	if !os.IsNotExist(err) {
		return &CustomError{"Destination already exists"}
	}
	// create dest dir
	err = os.MkdirAll(dest, fi.Mode())
	if err != nil {
		return err
	}
	entries, err := ioutil.ReadDir(source)
	for _, entry := range entries {
		if entry.Name() != ".git" {
			sfp := source + "/" + entry.Name()
			dfp := dest + "/" + entry.Name()
			if entry.IsDir() {
				err = CopyDir(sfp, dfp)
				if err != nil {
					log.Println(err)
				}
			} else {
				// perform copy
				err = CopyFile(sfp, dfp)
				if err != nil {
					log.Println(err)
				}
			}
		}

	}
	return
}

// A struct for returning custom error messages
type CustomError struct {
	What string
}

// Returns the error message defined in What as a string
func (e *CustomError) Error() string {
	return e.What
}
<commit_msg>remove .git directories and .gitignore files<commit_after>// Copy a whole directory tree. Current implementation is a packaged version of Jaybill McCarthy's code which can be found at http://jayblog.jaybill.com/post/id/26
package copyrecur

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
)

// Copies file source to destination dest.
func CopyFile(source string, dest string) (err error) {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()
	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err == nil {
		si, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, si.Mode())
		}

	}
	return
}

// Recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
func CopyDir(source string, dest string) (err error) {
	// get properties of source dir
	fi, err := os.Stat(source)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return &CustomError{"Source is not a directory"}
	}
	// ensure dest dir does not already exist
	_, err = os.Open(dest)
	if !os.IsNotExist(err) {
		return &CustomError{"Destination already exists"}
	}
	// create dest dir
	err = os.MkdirAll(dest, fi.Mode())
	if err != nil {
		return err
	}
	entries, err := ioutil.ReadDir(source)
	for _, entry := range entries {
		if entry.Name() != ".git" || entry.Name() != ".gitignore" {
			sfp := source + "/" + entry.Name()
			dfp := dest + "/" + entry.Name()
			if entry.IsDir() {
				err = CopyDir(sfp, dfp)
				if err != nil {
					log.Println(err)
				}
			} else {
				// perform copy
				err = CopyFile(sfp, dfp)
				if err != nil {
					log.Println(err)
				}
			}
		} else {
			fmt.Println(entry.Name())
		}

	}
	return
}

// A struct for returning custom error messages
type CustomError struct {
	What string
}

// Returns the error message defined in What as a string
func (e *CustomError) Error() string {
	return e.What
}
<|endoftext|>