<commit_before>// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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 entry

import (
	"bytes"
	"crypto/sha256"
	"errors"
	"fmt"
	"sort"

	"github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	"github.com/google/tink/go/keyset"
	"github.com/google/tink/go/signature"

	"github.com/google/keytransparency/core/mutator"

	pb "github.com/google/keytransparency/core/api/v1/keytransparency_go_proto"
	tinkpb "github.com/google/tink/proto/tink_go_proto"
)

// MapLogItemFn maps elements from *mutator.LogMessage to KV<index, *pb.EntryUpdate>.
func MapLogItemFn(m *mutator.LogMessage, emit func(index []byte, mutation *pb.EntryUpdate)) error {
	var entry pb.Entry
	if err := proto.Unmarshal(m.Mutation.Entry, &entry); err != nil {
		return err
	}
	emit(entry.Index, &pb.EntryUpdate{
		Mutation:  m.Mutation,
		Committed: m.ExtraData,
	})
	return nil
}

// IsValidEntry checks the internal consistency and correctness of a mutation.
func IsValidEntry(signedEntry *pb.SignedEntry) error {
	// Ensure that the mutation size is within bounds.
	if got, want := proto.Size(signedEntry), mutator.MaxMutationSize; got > want {
		glog.Warningf("mutation is %v bytes, want <= %v", got, want)
		return mutator.ErrSize
	}

	newEntry := pb.Entry{}
	if err := proto.Unmarshal(signedEntry.GetEntry(), &newEntry); err != nil {
		return fmt.Errorf("proto.Unmarshal(): %v", err)
	}

	ks := newEntry.GetAuthorizedKeys()
	return verifyKeys(ks, signedEntry.GetEntry(), signedEntry.GetSignatures())
}

// ReduceFn decides which of multiple updates can be applied in this revision.
func ReduceFn(msgs []*pb.EntryUpdate, leaves []*pb.EntryUpdate,
	emit func(*pb.EntryUpdate), emitErr func(error)) {
	if got := len(leaves); got > 1 {
		emitErr(fmt.Errorf("expected 0 or 1 map leaf for got %v", got))
		return // A bad index should not cause the whole batch to fail.
	}
	var oldValue *pb.SignedEntry // If no map leaf was found, oldValue will be nil.
	if len(leaves) > 0 {
		oldValue = leaves[0].GetMutation()
	}

	if len(msgs) == 0 {
		emitErr(errors.New("no msgs"))
		return // A bad index should not cause the whole batch to fail.
	}

	// Filter for mutations that are valid.
	newEntries := make([]*pb.EntryUpdate, 0, len(msgs))
	for i, msg := range msgs {
		newValue, err := MutateFn(oldValue, msg.Mutation)
		if err != nil {
			emitErr(fmt.Errorf("entry: ReduceFn(msg %d/%d): %v", i, len(msgs)-1, err))
			continue
		}
		newEntries = append(newEntries, &pb.EntryUpdate{
			Mutation:  newValue,
			Committed: msg.Committed,
		})
	}
	if len(newEntries) == 0 {
		emitErr(errors.New("entry: no valid mutations"))
		return // No valid mutations for one index should not cause the whole batch to fail.
	}
	// Choose the mutation deterministically, regardless of the messages order.
	sort.Slice(newEntries, func(i, j int) bool {
		iHash := sha256.Sum256(newEntries[i].GetMutation().GetEntry())
		jHash := sha256.Sum256(newEntries[j].GetMutation().GetEntry())
		return bytes.Compare(iHash[:], jHash[:]) < 0
	})
	emit(newEntries[0])
}

// MutateFn verifies that newSignedEntry is a valid mutation for oldSignedEntry and returns the
// application of newSignedEntry to oldSignedEntry.
func MutateFn(oldSignedEntry, newSignedEntry *pb.SignedEntry) (*pb.SignedEntry, error) {
	if err := IsValidEntry(newSignedEntry); err != nil {
		return nil, err
	}

	newEntry := pb.Entry{}
	if err := proto.Unmarshal(newSignedEntry.GetEntry(), &newEntry); err != nil {
		return nil, fmt.Errorf("proto.Unmarshal(): %v", err)
	}
	oldEntry := pb.Entry{}
	// oldSignedEntry may be nil, resulting an empty oldEntry struct.
	if err := proto.Unmarshal(oldSignedEntry.GetEntry(), &oldEntry); err != nil {
		return nil, fmt.Errorf("proto.Unmarshal(): %v", err)
	}

	// Verify pointer to previous data.  The very first entry will have
	// oldSignedEntry=nil, so its hash is the Sha256 value of nil.
	prevEntryHash := sha256.Sum256(oldSignedEntry.GetEntry())
	if got, want := prevEntryHash[:], newEntry.GetPrevious(); !bytes.Equal(got, want) {
		// Check if this mutation is a replay.
		if bytes.Equal(oldSignedEntry.GetEntry(), newSignedEntry.Entry) {
			glog.Warningf("mutation is a replay of an old one")
			return nil, mutator.ErrReplay
		}
		glog.Warningf("previous entry hash: %x, want %x", got, want)
		return nil, mutator.ErrPreviousHash
	}

	if oldSignedEntry == nil {
		// Skip verificaion checks if there is no previous oldSignedEntry.
		return newSignedEntry, nil
	}

	ks := oldEntry.GetAuthorizedKeys()
	if err := verifyKeys(ks, newSignedEntry.Entry, newSignedEntry.GetSignatures()); err != nil {
		return nil, err
	}

	return newSignedEntry, nil
}

// verifyKeys verifies both old and new authorized keys based on the following
// criteria:
//   1. At least one signature with a key in the entry should exist.
//   2. Signatures with no matching keys are simply ignored.
func verifyKeys(ks *tinkpb.Keyset, data []byte, sigs [][]byte) error {
	if ks == nil {
		return errors.New("entry: nil keyset")
	}
	handle, err := keyset.NewHandleWithNoSecrets(ks)
	if err != nil {
		return fmt.Errorf("tink.KeysetHanldeWithNoSecret(new): %v", err)
	}

	verifier, err := signature.NewVerifier(handle)
	if err != nil {
		return fmt.Errorf("signature.NewVerifier(%v): %v", ks, err)
	}

	for _, sig := range sigs {
		if err := verifier.Verify(sig, data); err == nil {
			return nil
		}
	}
	return mutator.ErrUnauthorized
}
<commit_msg>Fix reversed arguments (#1227)<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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 entry

import (
	"bytes"
	"crypto/sha256"
	"errors"
	"fmt"
	"sort"

	"github.com/golang/glog"
	"github.com/golang/protobuf/proto"
	"github.com/google/tink/go/keyset"
	"github.com/google/tink/go/signature"

	"github.com/google/keytransparency/core/mutator"

	pb "github.com/google/keytransparency/core/api/v1/keytransparency_go_proto"
	tinkpb "github.com/google/tink/proto/tink_go_proto"
)

// MapLogItemFn maps elements from *mutator.LogMessage to KV<index, *pb.EntryUpdate>.
func MapLogItemFn(m *mutator.LogMessage, emit func(index []byte, mutation *pb.EntryUpdate)) error {
	var entry pb.Entry
	if err := proto.Unmarshal(m.Mutation.Entry, &entry); err != nil {
		return err
	}
	emit(entry.Index, &pb.EntryUpdate{
		Mutation:  m.Mutation,
		Committed: m.ExtraData,
	})
	return nil
}

// IsValidEntry checks the internal consistency and correctness of a mutation.
func IsValidEntry(signedEntry *pb.SignedEntry) error {
	// Ensure that the mutation size is within bounds.
	if got, want := proto.Size(signedEntry), mutator.MaxMutationSize; got > want {
		glog.Warningf("mutation is %v bytes, want <= %v", got, want)
		return mutator.ErrSize
	}

	newEntry := pb.Entry{}
	if err := proto.Unmarshal(signedEntry.GetEntry(), &newEntry); err != nil {
		return fmt.Errorf("proto.Unmarshal(): %v", err)
	}

	ks := newEntry.GetAuthorizedKeys()
	return verifyKeys(ks, signedEntry.GetEntry(), signedEntry.GetSignatures())
}

// ReduceFn decides which of multiple updates can be applied in this revision.
func ReduceFn(leaves []*pb.EntryUpdate, msgs []*pb.EntryUpdate,
	emit func(*pb.EntryUpdate), emitErr func(error)) {
	if got := len(leaves); got > 1 {
		emitErr(fmt.Errorf("expected 0 or 1 map leaf for got %v", got))
		return // A bad index should not cause the whole batch to fail.
	}
	var oldValue *pb.SignedEntry // If no map leaf was found, oldValue will be nil.
	if len(leaves) > 0 {
		oldValue = leaves[0].GetMutation()
	}

	if len(msgs) == 0 {
		emitErr(errors.New("no msgs"))
		return // A bad index should not cause the whole batch to fail.
	}

	// Filter for mutations that are valid.
	newEntries := make([]*pb.EntryUpdate, 0, len(msgs))
	for i, msg := range msgs {
		newValue, err := MutateFn(oldValue, msg.GetMutation())
		if err != nil {
			emitErr(fmt.Errorf("entry: ReduceFn(msg %d/%d): %v", i, len(msgs)-1, err))
			continue
		}
		newEntries = append(newEntries, &pb.EntryUpdate{
			Mutation:  newValue,
			Committed: msg.GetCommitted(),
		})
	}
	if len(newEntries) == 0 {
		emitErr(errors.New("entry: no valid mutations"))
		return // No valid mutations for one index should not cause the whole batch to fail.
	}
	// Choose the mutation deterministically, regardless of the messages order.
	sort.Slice(newEntries, func(i, j int) bool {
		iHash := sha256.Sum256(newEntries[i].GetMutation().GetEntry())
		jHash := sha256.Sum256(newEntries[j].GetMutation().GetEntry())
		return bytes.Compare(iHash[:], jHash[:]) < 0
	})
	emit(newEntries[0])
}

// MutateFn verifies that newSignedEntry is a valid mutation for oldSignedEntry and returns the
// application of newSignedEntry to oldSignedEntry.
func MutateFn(oldSignedEntry, newSignedEntry *pb.SignedEntry) (*pb.SignedEntry, error) {
	if err := IsValidEntry(newSignedEntry); err != nil {
		return nil, err
	}

	newEntry := pb.Entry{}
	if err := proto.Unmarshal(newSignedEntry.GetEntry(), &newEntry); err != nil {
		return nil, fmt.Errorf("proto.Unmarshal(): %v", err)
	}
	oldEntry := pb.Entry{}
	// oldSignedEntry may be nil, resulting an empty oldEntry struct.
	if err := proto.Unmarshal(oldSignedEntry.GetEntry(), &oldEntry); err != nil {
		return nil, fmt.Errorf("proto.Unmarshal(): %v", err)
	}

	// Verify pointer to previous data.  The very first entry will have
	// oldSignedEntry=nil, so its hash is the Sha256 value of nil.
	prevEntryHash := sha256.Sum256(oldSignedEntry.GetEntry())
	if got, want := prevEntryHash[:], newEntry.GetPrevious(); !bytes.Equal(got, want) {
		// Check if this mutation is a replay.
		if bytes.Equal(oldSignedEntry.GetEntry(), newSignedEntry.Entry) {
			glog.Warningf("mutation is a replay of an old one")
			return nil, mutator.ErrReplay
		}
		glog.Warningf("previous entry hash: %x, want %x", got, want)
		return nil, mutator.ErrPreviousHash
	}

	if oldSignedEntry == nil {
		// Skip verificaion checks if there is no previous oldSignedEntry.
		return newSignedEntry, nil
	}

	ks := oldEntry.GetAuthorizedKeys()
	if err := verifyKeys(ks, newSignedEntry.Entry, newSignedEntry.GetSignatures()); err != nil {
		return nil, err
	}

	return newSignedEntry, nil
}

// verifyKeys verifies both old and new authorized keys based on the following
// criteria:
//   1. At least one signature with a key in the entry should exist.
//   2. Signatures with no matching keys are simply ignored.
func verifyKeys(ks *tinkpb.Keyset, data []byte, sigs [][]byte) error {
	if ks == nil {
		return errors.New("entry: nil keyset")
	}
	handle, err := keyset.NewHandleWithNoSecrets(ks)
	if err != nil {
		return fmt.Errorf("tink.KeysetHanldeWithNoSecret(new): %v", err)
	}

	verifier, err := signature.NewVerifier(handle)
	if err != nil {
		return fmt.Errorf("signature.NewVerifier(%v): %v", ks, err)
	}

	for _, sig := range sigs {
		if err := verifier.Verify(sig, data); err == nil {
			return nil
		}
	}
	return mutator.ErrUnauthorized
}
<|endoftext|>


<commit_before>package middlewares

import (
	"net/http"

	"math/rand"
	"time"

	"github.com/uber-go/zap"
	"github.com/urfave/negroni"
)

type ZapLoggerMiddleware struct {
	logger zap.Logger
}

func NewZapLoggerMiddleware(logger zap.Logger) *ZapLoggerMiddleware {
	return &ZapLoggerMiddleware{logger: logger}
}

func (middleware *ZapLoggerMiddleware) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request, next http.HandlerFunc) {
	startTime := time.Now()
	requestId := rand.Int63()

	middleware.logger.Info(
		"HTTP Request started",
		zap.String("host", request.Host),
		zap.String("method", request.Method),
		zap.String("path", request.URL.Path),
		zap.Int64("request-id", requestId),
	)

	negroniResponseWriter, ok := responseWriter.(negroni.ResponseWriter)
	if !ok {
		negroniResponseWriter = negroni.NewResponseWriter(responseWriter)
	}

	next(responseWriter, request)

	fields := []zap.Field{
		zap.String("host", request.Host),
		zap.String("method", request.Method),
		zap.String("path", request.URL.Path),
		zap.Int64("request-id", requestId),
		zap.Int("status-code", negroniResponseWriter.Status()),
		zap.Int("body-size", negroniResponseWriter.Size()),
		zap.Duration("duration", time.Since(startTime)),
	}
	if negroniResponseWriter.Status() >= 300 && negroniResponseWriter.Status() < 400 {
		fields = append(fields, zap.String("Location", negroniResponseWriter.Header().Get("Location")))
	}
	middleware.logger.Info("HTTP Request completed", fields...)
}
<commit_msg>Make a context-sensitive logger available to handlers<commit_after>package middlewares

import (
	"net/http"

	"math/rand"
	"time"

	"github.com/gorilla/context"
	"github.com/uber-go/zap"
	"github.com/urfave/negroni"
)

type ZapLoggerMiddleware struct {
	logger zap.Logger
}

func NewZapLoggerMiddleware(logger zap.Logger) *ZapLoggerMiddleware {
	return &ZapLoggerMiddleware{logger: logger}
}

func (middleware *ZapLoggerMiddleware) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request, next http.HandlerFunc) {
	startTime := time.Now()

	requestLogger := middleware.logger.With(zap.Int64("request-id", rand.Int63()))
	context.Set(request, "logger", requestLogger)

	requestLogger.Info(
		"HTTP Request started",
		zap.String("host", request.Host),
		zap.String("method", request.Method),
		zap.String("path", request.URL.Path),
	)

	negroniResponseWriter, ok := responseWriter.(negroni.ResponseWriter)
	if !ok {
		negroniResponseWriter = negroni.NewResponseWriter(responseWriter)
	}

	next(responseWriter, request)

	fields := []zap.Field{
		zap.String("host", request.Host),
		zap.String("method", request.Method),
		zap.String("path", request.URL.Path),
		zap.Int("status-code", negroniResponseWriter.Status()),
		zap.Int("body-size", negroniResponseWriter.Size()),
		zap.Duration("duration", time.Since(startTime)),
	}
	if negroniResponseWriter.Status() >= 300 && negroniResponseWriter.Status() < 400 {
		fields = append(fields, zap.String("Location", negroniResponseWriter.Header().Get("Location")))
	}
	requestLogger.Info("HTTP Request completed", fields...)

	context.Clear(request)
}
<|endoftext|>


<commit_before>package minimalweather

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/elcuervo/geoip"
	"log"
	"os"
	"fmt"
	"math"
	"strings"
	"net/http"
        "html/template"
	"strconv"
)

var c = Pool.Get()

type CityWeather struct {
        City        City        `json:"city"`
	Weather     Weather     `json:"weather"`
        Unit        string      `json:"unit"`
        JSON        string      `json:"-"`
}

func outputWeatherAsJSON(current_city City, current_weather Weather) []byte {
	city_weather := &CityWeather{
		City:        current_city,
		Weather:     current_weather}

	out, _ := json.Marshal(city_weather)

	return out
}

func weatherByCity(w http.ResponseWriter, req *http.Request) {
	city_name := mux.Vars(req)["city"]

	log.Println("By Name:", city_name)

	current_city := <-FindByName(city_name)
	current_weather := <-GetWeather(current_city.Coords)

	if current_city.Error != nil {
		http.NotFound(w, req)
	} else {
		out := outputWeatherAsJSON(current_city, current_weather)
		w.Write(out)
	}
}

func weatherByCoords(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	lat, _ := strconv.ParseFloat(vars["lat"], 64)
	lng, _ := strconv.ParseFloat(vars["lng"], 64)

	log.Println("By Coords:", lat, lng)

	coords := Coordinates{ lat, lng }
	current_city := FindByCoords(coords)
	current_weather := <-GetWeather(coords)

	out := outputWeatherAsJSON(<-current_city, current_weather)

	w.Write(out)
}

func cityByCoords(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	lat, _ := strconv.ParseFloat(vars["lat"], 64)
	lng, _ := strconv.ParseFloat(vars["lng"], 64)

	log.Println("city By Coords:", lat, lng)

	coords := Coordinates{ lat, lng }
	current_city := <-FindByCoords(coords)

        out, _ := json.Marshal(current_city)
	w.Write(out)
}

func ipFromRemote(s string) string {
        index := strings.LastIndex(s, ":")
        if index == -1 {
                return s
        }
        return s[:index]
}

func ipAddress(r *http.Request) string {
        development := os.Getenv("DEVELOPMENT")
        if development != "" {
                return "186.52.170.66"
        }

        hdr := r.Header
        hdrRealIp := hdr.Get("X-Real-Ip")
        hdrForwardedFor := hdr.Get("X-Forwarded-For")

        if hdrRealIp == "" && hdrForwardedFor == "" {
                return ipFromRemote(r.RemoteAddr)
        }

        if hdrForwardedFor != "" {
                // X-Forwarded-For is potentially a list of addresses separated with ","
                parts := strings.Split(hdrForwardedFor, ",")
                for i, p := range parts {
                        parts[i] = strings.TrimSpace(p)
                }
                // TODO: should return first non-local address
                return parts[0]
        }
        return hdrRealIp
}

func geolocate(req *http.Request) geoip.Geolocation {
        var user_addr string
        user_addr = ipAddress(req)
        log.Println(user_addr)

        return <-GetLocation(user_addr)
}

func homepage(w http.ResponseWriter, req *http.Request) {
        var cw *CityWeather
        var coords Coordinates

        location_cookie, err := req.Cookie("mw-location")

        if err == nil {
                log.Println("From Cookie cache")
                parts := strings.Split(location_cookie.Value, "|")
                lat, _ := strconv.ParseFloat(parts[0], 64)
                lng, _ := strconv.ParseFloat(parts[1], 64)
                coords = Coordinates{ lat, lng }
        } else {
                log.Println("From geolocation")
                geo := geolocate(req)
                coords = Coordinates{ geo.Location.Latitude, geo.Location.Longitude }
        }

        city := <-FindByCoords(coords)
        weather := <-GetWeather(city.Coords)

        cw = &CityWeather{ City: city, Weather: weather }

        unit_cookie, err := req.Cookie("mw-unit")
        if err == nil {
                cw.Unit = unit_cookie.Value
        } else {
                cw.Unit = "C"
        }

        if cw.Unit == "F" {
                cw.Weather.Temperature = ((cw.Weather.Temperature*9)/5)+32
        }

        lat, lng := city.Coords.Lat, city.Coords.Lng

        cookie := &http.Cookie{
                Name: "mw-location",
                Value: fmt.Sprintf("%f|%f", lat, lng),
                Path: "/",
        }

        http.SetCookie(w, cookie)

        city_cookie := &http.Cookie{
                Name: "mw-city",
                Value: fmt.Sprintf("%s", city.Name),
                Path: "/",
        }

        http.SetCookie(w, city_cookie)

        t, _ := template.ParseFiles("./website/index.html")
        out, err := json.Marshal(cw)
        cw.JSON = string(out)
        cw.Weather.Temperature = math.Floor(cw.Weather.Temperature)
        err = t.Execute(w, cw)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        }
}

type About struct{}

func about(w http.ResponseWriter, req *http.Request) {
        a := &About{}
        t, _ := template.ParseFiles("./website/about.html")
        err := t.Execute(w, a)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        }
}

func isOk(r *http.Request, rm *mux.RouteMatch) bool {
        ref := r.Referer()
        allowed := ref == "http://localhost:12345/" ||
        ref == "http://minimalweather.com/" ||
        ref == "http://www.minimalweather.com/"
        return allowed
}

func Handler() *mux.Router {
	r := mux.NewRouter()

	r.HandleFunc("/weather/{city}", weatherByCity).Methods("GET").MatcherFunc(isOk)
	r.HandleFunc("/weather/{lat}/{lng}", weatherByCoords).Methods("GET").MatcherFunc(isOk)
	r.HandleFunc("/city/{lat}/{lng}", cityByCoords).Methods("GET").MatcherFunc(isOk)

	r.PathPrefix("/assets").Handler(http.FileServer(http.Dir("./website/")))
        r.HandleFunc("/about", about).Methods("GET")
        r.HandleFunc("/", homepage).Methods("GET")

	return r
}
<commit_msg>I forgot about nimbus :(<commit_after>package minimalweather

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/elcuervo/geoip"
	"log"
	"os"
	"fmt"
	"math"
	"strings"
	"net/http"
        "html/template"
	"strconv"
)

var c = Pool.Get()

type CityWeather struct {
        City        City        `json:"city"`
	Weather     Weather     `json:"weather"`
        Unit        string      `json:"unit"`
        JSON        string      `json:"-"`
}

func outputWeatherAsJSON(current_city City, current_weather Weather) []byte {
	city_weather := &CityWeather{
		City:        current_city,
		Weather:     current_weather}

	out, _ := json.Marshal(city_weather)

	return out
}

func weatherByCity(w http.ResponseWriter, req *http.Request) {
	city_name := mux.Vars(req)["city"]

	log.Println("By Name:", city_name)

	current_city := <-FindByName(city_name)
	current_weather := <-GetWeather(current_city.Coords)

	if current_city.Error != nil {
		http.NotFound(w, req)
	} else {
		out := outputWeatherAsJSON(current_city, current_weather)
		w.Write(out)
	}
}

func weatherByCoords(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	lat, _ := strconv.ParseFloat(vars["lat"], 64)
	lng, _ := strconv.ParseFloat(vars["lng"], 64)

	log.Println("By Coords:", lat, lng)

	coords := Coordinates{ lat, lng }
	current_city := FindByCoords(coords)
	current_weather := <-GetWeather(coords)

	out := outputWeatherAsJSON(<-current_city, current_weather)

	w.Write(out)
}

func cityByCoords(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	lat, _ := strconv.ParseFloat(vars["lat"], 64)
	lng, _ := strconv.ParseFloat(vars["lng"], 64)

	log.Println("city By Coords:", lat, lng)

	coords := Coordinates{ lat, lng }
	current_city := <-FindByCoords(coords)

        out, _ := json.Marshal(current_city)
	w.Write(out)
}

func ipFromRemote(s string) string {
        index := strings.LastIndex(s, ":")
        if index == -1 {
                return s
        }
        return s[:index]
}

func ipAddress(r *http.Request) string {
        development := os.Getenv("DEVELOPMENT")
        if development != "" {
                return "186.52.170.66"
        }

        hdr := r.Header
        hdrRealIp := hdr.Get("X-Real-Ip")
        hdrForwardedFor := hdr.Get("X-Forwarded-For")

        if hdrRealIp == "" && hdrForwardedFor == "" {
                return ipFromRemote(r.RemoteAddr)
        }

        if hdrForwardedFor != "" {
                // X-Forwarded-For is potentially a list of addresses separated with ","
                parts := strings.Split(hdrForwardedFor, ",")
                for i, p := range parts {
                        parts[i] = strings.TrimSpace(p)
                }
                // TODO: should return first non-local address
                return parts[0]
        }
        return hdrRealIp
}

func geolocate(req *http.Request) geoip.Geolocation {
        var user_addr string
        user_addr = ipAddress(req)
        log.Println(user_addr)

        return <-GetLocation(user_addr)
}

func homepage(w http.ResponseWriter, req *http.Request) {
        var cw *CityWeather
        var coords Coordinates

        location_cookie, err := req.Cookie("mw-location")

        if err == nil {
                log.Println("From Cookie cache")
                parts := strings.Split(location_cookie.Value, "|")
                lat, _ := strconv.ParseFloat(parts[0], 64)
                lng, _ := strconv.ParseFloat(parts[1], 64)
                coords = Coordinates{ lat, lng }
        } else {
                log.Println("From geolocation")
                geo := geolocate(req)
                coords = Coordinates{ geo.Location.Latitude, geo.Location.Longitude }
        }

        city := <-FindByCoords(coords)
        weather := <-GetWeather(city.Coords)

        cw = &CityWeather{ City: city, Weather: weather }

        unit_cookie, err := req.Cookie("mw-unit")
        if err == nil {
                cw.Unit = unit_cookie.Value
        } else {
                cw.Unit = "C"
        }

        if cw.Unit == "F" {
                cw.Weather.Temperature = ((cw.Weather.Temperature*9)/5)+32
        }

        lat, lng := city.Coords.Lat, city.Coords.Lng

        cookie := &http.Cookie{
                Name: "mw-location",
                Value: fmt.Sprintf("%f|%f", lat, lng),
                Path: "/",
        }

        http.SetCookie(w, cookie)

        city_cookie := &http.Cookie{
                Name: "mw-city",
                Value: fmt.Sprintf("%s", city.Name),
                Path: "/",
        }

        http.SetCookie(w, city_cookie)

        t, _ := template.ParseFiles("./website/index.html")
        out, err := json.Marshal(cw)
        cw.JSON = string(out)
        cw.Weather.Temperature = math.Floor(cw.Weather.Temperature)
        err = t.Execute(w, cw)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        }
}

type About struct{}

func about(w http.ResponseWriter, req *http.Request) {
        a := &About{}
        t, _ := template.ParseFiles("./website/about.html")
        err := t.Execute(w, a)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        }
}

func isOk(r *http.Request, rm *mux.RouteMatch) bool {
        ref := r.Referer()
        allowed := ref == "http://localhost:12345/" ||
        ref == "http://minimalweather.com/" ||
        ref == "http://nimbus.minimalweather.com/" ||
        ref == "http://www.minimalweather.com/"
        return allowed
}

func Handler() *mux.Router {
	r := mux.NewRouter()

	r.HandleFunc("/weather/{city}", weatherByCity).Methods("GET").MatcherFunc(isOk)
	r.HandleFunc("/weather/{lat}/{lng}", weatherByCoords).Methods("GET").MatcherFunc(isOk)
	r.HandleFunc("/city/{lat}/{lng}", cityByCoords).Methods("GET").MatcherFunc(isOk)

	r.PathPrefix("/assets").Handler(http.FileServer(http.Dir("./website/")))
        r.HandleFunc("/about", about).Methods("GET")
        r.HandleFunc("/", homepage).Methods("GET")

	return r
}
<|endoftext|>


<commit_before>// Copyright 2012 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 build

import (
	"fmt"
	"net/http"

	"appengine"
	"appengine/datastore"
	"cache"
)

// defaultPackages specifies the Package records to be created by initHandler.
var defaultPackages = []*Package{
	{Name: "Go", Kind: "go"},
}

// subRepos specifies the Go project sub-repositories.
var subRepos = []string{
	"codereview",
	"crypto",
	"image",
	"net",
	"talks",
	"exp",
}

// Put subRepos into defaultPackages.
func init() {
	for _, name := range subRepos {
		p := &Package{
			Kind: "subrepo",
			Name: "go." + name,
			Path: "code.google.com/p/go." + name,
		}
		defaultPackages = append(defaultPackages, p)
	}
}

func initHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	defer cache.Tick(c)
	for _, p := range defaultPackages {
		err := datastore.Get(c, p.Key(c), new(Package))
		if _, ok := err.(*datastore.ErrFieldMismatch); ok {
			// Some fields have been removed, so it's okay to ignore this error.
			err = nil
		}
		if err == nil {
			continue
		} else if err != datastore.ErrNoSuchEntity {
			logErr(w, r, err)
			return
		}
		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
			logErr(w, r, err)
			return
		}
	}
	fmt.Fprint(w, "OK")
}
<commit_msg>misc/dashboard: add go.blog sub-repo to dashboard<commit_after>// Copyright 2012 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 build

import (
	"fmt"
	"net/http"

	"appengine"
	"appengine/datastore"
	"cache"
)

// defaultPackages specifies the Package records to be created by initHandler.
var defaultPackages = []*Package{
	{Name: "Go", Kind: "go"},
}

// subRepos specifies the Go project sub-repositories.
var subRepos = []string{
	"blog",
	"codereview",
	"crypto",
	"exp",
	"image",
	"net",
	"talks",
}

// Put subRepos into defaultPackages.
func init() {
	for _, name := range subRepos {
		p := &Package{
			Kind: "subrepo",
			Name: "go." + name,
			Path: "code.google.com/p/go." + name,
		}
		defaultPackages = append(defaultPackages, p)
	}
}

func initHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	defer cache.Tick(c)
	for _, p := range defaultPackages {
		err := datastore.Get(c, p.Key(c), new(Package))
		if _, ok := err.(*datastore.ErrFieldMismatch); ok {
			// Some fields have been removed, so it's okay to ignore this error.
			err = nil
		}
		if err == nil {
			continue
		} else if err != datastore.ErrNoSuchEntity {
			logErr(w, r, err)
			return
		}
		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
			logErr(w, r, err)
			return
		}
	}
	fmt.Fprint(w, "OK")
}
<|endoftext|>


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

// Package handler http server handler functions
package handler

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// validRegex regexp for validating sql variables
var validRegex = regexp.MustCompile(`^[ A-Za-z0-9_@,|:/\[\]\(\)\.\+\*-]*$`)

// const defaultStartTime default REST API query start time value
var defaultStartTime = "-8h"

// json struct used to query data by the POST http request
type dataQuery struct {
	IDs            []string          `json:"ids"`
	Tags           map[string]string `json:"tags"`
	End            interface{}       `json:"end"`
	Start          interface{}       `json:"start"`
	BucketDuration interface{}       `json:"bucketDuration"`
	Limit          json.Number       `json:"limit"`
	Order          string            `json:"order"`
}

// json struct used to parse post data http request
type postDataItem struct {
	Timestamp json.Number `json:"timestamp"`
	Value     json.Number `json:"value"`
}
type postDataItems struct {
	ID   string         `json:"id"`
	Data []postDataItem `json:"data"`
}

// json struct used to parse put tags http request
type putTags struct {
	ID   string            `json:"id"`
	Tags map[string]string `json:"tags"`
}

// parseTags takes a comma separeted key:value list string and returns a map[string]string
// 	e.g.
// 	"warm:kitty,soft:kitty" => {"warm": "kitty", "soft": "kitty"}
func parseTags(tags string) map[string]string {
	vsf := make(map[string]string)

	tagsList := strings.Split(tags, ",")
	for _, tag := range tagsList {
		t := strings.Split(tag, ":")
		if len(t) == 2 {
			vsf[t[0]] = t[1]
		}
	}
	return vsf
}

func validStr(s string) bool {
	valid := validRegex.MatchString(s)
	if !valid {
		log.Printf("Valid string fail: %s\n", s)
	}
	return valid
}

func validTags(tags map[string]string) bool {
	for k, v := range tags {
		if !validStr(k) || !validStr(v) {
			return false
		}
	}

	return true
}

// ParseTenant return the tenant header value or "_ops"
func parseTenant(r *http.Request) string {
	tenant := r.Header.Get("Hawkular-Tenant")
	if tenant == "" {
		tenant = "_ops"
	}

	return tenant
}

func badID(w http.ResponseWriter, v bool) {
	w.WriteHeader(504)
	fmt.Fprintf(w, "{\"error\":\"504\",\"message\":\"Bad metrics IDe - 504\"}")

	if v {
		log.Printf("Bad metrics ID - 504\n")
	}
}

func parseTimespanStrings(e string, s string, b string) (int64, int64, int64, error) {
	var i int64
	var err error
	var start int64
	var end int64
	var bucketDuration int64

	if e == "" {
		end = int64(time.Now().UTC().Unix()) * 1000
	} else if i, err = parseSec(e); err == nil {
		end = i * 1000
	} else {
		return 0, 0, 0, err
	}

	if s == "" {
		i, _ := parseSec(defaultStartTime)
		start = i * 1000
	} else if i, err = parseSec(s); err == nil {
		start = i * 1000
	} else {
		return 0, 0, 0, err
	}

	if b == "" {
		bucketDuration = int64(0)
	} else if i, err = parseSec(b); err == nil {
		bucketDuration = i * 1000
	} else {
		return 0, 0, 0, err
	}

	return end, start, bucketDuration, nil
}

func parseTimespan(r *http.Request) (int64, int64, int64, error) {
	var e string
	var s string
	var b string

	if v, ok := r.Form["end"]; ok && len(v) > 0 {
		e = v[0]
	}

	if v, ok := r.Form["start"]; ok && len(v) > 0 {
		s = v[0]
	}

	if v, ok := r.Form["bucketDuration"]; ok && len(v) > 0 {
		b = v[0]
	}

	return parseTimespanStrings(e, s, b)
}

func baseTime(t int) int64 {
	nowSec := int64(time.Now().UTC().Unix())

	// if time is negative, assume base is now
	if t < 0 {
		return nowSec + int64(t)
	}

	return int64(t)
}

func parseSec(t string) (int64, error) {
	var err error
	var i int
	outSec := int64(0)

	// check for simple int
	if i, err = strconv.Atoi(t); err == nil {
		return baseTime(i / 1e3), nil
	} else if len(t) < 2 {
		// len < 2 and not int is an error
		return 0, err
	}

	// check for ms and mn
	switch t[len(t)-2:] {
	case "ms":
		if i, err = strconv.Atoi(t[:len(t)-2]); err == nil {
			return baseTime(i / 1e3), nil
		}
	case "mn":
		if i, err = strconv.Atoi(t[:len(t)-2]); err == nil {
			return baseTime(i * 60), nil
		}
	}

	// check for s, h and d
	switch t[len(t)-1:] {
	case "s":
		// if this is the "s" from "ms" then outSec != nil
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil && outSec == 0 {
			return baseTime(i), nil
		}
	case "h":
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil {
			return baseTime(i * 60 * 60), nil
		}
	case "d":
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil {
			return baseTime(i * 60 * 60 * 24), nil
		}
	}

	// if here must be an error
	return 0, err
}
<commit_msg>fix timestamp parsing error<commit_after>// Copyright 2016,2017 Yaacov Zamir <kobi.zamir@gmail.com>
// and other contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package handler http server handler functions
package handler

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// validRegex regexp for validating sql variables
var validRegex = regexp.MustCompile(`^[ A-Za-z0-9_@,|:/\[\]\(\)\.\+\*-]*$`)

// const defaultStartTime default REST API query start time value
var defaultStartTime = "-8h"

// json struct used to query data by the POST http request
type dataQuery struct {
	IDs            []string          `json:"ids"`
	Tags           map[string]string `json:"tags"`
	End            interface{}       `json:"end"`
	Start          interface{}       `json:"start"`
	BucketDuration interface{}       `json:"bucketDuration"`
	Limit          json.Number       `json:"limit"`
	Order          string            `json:"order"`
}

// json struct used to parse post data http request
type postDataItem struct {
	Timestamp json.Number `json:"timestamp"`
	Value     json.Number `json:"value"`
}
type postDataItems struct {
	ID   string         `json:"id"`
	Data []postDataItem `json:"data"`
}

// json struct used to parse put tags http request
type putTags struct {
	ID   string            `json:"id"`
	Tags map[string]string `json:"tags"`
}

// parseTags takes a comma separeted key:value list string and returns a map[string]string
// 	e.g.
// 	"warm:kitty,soft:kitty" => {"warm": "kitty", "soft": "kitty"}
func parseTags(tags string) map[string]string {
	vsf := make(map[string]string)

	tagsList := strings.Split(tags, ",")
	for _, tag := range tagsList {
		t := strings.Split(tag, ":")
		if len(t) == 2 {
			vsf[t[0]] = t[1]
		}
	}
	return vsf
}

func validStr(s string) bool {
	valid := validRegex.MatchString(s)
	if !valid {
		log.Printf("Valid string fail: %s\n", s)
	}
	return valid
}

func validTags(tags map[string]string) bool {
	for k, v := range tags {
		if !validStr(k) || !validStr(v) {
			return false
		}
	}

	return true
}

// ParseTenant return the tenant header value or "_ops"
func parseTenant(r *http.Request) string {
	tenant := r.Header.Get("Hawkular-Tenant")
	if tenant == "" {
		tenant = "_ops"
	}

	return tenant
}

func badID(w http.ResponseWriter, v bool) {
	w.WriteHeader(504)
	fmt.Fprintf(w, "{\"error\":\"504\",\"message\":\"Bad metrics IDe - 504\"}")

	if v {
		log.Printf("Bad metrics ID - 504\n")
	}
}

func parseTimespanStrings(e string, s string, b string) (int64, int64, int64, error) {
	var i int64
	var err error
	var start int64
	var end int64
	var bucketDuration int64

	if e == "" {
		end = int64(time.Now().UTC().Unix()) * 1000
	} else if i, err = parseSec(e); err == nil {
		end = i * 1000
	} else {
		return 0, 0, 0, err
	}

	if s == "" {
		i, _ := parseSec(defaultStartTime)
		start = i * 1000
	} else if i, err = parseSec(s); err == nil {
		start = i * 1000
	} else {
		return 0, 0, 0, err
	}

	if b == "" {
		bucketDuration = int64(0)
	} else if i, err = parseSec(b); err == nil {
		bucketDuration = i * 1000
	} else {
		return 0, 0, 0, err
	}

	return end, start, bucketDuration, nil
}

func parseTimespan(r *http.Request) (int64, int64, int64, error) {
	var e string
	var s string
	var b string

	if v, ok := r.Form["end"]; ok && len(v) > 0 {
		e = v[0]
	}

	if v, ok := r.Form["start"]; ok && len(v) > 0 {
		s = v[0]
	}

	if v, ok := r.Form["bucketDuration"]; ok && len(v) > 0 {
		b = v[0]
	}

	return parseTimespanStrings(e, s, b)
}

func baseTime(t int) int64 {
	nowSec := int64(time.Now().UTC().Unix())

	// if time is negative, assume base is now
	if t < 0 {
		return nowSec + int64(t)
	}

	return int64(t)
}

func parseSec(t string) (int64, error) {
	var err error
	var i int
	outSec := int64(0)

	// check for simple int
	if i, err = strconv.Atoi(t); err == nil {
		return baseTime(i / 1e3), nil
	} else if len(t) < 2 {
		// len < 2 and not int is an error
		return 0, err
	}

	// check for ms and mn
	switch t[len(t)-2:] {
	case "ms":
		if i, err = strconv.Atoi(t[:len(t)-2]); err == nil {
			return baseTime(i / 1e3), nil
		}
	case "mn":
		if i, err = strconv.Atoi(t[:len(t)-2]); err == nil {
			return baseTime(i * 60), nil
		}
	}

	// check for s, h and d
	switch t[len(t)-1:] {
	case "s":
		// if this is the "s" from "ms" then outSec != nil
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil && outSec == 0 {
			return baseTime(i), nil
		}
	case "h":
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil {
			return baseTime(i * 60 * 60), nil
		}
	case "d":
		if i, err = strconv.Atoi(t[:len(t)-1]); err == nil {
			return baseTime(i * 60 * 60 * 24), nil
		}
	}

	// if here must be an error
	errMsg := fmt.Sprintf("Can't parse %s timestamp", t)
	return 0, errors.New(errMsg)
}
<|endoftext|>


<commit_before>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2015 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2015 Andrii Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy_header

import (
    "crypto/rand"
    "errors"
    "fmt"
    "net"
    "strings"

    "sippy/utils"
    "sippy/conf"
)

type SipVia struct {
    compactName
    sipver      string
    host        *sippy_conf.MyAddress
    port        *sippy_conf.MyPort
    extra_headers string

    received    *string
    rport       *string
    ttl         *string
    maddr       *string
    branch      *string
    extension   *string

    received_exists    bool
    rport_exists       bool
    ttl_exists         bool
    maddr_exists       bool
    branch_exists      bool
    extension_exists   bool
}

var _sip_via_name compactName = newCompactName("Via", "v")

func ParseSipVia(body string, config sippy_conf.Config) ([]SipHeader, error) {
    vias := make([]SipHeader, 0)
    for _, via := range strings.Split(body, ",") {
        arr := sippy_utils.FieldsN(via, 2)
        if len(arr) != 2 {
            return nil, errors.New("Bad via: '" + via + "'")
        }
        via := &SipVia{
            compactName : _sip_via_name,
            sipver : arr[0],
        }
        arr = strings.Split(arr[1], ";")
        var val *string
        for _, param := range arr[1:] {
            param = strings.TrimSpace(param)
            sparam := strings.SplitN(param, "=", 2)
            val = nil
            if len(sparam) == 2 {
                val = &sparam[1]
            }
            switch sparam[0] {
            case "received":
                via.received = val
                via.received_exists = true
            case "rport":
                via.rport = val
                via.rport_exists = true
            case "ttl":
                via.ttl = val
                via.ttl_exists = true
            case "maddr":
                via.maddr = val
                via.maddr_exists = true
            case "branch":
                via.branch = val
                via.branch_exists = true
            case "extension":
                via.extension = val
                via.extension_exists = true
            default:
                via.extra_headers += ";" + sparam[1]
                if val != nil {
                    via.extra_headers += "=" + *val
                }
            }
        }
        host, port, err := net.SplitHostPort(arr[0])
        if err != nil {
            via.host = sippy_conf.NewMyAddress(arr[0])
            via.port = nil
        } else {
            via.host = sippy_conf.NewMyAddress(host)
            via.port = sippy_conf.NewMyPort(port)
        }
        vias = append(vias, via)
    }
    return vias, nil
}

func NewSipVia(config sippy_conf.Config) *SipVia {
    self := &SipVia{
        compactName : _sip_via_name,
        rport_exists : true,
        sipver      : "SIP/2.0/UDP",
        host        : config.GetMyAddress(),
        port        : config.GetMyPort(),

        received_exists : false,
        ttl_exists      : false,
        maddr_exists    : false,
        branch_exists   : false,
        extension_exists: false,
    }
    return self
}

func (self *SipVia) Body() string {
    return self.LocalBody(nil)
}

func (self *SipVia) LocalBody(hostport *sippy_conf.HostPort) string {
    return self._local_str(hostport)
}

func (self *SipVia) String() string {
    return self.LocalStr(nil, false)
}

func (self *SipVia) LocalStr(hostport *sippy_conf.HostPort, compact bool) string {
    if compact {
        return self.CompactName() + ":" + self.LocalBody(hostport)
    }
    return self.Name() + ":" + self.LocalBody(hostport)
}

func (self *SipVia) _local_str(hostport *sippy_conf.HostPort) string {
    s := ""
    if hostport != nil && self.host.IsSystemDefault() {
        s = self.sipver + " " + hostport.Host.String()
    } else {
        s = self.sipver + " " + self.host.String()
    }
    if self.port != nil {
        if hostport != nil && self.port.IsSystemDefault() {
            s += ":" + hostport.Port.String()
        } else {
            s += ":" + self.port.String()
        }
    }
    for _, it := range []struct{ key string; val *string; exists bool } {
                            {"received", self.received, self.received_exists },
                            {"rport", self.rport, self.rport_exists },
                            {"ttl", self.ttl, self.ttl_exists },
                            {"maddr", self.maddr, self.maddr_exists },
                            {"branch", self.branch, self.branch_exists },
                            {"extension", self.extension, self.extension_exists },
                        } {
        if it.exists {
            s += ";" + it.key
            if it.val != nil {
                s += "=" + *it.val
            }
        }
    }
    return s + self.extra_headers
}

func (self *SipVia) GetCopy() *SipVia {
    tmp := *self
    if self.received != nil { tmp_s := *self.received; tmp.received = &tmp_s }
    if self.rport != nil { tmp_s := *self.rport; tmp.rport = &tmp_s }
    if self.ttl != nil { tmp_s := *self.ttl; tmp.ttl = &tmp_s }
    if self.maddr != nil { tmp_s := *self.maddr; tmp.maddr = &tmp_s }
    if self.branch != nil { tmp_s := *self.branch; tmp.branch = &tmp_s }
    if self.extension != nil { tmp_s := *self.extension; tmp.extension = &tmp_s }
    return &tmp
}

func (self *SipVia) GetCopyAsIface() SipHeader {
    return self.GetCopy()
}

func (self *SipVia) GenBranch() {
    buf := make([]byte, 16)
    rand.Read(buf)
    tmp := "z9hG4bK" + fmt.Sprintf("%x", buf)
    self.branch = &tmp
    self.branch_exists = true
}

func (self *SipVia) GetBranch() string {
    if self.branch_exists && self.branch != nil {
        return *self.branch
    }
    return ""
}

func (self *SipVia) GetAddr(config sippy_conf.Config) (string, string) {
    if self.port == nil {
        return self.host.String(), config.SipPort().String()
    } else {
        return self.host.String(), self.port.String()
    }
}

func (self *SipVia) GetTAddr(config sippy_conf.Config) *sippy_conf.HostPort {
    var host, rport string

    if self.rport_exists && self.rport != nil {
        rport = *self.rport
    } else {
        _, rport = self.GetAddr(config)
    }
    if self.received_exists && self.received != nil {
        host = *self.received
    } else {
        host, _ = self.GetAddr(config)
    }
    return sippy_conf.NewHostPort(host, rport)
}

func (self *SipVia) SetRport(v *string) {
    self.rport_exists = true
    self.rport = v
}

func (self *SipVia) SetReceived(v string) {
    self.received_exists = true
    self.received = &v
}

func (self *SipVia) HasRport() bool {
    return self.rport_exists
}
<commit_msg>fixing typo when parsing extra via params<commit_after>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2015 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2015 Andrii Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy_header

import (
    "crypto/rand"
    "errors"
    "fmt"
    "net"
    "strings"

    "sippy/utils"
    "sippy/conf"
)

type SipVia struct {
    compactName
    sipver      string
    host        *sippy_conf.MyAddress
    port        *sippy_conf.MyPort
    extra_headers string

    received    *string
    rport       *string
    ttl         *string
    maddr       *string
    branch      *string
    extension   *string

    received_exists    bool
    rport_exists       bool
    ttl_exists         bool
    maddr_exists       bool
    branch_exists      bool
    extension_exists   bool
}

var _sip_via_name compactName = newCompactName("Via", "v")

func ParseSipVia(body string, config sippy_conf.Config) ([]SipHeader, error) {
    vias := make([]SipHeader, 0)
    for _, via := range strings.Split(body, ",") {
        arr := sippy_utils.FieldsN(via, 2)
        if len(arr) != 2 {
            return nil, errors.New("Bad via: '" + via + "'")
        }
        via := &SipVia{
            compactName : _sip_via_name,
            sipver : arr[0],
        }
        arr = strings.Split(arr[1], ";")
        var val *string
        for _, param := range arr[1:] {
            param = strings.TrimSpace(param)
            sparam := strings.SplitN(param, "=", 2)
            val = nil
            if len(sparam) == 2 {
                val = &sparam[1]
            }
            switch sparam[0] {
            case "received":
                via.received = val
                via.received_exists = true
            case "rport":
                via.rport = val
                via.rport_exists = true
            case "ttl":
                via.ttl = val
                via.ttl_exists = true
            case "maddr":
                via.maddr = val
                via.maddr_exists = true
            case "branch":
                via.branch = val
                via.branch_exists = true
            case "extension":
                via.extension = val
                via.extension_exists = true
            default:
                via.extra_headers += ";" + sparam[0]
                if val != nil {
                    via.extra_headers += "=" + *val
                }
            }
        }
        host, port, err := net.SplitHostPort(arr[0])
        if err != nil {
            via.host = sippy_conf.NewMyAddress(arr[0])
            via.port = nil
        } else {
            via.host = sippy_conf.NewMyAddress(host)
            via.port = sippy_conf.NewMyPort(port)
        }
        vias = append(vias, via)
    }
    return vias, nil
}

func NewSipVia(config sippy_conf.Config) *SipVia {
    self := &SipVia{
        compactName : _sip_via_name,
        rport_exists : true,
        sipver      : "SIP/2.0/UDP",
        host        : config.GetMyAddress(),
        port        : config.GetMyPort(),

        received_exists : false,
        ttl_exists      : false,
        maddr_exists    : false,
        branch_exists   : false,
        extension_exists: false,
    }
    return self
}

func (self *SipVia) Body() string {
    return self.LocalBody(nil)
}

func (self *SipVia) LocalBody(hostport *sippy_conf.HostPort) string {
    return self._local_str(hostport)
}

func (self *SipVia) String() string {
    return self.LocalStr(nil, false)
}

func (self *SipVia) LocalStr(hostport *sippy_conf.HostPort, compact bool) string {
    if compact {
        return self.CompactName() + ":" + self.LocalBody(hostport)
    }
    return self.Name() + ":" + self.LocalBody(hostport)
}

func (self *SipVia) _local_str(hostport *sippy_conf.HostPort) string {
    s := ""
    if hostport != nil && self.host.IsSystemDefault() {
        s = self.sipver + " " + hostport.Host.String()
    } else {
        s = self.sipver + " " + self.host.String()
    }
    if self.port != nil {
        if hostport != nil && self.port.IsSystemDefault() {
            s += ":" + hostport.Port.String()
        } else {
            s += ":" + self.port.String()
        }
    }
    for _, it := range []struct{ key string; val *string; exists bool } {
                            {"received", self.received, self.received_exists },
                            {"rport", self.rport, self.rport_exists },
                            {"ttl", self.ttl, self.ttl_exists },
                            {"maddr", self.maddr, self.maddr_exists },
                            {"branch", self.branch, self.branch_exists },
                            {"extension", self.extension, self.extension_exists },
                        } {
        if it.exists {
            s += ";" + it.key
            if it.val != nil {
                s += "=" + *it.val
            }
        }
    }
    return s + self.extra_headers
}

func (self *SipVia) GetCopy() *SipVia {
    tmp := *self
    if self.received != nil { tmp_s := *self.received; tmp.received = &tmp_s }
    if self.rport != nil { tmp_s := *self.rport; tmp.rport = &tmp_s }
    if self.ttl != nil { tmp_s := *self.ttl; tmp.ttl = &tmp_s }
    if self.maddr != nil { tmp_s := *self.maddr; tmp.maddr = &tmp_s }
    if self.branch != nil { tmp_s := *self.branch; tmp.branch = &tmp_s }
    if self.extension != nil { tmp_s := *self.extension; tmp.extension = &tmp_s }
    return &tmp
}

func (self *SipVia) GetCopyAsIface() SipHeader {
    return self.GetCopy()
}

func (self *SipVia) GenBranch() {
    buf := make([]byte, 16)
    rand.Read(buf)
    tmp := "z9hG4bK" + fmt.Sprintf("%x", buf)
    self.branch = &tmp
    self.branch_exists = true
}

func (self *SipVia) GetBranch() string {
    if self.branch_exists && self.branch != nil {
        return *self.branch
    }
    return ""
}

func (self *SipVia) GetAddr(config sippy_conf.Config) (string, string) {
    if self.port == nil {
        return self.host.String(), config.SipPort().String()
    } else {
        return self.host.String(), self.port.String()
    }
}

func (self *SipVia) GetTAddr(config sippy_conf.Config) *sippy_conf.HostPort {
    var host, rport string

    if self.rport_exists && self.rport != nil {
        rport = *self.rport
    } else {
        _, rport = self.GetAddr(config)
    }
    if self.received_exists && self.received != nil {
        host = *self.received
    } else {
        host, _ = self.GetAddr(config)
    }
    return sippy_conf.NewHostPort(host, rport)
}

func (self *SipVia) SetRport(v *string) {
    self.rport_exists = true
    self.rport = v
}

func (self *SipVia) SetReceived(v string) {
    self.received_exists = true
    self.received = &v
}

func (self *SipVia) HasRport() bool {
    return self.rport_exists
}
<|endoftext|>


<commit_before>// Package command provides commands for querying both, server and client.
package command

type CommandType int

const (
	REGISTER CommandType = iota //Register a user
	MESSAGE                     //Message in Value
	BLOGIN
	BLOGOUT
	BMESSAGE //Broadcast-Message
)

//Every Command has a type and a value for sending arbitrary data.
type Command struct {
	Type  CommandType
	Value []byte
}
<commit_msg>added further description<commit_after>// Package command provides commands for querying both, server and client.
package command

type CommandType int

const (
	REGISTER CommandType = iota //Register a user
	//Text-Messaging Commands
	BMESSAGE //Broadcast-Message
	UMESSAGE //Unicast-Message
	MMESSAGE //Multicast-Message
	//System Commands
	BLOGIN  //Broadcast-Login
	BLOGOUT //Broadcast-Logout
)

//Every Command has a type and a value for sending arbitrary data.
type Command struct {
	Type  CommandType
	Value []byte
}
<|endoftext|>


<commit_before>//Contains all message related stuff
package message

<commit_msg>added Message struct<commit_after>//will all message related stuff
package message

import "gofire/user"

type Message struct {
	User *user.User //User who sended the message
	Msg []byte //For arbitrary data
}<|endoftext|>


<commit_before>package saml

import (
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// UserRequest represents a request submitted from an user.
type UserRequest struct {
	Context    context.Context
	RemoteAddr string
	Method     string
	RequestURI string
	Header     http.Header
	Form       string
	Body       string
}

// String returns a formatted log with the user request, useful for debugging.
func (ur UserRequest) String() string {
	lines := []string{}

	if ur.Context != nil {
		lines = append(lines, fmt.Sprintf("Context: %v", ur.Context))
	}

	lines = append(lines, fmt.Sprintf("Method: %s", ur.Method))
	lines = append(lines, fmt.Sprintf("RemoteAddr: %s", ur.RemoteAddr))
	lines = append(lines, fmt.Sprintf("RequestURI: %s", ur.RequestURI))
	lines = append(lines, fmt.Sprintf("Header: %#v", ur.Header))

	if ur.Form != "" {
		lines = append(lines, fmt.Sprintf("Form: %s", ur.Form))
	}

	if ur.Body != "" {
		lines = append(lines, fmt.Sprintf("Body: %s", ur.Body))
	}

	return strings.Join(lines, "\n")
}

var logger Logger = &simpleLogger{log.New(os.Stdout, "SAML: ", log.Flags())}

// simpleLogger implements a Logger that treats fatal errors as regular
// ones.
type simpleLogger struct {
	lg *log.Logger
}

// Fatalf satisfies Logger.
func (s *simpleLogger) Fatalf(f string, v ...interface{}) {
	s.lg.Printf(f, v...)
}

// Fatal satisfies Logger.
func (s *simpleLogger) Fatal(v ...interface{}) {
	s.lg.Print(v...)
}

// Printf satisfies Logger.
func (s *simpleLogger) Printf(f string, v ...interface{}) {
	s.lg.Printf(f, v...)
}

// Print satisfies Logger.
func (s *simpleLogger) Print(v ...interface{}) {
	s.lg.Print(v...)
}

// Logger provides methods for request logging and debugging.
type Logger interface {
	Printf(s string, v ...interface{})

	Print(v ...interface{})

	Fatalf(s string, v ...interface{})

	Fatal(v ...interface{})
}

// InspectRequest creates a *UserRequest from a *http.Request
func InspectRequest(r *http.Request) *UserRequest {
	if r == nil {
		return nil
	}

	var body []byte
	if r.Body != nil {
		var err error
		// Read body contents.
		body, err = ioutil.ReadAll(r.Body)
		if err != nil {
			body = []byte(fmt.Sprintf("[%v]", err.Error()))
		} else {
			// Reset body to original state.
			r.Body = ioutil.NopCloser(bytes.NewBuffer(body))
		}
	}

	return &UserRequest{
		Context:    r.Context(),
		RemoteAddr: r.RemoteAddr,
		Method:     r.Method,
		RequestURI: r.RequestURI,
		Header:     r.Header,
		Form:       r.Form.Encode(),
		Body:       string(body),
	}
}

// Log prints logging message, not necessarily an error.
func Log(v ...interface{}) {
	logger.Print(v...)
}

// Logf prints a formatted logging message, not necessarily an error.
func Logf(s string, v ...interface{}) {
	logger.Printf(s, v...)
}

// Fatal prints an error. This does not end the execution of the program.
func Fatal(v ...interface{}) {
	logger.Fatal(v...)
}

// Fatalf prints a formatted error. This does not end the execution of the
// program.
func Fatalf(s string, v ...interface{}) {
	logger.Fatalf(s, v...)
}

// SetLogger determines which logger to use.
func SetLogger(lg Logger) {
	logger = lg
}

var _ = Logger(&simpleLogger{})
<commit_msg>remove context from error message<commit_after>package saml

import (
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// UserRequest represents a request submitted from an user.
type UserRequest struct {
	Context    context.Context
	RemoteAddr string
	Method     string
	RequestURI string
	Header     http.Header
	Form       string
	Body       string
}

// String returns a formatted log with the user request, useful for debugging.
func (ur UserRequest) String() string {
	lines := []string{}

	lines = append(lines, fmt.Sprintf("Method: %s", ur.Method))
	lines = append(lines, fmt.Sprintf("RemoteAddr: %s", ur.RemoteAddr))
	lines = append(lines, fmt.Sprintf("RequestURI: %s", ur.RequestURI))
	lines = append(lines, fmt.Sprintf("Header: %#v", ur.Header))

	if ur.Form != "" {
		lines = append(lines, fmt.Sprintf("Form: %s", ur.Form))
	}

	if ur.Body != "" {
		lines = append(lines, fmt.Sprintf("Body: %s", ur.Body))
	}

	return strings.Join(lines, "\n")
}

var logger Logger = &simpleLogger{log.New(os.Stdout, "SAML: ", log.Flags())}

// simpleLogger implements a Logger that treats fatal errors as regular
// ones.
type simpleLogger struct {
	lg *log.Logger
}

// Fatalf satisfies Logger.
func (s *simpleLogger) Fatalf(f string, v ...interface{}) {
	s.lg.Printf(f, v...)
}

// Fatal satisfies Logger.
func (s *simpleLogger) Fatal(v ...interface{}) {
	s.lg.Print(v...)
}

// Printf satisfies Logger.
func (s *simpleLogger) Printf(f string, v ...interface{}) {
	s.lg.Printf(f, v...)
}

// Print satisfies Logger.
func (s *simpleLogger) Print(v ...interface{}) {
	s.lg.Print(v...)
}

// Logger provides methods for request logging and debugging.
type Logger interface {
	Printf(s string, v ...interface{})

	Print(v ...interface{})

	Fatalf(s string, v ...interface{})

	Fatal(v ...interface{})
}

// InspectRequest creates a *UserRequest from a *http.Request
func InspectRequest(r *http.Request) *UserRequest {
	if r == nil {
		return nil
	}

	var body []byte
	if r.Body != nil {
		var err error
		// Read body contents.
		body, err = ioutil.ReadAll(r.Body)
		if err != nil {
			body = []byte(fmt.Sprintf("[%v]", err.Error()))
		} else {
			// Reset body to original state.
			r.Body = ioutil.NopCloser(bytes.NewBuffer(body))
		}
	}

	return &UserRequest{
		Context:    r.Context(),
		RemoteAddr: r.RemoteAddr,
		Method:     r.Method,
		RequestURI: r.RequestURI,
		Header:     r.Header,
		Form:       r.Form.Encode(),
		Body:       string(body),
	}
}

// Log prints logging message, not necessarily an error.
func Log(v ...interface{}) {
	logger.Print(v...)
}

// Logf prints a formatted logging message, not necessarily an error.
func Logf(s string, v ...interface{}) {
	logger.Printf(s, v...)
}

// Fatal prints an error. This does not end the execution of the program.
func Fatal(v ...interface{}) {
	logger.Fatal(v...)
}

// Fatalf prints a formatted error. This does not end the execution of the
// program.
func Fatalf(s string, v ...interface{}) {
	logger.Fatalf(s, v...)
}

// SetLogger determines which logger to use.
func SetLogger(lg Logger) {
	logger = lg
}

var _ = Logger(&simpleLogger{})
<|endoftext|>


<commit_before>// Package logger.
package logger

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

// Level describes the chosen log level
type Level int

// LevelLogger represents levelled logger.
type LevelLogger struct {
	write  int32
	level  Level
	prefix string
	Logger *log.Logger
}

// skipLogging exists to prevent calling underlying logger methods when not needed.
func (n *LevelLogger) skipLogging() bool {
	return atomic.LoadInt32(&n.write) == 0
}

// Print calls underlying Logger Print func.
func (n *LevelLogger) Print(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Print(v...)
}

// Printf calls underlying Logger Printf func.
func (n *LevelLogger) Printf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Printf(format, v...)
}

// Println calls underlying Logger Println func.
func (n *LevelLogger) Println(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Println(v...)
}

// Fatal calls underlying Logger Fatal func.
func (n *LevelLogger) Fatal(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatal(v...)
}

// Fatalf calls underlying Logger Fatalf func.
func (n *LevelLogger) Fatalf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatalf(format, v...)
}

// Fatalln calls underlying Logger Fatalln func.
func (n *LevelLogger) Fatalln(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatalln(v...)
}

// Panic calls underlying Logger Panic func.
func (n *LevelLogger) Panic(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panic(v...)
}

// Panicf calls underlying Logger Panicf func.
func (n *LevelLogger) Panicf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panicf(format, v...)
}

// Panicln calls underlying Logger Panicln func.
func (n *LevelLogger) Panicln(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panicln(v...)
}

const (
	LevelTrace Level = iota
	LevelDebug
	LevelInfo
	LevelWarn
	LevelError
	LevelCritical
	LevelFatal
	LevelNone

	DefaultLogThreshold    = LevelInfo
	DefaultStdoutThreshold = LevelInfo
)

var (
	logger *log.Logger

	LogHandle  io.Writer = ioutil.Discard
	OutHandle  io.Writer = os.Stdout
	BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle)

	Flag int = log.Ldate | log.Ltime

	TRACE    *LevelLogger = &LevelLogger{level: LevelTrace, Logger: logger, prefix: "[T]: "}
	DEBUG    *LevelLogger = &LevelLogger{level: LevelDebug, Logger: logger, prefix: "[D]: "}
	INFO     *LevelLogger = &LevelLogger{level: LevelInfo, Logger: logger, prefix: "[I]: "}
	WARN     *LevelLogger = &LevelLogger{level: LevelWarn, Logger: logger, prefix: "[W]: "}
	ERROR    *LevelLogger = &LevelLogger{level: LevelError, Logger: logger, prefix: "[E]: "}
	CRITICAL *LevelLogger = &LevelLogger{level: LevelCritical, Logger: logger, prefix: "[C]: "}
	FATAL    *LevelLogger = &LevelLogger{level: LevelFatal, Logger: logger, prefix: "[F]: "}

	loggers []*LevelLogger = []*LevelLogger{TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, FATAL}

	logThreshold    Level = DefaultLogThreshold
	outputThreshold Level = DefaultStdoutThreshold
)

var LevelMatches = map[string]Level{
	"TRACE":    LevelTrace,
	"DEBUG":    LevelDebug,
	"INFO":     LevelInfo,
	"WARN":     LevelWarn,
	"ERROR":    LevelError,
	"CRITICAL": LevelCritical,
	"FATAL":    LevelFatal,
	"NONE":     LevelNone,
}

func init() {
	initialize()
}

// initialize initializes loggers.
func initialize() {
	BothHandle = io.MultiWriter(LogHandle, OutHandle)
	for i, l := range loggers {

		var handler io.Writer

		if l.level < outputThreshold && l.level < logThreshold {
			atomic.StoreInt32(&loggers[i].write, 0)
			handler = ioutil.Discard
		} else if l.level >= outputThreshold && l.level >= logThreshold {
			atomic.StoreInt32(&loggers[i].write, 1)
			handler = BothHandle
		} else if l.level >= outputThreshold && l.level < logThreshold {
			atomic.StoreInt32(&loggers[i].write, 1)
			handler = OutHandle
		} else {
			atomic.StoreInt32(&loggers[i].write, 1)
			handler = LogHandle
		}

		l.Logger = log.New(handler, l.prefix, Flag)
	}
}

// Ensures that the level provided is within the bounds of available levels.
func levelCheck(level Level) Level {
	switch {
	case level <= LevelTrace:
		return LevelTrace
	case level >= LevelFatal:
		return LevelFatal
	default:
		return level
	}
}

// SetLogThreshold establishes a threshold where anything matching or above will be logged.
func SetLogThreshold(level Level) {
	thresholdChanged := level != logThreshold
	if thresholdChanged {
		logThreshold = levelCheck(level)
		initialize()
	}
}

// SetStdoutThreshold establishes a threshold where anything matching or above will be output.
func SetStdoutThreshold(level Level) {
	thresholdChanged := level != outputThreshold
	if thresholdChanged {
		outputThreshold = levelCheck(level)
		initialize()
	}
}

// SetLogFile sets the LogHandle to a io.writer created for the file behind the given file path.
// Will append to this file.
func SetLogFile(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	LogHandle = file
	initialize()
	return nil
}

// SetLogFlag sets global log flag used in package.
func SetLogFlag(flag int) {
	flagChanged := flag != Flag
	Flag = flag
	if flagChanged {
		initialize()
	}
}
<commit_msg>make LevelLogger unwritable while setting new Logger<commit_after>// Package logger.
package logger

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

// Level describes the chosen log level
type Level int

// LevelLogger represents levelled logger.
type LevelLogger struct {
	writable int32
	level    Level
	prefix   string
	Logger   *log.Logger
}

// skipLogging exists to prevent calling underlying logger methods when not needed.
func (n *LevelLogger) skipLogging() bool {
	return atomic.LoadInt32(&n.writable) == 0
}

// Print calls underlying Logger Print func.
func (n *LevelLogger) Print(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Print(v...)
}

// Printf calls underlying Logger Printf func.
func (n *LevelLogger) Printf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Printf(format, v...)
}

// Println calls underlying Logger Println func.
func (n *LevelLogger) Println(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Println(v...)
}

// Fatal calls underlying Logger Fatal func.
func (n *LevelLogger) Fatal(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatal(v...)
}

// Fatalf calls underlying Logger Fatalf func.
func (n *LevelLogger) Fatalf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatalf(format, v...)
}

// Fatalln calls underlying Logger Fatalln func.
func (n *LevelLogger) Fatalln(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Fatalln(v...)
}

// Panic calls underlying Logger Panic func.
func (n *LevelLogger) Panic(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panic(v...)
}

// Panicf calls underlying Logger Panicf func.
func (n *LevelLogger) Panicf(format string, v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panicf(format, v...)
}

// Panicln calls underlying Logger Panicln func.
func (n *LevelLogger) Panicln(v ...interface{}) {
	if ok := n.skipLogging(); ok {
		return
	}
	n.Logger.Panicln(v...)
}

const (
	LevelTrace Level = iota
	LevelDebug
	LevelInfo
	LevelWarn
	LevelError
	LevelCritical
	LevelFatal
	LevelNone

	DefaultLogThreshold    = LevelInfo
	DefaultStdoutThreshold = LevelInfo
)

var (
	logger *log.Logger

	LogHandle  io.Writer = ioutil.Discard
	OutHandle  io.Writer = os.Stdout
	BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle)

	Flag int = log.Ldate | log.Ltime

	TRACE    *LevelLogger = &LevelLogger{level: LevelTrace, Logger: logger, prefix: "[T]: "}
	DEBUG    *LevelLogger = &LevelLogger{level: LevelDebug, Logger: logger, prefix: "[D]: "}
	INFO     *LevelLogger = &LevelLogger{level: LevelInfo, Logger: logger, prefix: "[I]: "}
	WARN     *LevelLogger = &LevelLogger{level: LevelWarn, Logger: logger, prefix: "[W]: "}
	ERROR    *LevelLogger = &LevelLogger{level: LevelError, Logger: logger, prefix: "[E]: "}
	CRITICAL *LevelLogger = &LevelLogger{level: LevelCritical, Logger: logger, prefix: "[C]: "}
	FATAL    *LevelLogger = &LevelLogger{level: LevelFatal, Logger: logger, prefix: "[F]: "}

	loggers []*LevelLogger = []*LevelLogger{TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, FATAL}

	logThreshold    Level = DefaultLogThreshold
	outputThreshold Level = DefaultStdoutThreshold
)

var LevelMatches = map[string]Level{
	"TRACE":    LevelTrace,
	"DEBUG":    LevelDebug,
	"INFO":     LevelInfo,
	"WARN":     LevelWarn,
	"ERROR":    LevelError,
	"CRITICAL": LevelCritical,
	"FATAL":    LevelFatal,
	"NONE":     LevelNone,
}

func init() {
	initialize()
}

// initialize initializes loggers.
func initialize() {
	BothHandle = io.MultiWriter(LogHandle, OutHandle)
	for _, l := range loggers {

		var handler io.Writer
		var writable int32

		if l.level < outputThreshold && l.level < logThreshold {
			writable = 0
			handler = ioutil.Discard
		} else if l.level >= outputThreshold && l.level >= logThreshold {
			writable = 1
			handler = BothHandle
		} else if l.level >= outputThreshold && l.level < logThreshold {
			writable = 1
			handler = OutHandle
		} else {
			writable = 1
			handler = LogHandle
		}

		atomic.StoreInt32(&l.writable, 0)
		l.Logger = log.New(handler, l.prefix, Flag)
		atomic.StoreInt32(&l.writable, writable)
	}
}

// Ensures that the level provided is within the bounds of available levels.
func levelCheck(level Level) Level {
	switch {
	case level <= LevelTrace:
		return LevelTrace
	case level >= LevelFatal:
		return LevelFatal
	default:
		return level
	}
}

// SetLogThreshold establishes a threshold where anything matching or above will be logged.
func SetLogThreshold(level Level) {
	thresholdChanged := level != logThreshold
	if thresholdChanged {
		logThreshold = levelCheck(level)
		initialize()
	}
}

// SetStdoutThreshold establishes a threshold where anything matching or above will be output.
func SetStdoutThreshold(level Level) {
	thresholdChanged := level != outputThreshold
	if thresholdChanged {
		outputThreshold = levelCheck(level)
		initialize()
	}
}

// SetLogFile sets the LogHandle to a io.writer created for the file behind the given file path.
// Will append to this file.
func SetLogFile(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	LogHandle = file
	initialize()
	return nil
}

// SetLogFlag sets global log flag used in package.
func SetLogFlag(flag int) {
	flagChanged := flag != Flag
	Flag = flag
	if flagChanged {
		initialize()
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Martini Authors
// Copyright 2014 Unknwon
//
// 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 macaron

import (
	"fmt"
	"log"
	"net/http"
	"runtime"
	"time"
)

var isWindows bool

func init() {
	isWindows = runtime.GOOS == "windows"
}

// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
func Logger() Handler {
	return func(ctx *Context, log *log.Logger) {
		start := time.Now()

		log.Printf("Started %s %s for %s", ctx.Req.Method, ctx.Req.URL.Path, ctx.RemoteAddr())

		rw := ctx.Resp.(ResponseWriter)
		ctx.Next()

		content := fmt.Sprintf("Completed %s %v %s in %v",  ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
		if !isWindows {
			switch rw.Status() {
			case 200, 201, 202:
				content = fmt.Sprintf("\033[1;32m%s\033[0m", content)
			case 301, 302:
				content = fmt.Sprintf("\033[1;37m%s\033[0m", content)
			case 304:
				content = fmt.Sprintf("\033[1;33m%s\033[0m", content)
			case 401, 403:
				content = fmt.Sprintf("\033[4;31m%s\033[0m", content)
			case 404:
				content = fmt.Sprintf("\033[1;31m%s\033[0m", content)
			case 500:
				content = fmt.Sprintf("\033[1;36m%s\033[0m", content)
			}
		}
		log.Println(content)
	}
}
<commit_msg>log the entire "RequestURI", not only "URL.Path"<commit_after>// Copyright 2013 Martini Authors
// Copyright 2014 Unknwon
//
// 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 macaron

import (
	"fmt"
	"log"
	"net/http"
	"runtime"
	"time"
)

var isWindows bool

func init() {
	isWindows = runtime.GOOS == "windows"
}

// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
func Logger() Handler {
	return func(ctx *Context, log *log.Logger) {
		start := time.Now()

		log.Printf("Started %s %s for %s", ctx.Req.Method,ctx.Req.RequestURI, ctx.RemoteAddr())

		rw := ctx.Resp.(ResponseWriter)
		ctx.Next()

		content := fmt.Sprintf("Completed %s %v %s in %v",  ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
		if !isWindows {
			switch rw.Status() {
			case 200, 201, 202:
				content = fmt.Sprintf("\033[1;32m%s\033[0m", content)
			case 301, 302:
				content = fmt.Sprintf("\033[1;37m%s\033[0m", content)
			case 304:
				content = fmt.Sprintf("\033[1;33m%s\033[0m", content)
			case 401, 403:
				content = fmt.Sprintf("\033[4;31m%s\033[0m", content)
			case 404:
				content = fmt.Sprintf("\033[1;31m%s\033[0m", content)
			case 500:
				content = fmt.Sprintf("\033[1;36m%s\033[0m", content)
			}
		}
		log.Println(content)
	}
}
<|endoftext|>


<commit_before>package xlog

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

// Level describes a logging level.
type Level int

const (
	Debug Level = 1 << iota
	Info        = 1 << iota
	Notice      = 1 << iota
	Warning     = 1 << iota
	Error       = 1 << iota
	Critical    = 1 << iota
	Alert       = 1 << iota
	Emergency   = 1 << iota
)

// Levels maps Level to a string representation.
var Levels = map[Level]string{
	Debug: "DEBUG",
	Info: "INFO",
	Notice: "NOTICE",
	Warning: "WARNING",
	Error: "ERROR",
	Critical: "CRITICAL",
	Alert: "ALERT",
	Emergency: "EMERGENCY",
}

// FileAliases maps file aliases to real file pointers.
var FileAliases = map[string]*os.File{
	"stdout": os.Stdout,
	"stdin": os.Stdin,
	"stderr": os.Stderr,
}

var (
	// DefaultDateFormat is the date format to use when none has been specified.
	DefaultDateFormat = "2006-01-02 15:04:05.000"

	// DefaultMessageFormat is the message format to use when none has been specified.
	DefaultMessageFormat = "{date|2006-01-02 15:04:05.000} {name}.{level} {message}"

	// FileFlags defines the file open options.
	FileOpenFlags int = os.O_RDWR|os.O_CREATE|os.O_APPEND

	// FileMode defines the mode files are opened in.
	FileOpenMode os.FileMode = 0666

	// PanicOnFileErrors defines whether the logger should panic when opening a file
	// fails. When set to false, any file open errors are ignored, and the file won't be
	// appended.
	PanicOnFileErrors = true

	// LoggerCapacity defines the initial capacity for each type of logger.
	LoggerCapacity = 2

	// FatalOn represents levels that causes the application to exit.
	FatalOn Level = 0

	// PanicOn represents levels that causes the application to panic.
	PanicOn Level = 0
)

// Loggable is an interface that provides methods for logging messages to
// various levels.
type Loggable interface {
	Log(level Level, v ...interface{})
	Logf(level Level, format string, v ...interface{})
	Debug(v ...interface{})
	Debugf(format string, v ...interface{})
	Info(v ...interface{})
	Infof(format string, v ...interface{})
	Warning(v ...interface{})
	Warningf(format string, v ...interface{})
	Error(v ...interface{})
	Errorf(format string, v ...interface{})
	Critical(v ...interface{})
	Criticalf(format string, v ...interface{})
	Alert(v ...interface{})
	Alertf(format string, v ...interface{})
	Emergency(v ...interface{})
	Emergencyf(format string, v ...interface{})
}

// Logger is a light weight logger designed to write to multiple files at different
// log levels.
type Logger struct {
	// Enabled defines whether logging is enabled.
	Enabled  bool

	// Formatter is used to format the log messages.
	Formatter Formatter

	// Loggers holds the appended file loggers.
	Loggers LoggerMap

	// pointers contains any files that have been opened for logging.
	pointers []*os.File

	// closed defines whether the logger has been closed.
	closed bool
}

// NewLogger returns a *Logger instance that's been initialized with default values.
func NewLogger(name string) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: NewDefaultFormatter(DefaultMessageFormat, name),
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// NewMultiLogger returns a *Logger instance that's been initialized with one or
// more files at the given level.
func NewMultiLogger(name string, files []string, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppend(files, level);
	return logger;
}

// NewMultiWriterLogger returns a *Logger instance that's been initialized with one or
// more writers at the given level.
func NewMultiWriterLogger(name string, writers []io.Writer, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppendWriter(writers, level);
	return logger;
}

// NewFormattedLogger returns a *Logger instance using the provided formatter.
func NewFormattedLogger(formatter Formatter) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: formatter,
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// Append adds a file that will be written to at the given level or greater.
// The file argument may be either the full path to a system file, or one of the
// aliases "stdout", "stdin", or "stderr".
func (l *Logger) Append(file string, level Level) {
	if w, ok := FileAliases[file]; ok {
		l.Loggers.Append(newLogger(w), level)
	} else {
		w := l.open(file)
		if w != nil {
			l.Loggers.Append(newLogger(w), level)
			l.pointers = append(l.pointers, w)
		}
	}
}

// MultiAppend adds one or more files to the logger.
func (l *Logger) MultiAppend(files []string, level Level) {
	for _, file := range files {
		l.Append(file, level)
	}
}

// AppendWriter adds a writer that will be written to at the given level or greater.
func (l *Logger) AppendWriter(w io.Writer, level Level) {
	l.Loggers.Append(newLogger(w), level)
}

// MultiAppendWriter adds one or more io.Writer instances to the logger.
func (l *Logger) MultiAppendWriter(writers []io.Writer, level Level) {
	for _, writer := range writers {
		l.AppendWriter(writer, level)
	}
}

// Close disables logging and frees up resources used by the logger.
// Note this method only closes files opened by the logger. It's the user's
// responsibility to close files that were passed to the logger via the
// AppendWriter method.
func (l *Logger) Close() {
	if !l.closed {
		for _, pointer := range l.pointers {
			pointer.Close()
		}

		l.Enabled = false
		l.Loggers = nil
		l.pointers = nil
	}
}

// Writable returns true when logging is enabled, and the logger hasn't been closed.
func (l *Logger) Writable() bool {
	return l.Enabled && !l.closed
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Log(level Level, v ...interface{}) {
	if l.Writable() {
		message := l.Formatter.Format(level, v...)
		for _, logger := range l.Loggers.FindByLevel(level) {
			logger.Print(message)
		}

		if FatalOn&level > 0 {
			os.Exit(1)
		} else if PanicOn&level > 0 {
			panic(message)
		}
	}
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Logf(level Level, format string, v ...interface{}) {
	l.Log(level, fmt.Sprintf(format, v...))
}

// Debug prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Debug(v ...interface{}) {
	l.Log(Debug, v...)
}

// Debugf prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Debugf(format string, v ...interface{}) {
	l.Logf(Debug, format, v...)
}

// Info prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Info(v ...interface{}) {
	l.Log(Info, v...)
}

// Infof prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Infof(format string, v ...interface{}) {
	l.Logf(Info, format, v...)
}

// Notice prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Notice(v ...interface{}) {
	l.Log(Notice, v...)
}

// Noticef prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Noticef(format string, v ...interface{}) {
	l.Logf(Notice, format, v...)
}

// Warning prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Warning(v ...interface{}) {
	l.Log(Warning, v...)
}

// Warningf prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Warningf(format string, v ...interface{}) {
	l.Logf(Warning, format, v...)
}

// Error prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Error(v ...interface{}) {
	l.Log(Error, v...)
}

// Errorf prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Errorf(format string, v ...interface{}) {
	l.Logf(Error, format, v...)
}

// Critical prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Critical(v ...interface{}) {
	l.Log(Critical, v...)
}

// Criticalf prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Criticalf(format string, v ...interface{}) {
	l.Logf(Critical, format, v...)
}

// Alert prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Alert(v ...interface{}) {
	l.Log(Alert, v...)
}

// Alertf prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Alertf(format string, v ...interface{}) {
	l.Logf(Alert, format, v...)
}

// Emergency prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Emergency(v ...interface{}) {
	l.Log(Emergency, v...)
}

// Emergencyf prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Emergencyf(format string, v ...interface{}) {
	l.Logf(Emergency, format, v...)
}

// open returns a file that logs can be written to.
func (l *Logger) open(name string) *os.File {
	w, err := os.OpenFile(name, FileOpenFlags, FileOpenMode)
	if err != nil {
		if PanicOnFileErrors {
			panic(err)
		} else {
			w = nil
		}
	}

	return w
}

// newLogger returns a *log.Logger instance configured with the default options.
func newLogger(w io.Writer) *log.Logger {
	return log.New(w, "", 0)
}
<commit_msg>Renamed some vars<commit_after>package xlog

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

// Level describes a logging level.
type Level int

const (
	Debug Level = 1 << iota
	Info        = 1 << iota
	Notice      = 1 << iota
	Warning     = 1 << iota
	Error       = 1 << iota
	Critical    = 1 << iota
	Alert       = 1 << iota
	Emergency   = 1 << iota
)

// Levels maps Level to a string representation.
var Levels = map[Level]string{
	Debug: "DEBUG",
	Info: "INFO",
	Notice: "NOTICE",
	Warning: "WARNING",
	Error: "ERROR",
	Critical: "CRITICAL",
	Alert: "ALERT",
	Emergency: "EMERGENCY",
}

// FileAliases maps file aliases to real file pointers.
var FileAliases = map[string]*os.File{
	"stdout": os.Stdout,
	"stdin": os.Stdin,
	"stderr": os.Stderr,
}

var (
	// DefaultDateFormat is the date format to use when none has been specified.
	DefaultDateFormat = "2006-01-02 15:04:05.000"

	// DefaultMessageFormat is the message format to use when none has been specified.
	DefaultMessageFormat = "{date|2006-01-02 15:04:05.000} {name}.{level} {message}"

	// FileFlags defines the file open options.
	FileOpenFlags int = os.O_RDWR|os.O_CREATE|os.O_APPEND

	// FileMode defines the mode files are opened in.
	FileOpenMode os.FileMode = 0666

	// PanicOnFileErrors defines whether the logger should panic when opening a file
	// fails. When set to false, any file open errors are ignored, and the file won't be
	// appended.
	PanicOnFileErrors = true

	// InitialLoggerCapacity defines the initial capacity for each type of logger.
	InitialLoggerCapacity = 4

	// FatalOn represents levels that causes the application to exit.
	FatalOn Level = 0

	// PanicOn represents levels that causes the application to panic.
	PanicOn Level = 0
)

// Loggable is an interface that provides methods for logging messages to
// various levels.
type Loggable interface {
	Log(level Level, v ...interface{})
	Logf(level Level, format string, v ...interface{})
	Debug(v ...interface{})
	Debugf(format string, v ...interface{})
	Info(v ...interface{})
	Infof(format string, v ...interface{})
	Warning(v ...interface{})
	Warningf(format string, v ...interface{})
	Error(v ...interface{})
	Errorf(format string, v ...interface{})
	Critical(v ...interface{})
	Criticalf(format string, v ...interface{})
	Alert(v ...interface{})
	Alertf(format string, v ...interface{})
	Emergency(v ...interface{})
	Emergencyf(format string, v ...interface{})
}

// Logger is a light weight logger designed to write to multiple files at different
// log levels.
type Logger struct {
	// Enabled defines whether logging is enabled.
	Enabled  bool

	// Formatter is used to format the log messages.
	Formatter Formatter

	// Loggers holds the appended file loggers.
	Loggers LoggerMap

	// pointers contains any files that have been opened for logging.
	pointers []*os.File

	// closed defines whether the logger has been closed.
	closed bool
}

// NewLogger returns a *Logger instance that's been initialized with default values.
func NewLogger(name string) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: NewDefaultFormatter(DefaultMessageFormat, name),
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// NewMultiLogger returns a *Logger instance that's been initialized with one or
// more files at the given level.
func NewMultiLogger(name string, files []string, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppend(files, level);
	return logger;
}

// NewMultiWriterLogger returns a *Logger instance that's been initialized with one or
// more writers at the given level.
func NewMultiWriterLogger(name string, writers []io.Writer, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppendWriter(writers, level);
	return logger;
}

// NewFormattedLogger returns a *Logger instance using the provided formatter.
func NewFormattedLogger(formatter Formatter) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: formatter,
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// Append adds a file that will be written to at the given level or greater.
// The file argument may be either the full path to a system file, or one of the
// aliases "stdout", "stdin", or "stderr".
func (l *Logger) Append(file string, level Level) {
	if w, ok := FileAliases[file]; ok {
		l.Loggers.Append(newLogger(w), level)
	} else {
		w := l.open(file)
		if w != nil {
			l.Loggers.Append(newLogger(w), level)
			l.pointers = append(l.pointers, w)
		}
	}
}

// MultiAppend adds one or more files to the logger.
func (l *Logger) MultiAppend(files []string, level Level) {
	for _, file := range files {
		l.Append(file, level)
	}
}

// AppendWriter adds a writer that will be written to at the given level or greater.
func (l *Logger) AppendWriter(w io.Writer, level Level) {
	l.Loggers.Append(newLogger(w), level)
}

// MultiAppendWriter adds one or more io.Writer instances to the logger.
func (l *Logger) MultiAppendWriter(writers []io.Writer, level Level) {
	for _, writer := range writers {
		l.AppendWriter(writer, level)
	}
}

// Close disables logging and frees up resources used by the logger.
// Note this method only closes files opened by the logger. It's the user's
// responsibility to close files that were passed to the logger via the
// AppendWriter method.
func (l *Logger) Close() {
	if !l.closed {
		for _, pointer := range l.pointers {
			pointer.Close()
		}

		l.Enabled = false
		l.Loggers = nil
		l.pointers = nil
	}
}

// Writable returns true when logging is enabled, and the logger hasn't been closed.
func (l *Logger) Writable() bool {
	return l.Enabled && !l.closed
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Log(level Level, v ...interface{}) {
	if l.Writable() {
		message := l.Formatter.Format(level, v...)
		for _, logger := range l.Loggers.FindByLevel(level) {
			logger.Print(message)
		}

		if FatalOn&level > 0 {
			os.Exit(1)
		} else if PanicOn&level > 0 {
			panic(message)
		}
	}
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Logf(level Level, format string, v ...interface{}) {
	l.Log(level, fmt.Sprintf(format, v...))
}

// Debug prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Debug(v ...interface{}) {
	l.Log(Debug, v...)
}

// Debugf prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Debugf(format string, v ...interface{}) {
	l.Logf(Debug, format, v...)
}

// Info prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Info(v ...interface{}) {
	l.Log(Info, v...)
}

// Infof prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Infof(format string, v ...interface{}) {
	l.Logf(Info, format, v...)
}

// Notice prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Notice(v ...interface{}) {
	l.Log(Notice, v...)
}

// Noticef prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Noticef(format string, v ...interface{}) {
	l.Logf(Notice, format, v...)
}

// Warning prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Warning(v ...interface{}) {
	l.Log(Warning, v...)
}

// Warningf prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Warningf(format string, v ...interface{}) {
	l.Logf(Warning, format, v...)
}

// Error prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Error(v ...interface{}) {
	l.Log(Error, v...)
}

// Errorf prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Errorf(format string, v ...interface{}) {
	l.Logf(Error, format, v...)
}

// Critical prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Critical(v ...interface{}) {
	l.Log(Critical, v...)
}

// Criticalf prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Criticalf(format string, v ...interface{}) {
	l.Logf(Critical, format, v...)
}

// Alert prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Alert(v ...interface{}) {
	l.Log(Alert, v...)
}

// Alertf prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Alertf(format string, v ...interface{}) {
	l.Logf(Alert, format, v...)
}

// Emergency prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Emergency(v ...interface{}) {
	l.Log(Emergency, v...)
}

// Emergencyf prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Emergencyf(format string, v ...interface{}) {
	l.Logf(Emergency, format, v...)
}

// open returns a file that logs can be written to.
func (l *Logger) open(name string) *os.File {
	w, err := os.OpenFile(name, FileOpenFlags, FileOpenMode)
	if err != nil {
		if PanicOnFileErrors {
			panic(err)
		} else {
			w = nil
		}
	}

	return w
}

// newLogger returns a *log.Logger instance configured with the default options.
func newLogger(w io.Writer) *log.Logger {
	return log.New(w, "", 0)
}
<|endoftext|>