<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/fatih/structs"
	"github.com/gorilla/mux"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"html/template"
	"net/http"
	"os"
	"regexp"
	"strconv"
)

var mdb *mgo.Session

func main() {
	var err error
	mdb, err = mgo.Dial("localhost")

	if err != nil {
		fmt.Println("Could not connect ot MongoDB: ", err)
		os.Exit(1)
	}
	defer mdb.Close()

	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/search", SearchHandler)
	r.HandleFunc("/listbreaches", ListBreaches)

	http.Handle("/", r)
	http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("templates/images"))))
	http.ListenAndServe(":8080", nil)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("templates/index.html")
	if err != nil {
		fmt.Printf("error template")
	}
	t.Execute(w, nil)
}

type BreachEntry struct {
	Id           bson.ObjectId `json:"id" bson:"_id,omitempty"`
	MemberID     int           `bson:"memberid"`
	Email        string        `bson:"email"`
	PasswordHash string        `bson:"passwordhash"`
	Password     string        `bson:"password"`
	Breach       string        `bson:"breach"`
	Hint         string        `bson:"hint"`
}

func SearchHandler(w http.ResponseWriter, r *http.Request) {
	// Get the searched for string
	searchterm := r.URL.Query().Get("search")
	if searchterm == "" {
		http.Error(w, "Error detecting search", http.StatusInternalServerError)
		return
	}

	breachfilter := r.URL.Query().Get("breach")
	if breachfilter == "" {
		breachfilter = "all"
	}

	// Begin a search
	mysess := mdb.Copy()
	c := mysess.DB("steamer").C("dumps")

	results := []BreachEntry{}

	var query *mgo.Query
	// TODO Remove unnessecary duplicated code here
	if breachfilter == "all" {
		query = c.Find(bson.M{"$or": []interface{}{
			bson.M{"email": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(searchterm)), ""}},
			bson.M{"passwordhash": searchterm},
			bson.M{"liame": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(Reverse(searchterm))), ""}},
		}})
	} else {
		query = c.Find(bson.M{"$and": []interface{}{
			bson.M{"breach": breachfilter},
			bson.M{"$or": []interface{}{
				bson.M{"email": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(searchterm)), ""}},
				bson.M{"passwordhash": searchterm},
				bson.M{"liame": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(Reverse(searchterm))), ""}},
			}},
		}})
	}

	// Sort if required
	sort := r.URL.Query().Get("sort")
	if sort == "" {
		sort = "all"
	}

	if sort != "all" {
		query = query.Sort(sort)
	}

	// Get the page number
	spage := r.URL.Query().Get("page")
	// Display the first page if page is not set
	if spage == "" {
		spage = "1"
	}
	page, err := strconv.Atoi(spage)
	if err != nil {
		http.Error(w, "Error parsing limit", http.StatusInternalServerError)
		return
	}

	// Limit if required
	slimit := r.URL.Query().Get("limit")

	if slimit == "" {
		slimit = "10"
	}
	limit, err := strconv.Atoi(slimit)
	if err != nil {
		http.Error(w, "Error parsing limit", http.StatusInternalServerError)
		return
	}

	// hard limit to prevent server dying (golang will probably barf on 10k as it is since it's not iterated properly)
	if (limit > 10000) || (limit < 1) {
		limit = 10000
	}

	// Calculate limit and numner of entries to skip from page number
	skipNum := (page - 1) * limit
	// TODO: Check if skipNum will overflow
	// Check if we need to limit
	err = query.Skip(skipNum).Limit(limit).All(&results)

	if err != nil {
		fmt.Fprintf(w, "error searching %v", err)
		return
	}

	// Output based on format
	format := r.URL.Query().Get("format")
	if format == "" {
		format = "web"
	}

	if format == "json" {
		json, err := json.Marshal(results)
		if err != nil {
			fmt.Fprintf(os.Stderr, "json encoding error: %v", err)
			http.Error(w, "Error json encoding", http.StatusInternalServerError)
			return
		}

		// replace with a bytes write rather than a string conversion
		fmt.Fprintf(w, string(json))
	} else {
		// Render the standard template with results directory
		t, err := template.ParseFiles("templates/index.html")
		if err != nil {
			fmt.Printf("error template")
		}
		// Pass in a slice map, not a map of structs
		var m []map[string]interface{}
		for _, res := range results {
			m = append(m, structs.Map(res))
		}
		templateData := struct {
			Results []map[string]interface{}
			Search  string
			Breach  string
			Sort    string
			PageNum string
			Limit string
		}{
			m,
			searchterm,
			breachfilter,
			sort,
			spage,
			slimit,
		}
		t.Execute(w, templateData)
	}
}

// Return a JSON response of all the breaches in the database
func ListBreaches(w http.ResponseWriter, r *http.Request) {
	// db.dumps.distinct("breaches")
	mysess := mdb.Copy()
	c := mysess.DB("steamer").C("dumps")

	var results []string
	err := c.Find(nil).Distinct("breach", &results)
	if err != nil {
		fmt.Fprintf(os.Stderr, "breach search error: %v", err)
		http.Error(w, "Error searching breaches", http.StatusInternalServerError)
		return
	}

	json, err := json.Marshal(results)
	if err != nil {
		fmt.Fprintf(os.Stderr, "json encoding error: %v", err)
		http.Error(w, "Error json encoding", http.StatusInternalServerError)
		return
	}

	// replace with a bytes write rather than a string conversion
	fmt.Fprintf(w, string(json))
}

func Reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}
<commit_msg>formatted with gofmt<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/fatih/structs"
	"github.com/gorilla/mux"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"html/template"
	"net/http"
	"os"
	"regexp"
	"strconv"
)

var mdb *mgo.Session

func main() {
	var err error
	mdb, err = mgo.Dial("localhost")

	if err != nil {
		fmt.Println("Could not connect ot MongoDB: ", err)
		os.Exit(1)
	}
	defer mdb.Close()

	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	r.HandleFunc("/search", SearchHandler)
	r.HandleFunc("/listbreaches", ListBreaches)

	http.Handle("/", r)
	http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("templates/images"))))
	http.ListenAndServe(":8080", nil)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("templates/index.html")
	if err != nil {
		fmt.Printf("error template")
	}
	t.Execute(w, nil)
}

type BreachEntry struct {
	Id           bson.ObjectId `json:"id" bson:"_id,omitempty"`
	MemberID     int           `bson:"memberid"`
	Email        string        `bson:"email"`
	PasswordHash string        `bson:"passwordhash"`
	Password     string        `bson:"password"`
	Breach       string        `bson:"breach"`
	Hint         string        `bson:"hint"`
}

func SearchHandler(w http.ResponseWriter, r *http.Request) {
	// Get the searched for string
	searchterm := r.URL.Query().Get("search")
	if searchterm == "" {
		http.Error(w, "Error detecting search", http.StatusInternalServerError)
		return
	}

	breachfilter := r.URL.Query().Get("breach")
	if breachfilter == "" {
		breachfilter = "all"
	}

	// Begin a search
	mysess := mdb.Copy()
	c := mysess.DB("steamer").C("dumps")

	results := []BreachEntry{}

	var query *mgo.Query
	// TODO Remove unnessecary duplicated code here
	if breachfilter == "all" {
		query = c.Find(bson.M{"$or": []interface{}{
			bson.M{"email": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(searchterm)), ""}},
			bson.M{"passwordhash": searchterm},
			bson.M{"liame": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(Reverse(searchterm))), ""}},
		}})
	} else {
		query = c.Find(bson.M{"$and": []interface{}{
			bson.M{"breach": breachfilter},
			bson.M{"$or": []interface{}{
				bson.M{"email": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(searchterm)), ""}},
				bson.M{"passwordhash": searchterm},
				bson.M{"liame": bson.RegEx{fmt.Sprintf("^%v.*", regexp.QuoteMeta(Reverse(searchterm))), ""}},
			}},
		}})
	}

	// Sort if required
	sort := r.URL.Query().Get("sort")
	if sort == "" {
		sort = "all"
	}

	if sort != "all" {
		query = query.Sort(sort)
	}

	// Get the page number
	spage := r.URL.Query().Get("page")
	// Display the first page if page is not set
	if spage == "" {
		spage = "1"
	}
	page, err := strconv.Atoi(spage)
	if err != nil {
		http.Error(w, "Error parsing limit", http.StatusInternalServerError)
		return
	}

	// Limit if required
	slimit := r.URL.Query().Get("limit")

	if slimit == "" {
		slimit = "10"
	}
	limit, err := strconv.Atoi(slimit)
	if err != nil {
		http.Error(w, "Error parsing limit", http.StatusInternalServerError)
		return
	}

	// hard limit to prevent server dying (golang will probably barf on 10k as it is since it's not iterated properly)
	if (limit > 10000) || (limit < 1) {
		limit = 10000
	}

	// Calculate limit and numner of entries to skip from page number
	skipNum := (page - 1) * limit
	// TODO: Check if skipNum will overflow
	// Check if we need to limit
	err = query.Skip(skipNum).Limit(limit).All(&results)

	if err != nil {
		fmt.Fprintf(w, "error searching %v", err)
		return
	}

	// Output based on format
	format := r.URL.Query().Get("format")
	if format == "" {
		format = "web"
	}

	if format == "json" {
		json, err := json.Marshal(results)
		if err != nil {
			fmt.Fprintf(os.Stderr, "json encoding error: %v", err)
			http.Error(w, "Error json encoding", http.StatusInternalServerError)
			return
		}

		// replace with a bytes write rather than a string conversion
		fmt.Fprintf(w, string(json))
	} else {
		// Render the standard template with results directory
		t, err := template.ParseFiles("templates/index.html")
		if err != nil {
			fmt.Printf("error template")
		}
		// Pass in a slice map, not a map of structs
		var m []map[string]interface{}
		for _, res := range results {
			m = append(m, structs.Map(res))
		}
		templateData := struct {
			Results []map[string]interface{}
			Search  string
			Breach  string
			Sort    string
			PageNum string
			Limit   string
		}{
			m,
			searchterm,
			breachfilter,
			sort,
			spage,
			slimit,
		}
		t.Execute(w, templateData)
	}
}

// Return a JSON response of all the breaches in the database
func ListBreaches(w http.ResponseWriter, r *http.Request) {
	// db.dumps.distinct("breaches")
	mysess := mdb.Copy()
	c := mysess.DB("steamer").C("dumps")

	var results []string
	err := c.Find(nil).Distinct("breach", &results)
	if err != nil {
		fmt.Fprintf(os.Stderr, "breach search error: %v", err)
		http.Error(w, "Error searching breaches", http.StatusInternalServerError)
		return
	}

	json, err := json.Marshal(results)
	if err != nil {
		fmt.Fprintf(os.Stderr, "json encoding error: %v", err)
		http.Error(w, "Error json encoding", http.StatusInternalServerError)
		return
	}

	// replace with a bytes write rather than a string conversion
	fmt.Fprintf(w, string(json))
}

func Reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}
<|endoftext|>


<commit_before>package pages

import (
	"database/sql"
	"net/http"
	"net/mail"
	"time"

	"github.com/gorilla/sessions"
	"github.com/upframe/fest/email"
	"github.com/upframe/fest/models"
)

// DeactivateGET creates a new deactivation link
func DeactivateGET(w http.ResponseWriter, r *http.Request, s *sessions.Session) (int, error) {
	// Checks if the hash is indicated in the URL
	if r.URL.Query().Get("deactivate") == "" {
		return Redirect(w, r, "/settings")
	}

	// Fetches the link from the database
	link, err := models.GetLinkByHash(r.URL.Query().Get("confirm"))

	// If the error is no rows, or the link is used, or it's expired or the path
	// is incorrect, show a 404 Not Found page.
	if err == sql.ErrNoRows || link.Used || link.Expires.Unix() < time.Now().Unix() || link.Path != "/settings/deactivate" {
		return http.StatusNotFound, nil
	}

	// If there is any other error, return a 500
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Gets the users and checks for error
	g, err := models.GetUserByID(link.User)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Deactivates the user and checks for error
	user := g.(*models.User)
	err = user.Deactivate()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Marks the link as used and checks the errors
	link.Used = true
	err = link.Update("used")
	if err != nil {
		return http.StatusInternalServerError, err
	}

	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	return http.StatusOK, nil
}

// DeactivatePOST creates the deactivation email and sends it to the user
func DeactivatePOST(w http.ResponseWriter, r *http.Request, s *sessions.Session) (int, error) {
	if !IsLoggedIn(s) {
		return http.StatusBadRequest, errNotLoggedIn
	}

	// Sets the current time and expiration time of the deactivation email
	now := time.Now()
	expires := time.Now().Add(time.Hour * 2)

	link := &models.Link{
		Path:    "/register",
		Hash:    models.UniqueHash(s.Values["Email"].(string)),
		User:    s.Values["UserID"].(int),
		Used:    false,
		Time:    &now,
		Expires: &expires,
	}

	err := link.Insert()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	data := make(map[string]interface{})
	data["Name"] = s.Values["FirstName"].(string) + " " + s.Values["LastName"].(string)
	data["Hash"] = link.Hash
	data["Host"] = BaseAddress

	email := &email.Email{
		From: &mail.Address{
			Name:    "Upframe",
			Address: email.FromDefaultEmail,
		},
		To: &mail.Address{
			Name:    data["Name"].(string),
			Address: s.Values["Email"].(string),
		},
		Subject: "Deactivate your account",
	}

	err = email.UseTemplate("deactivation", data)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = email.Send()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}
<commit_msg>update<commit_after>package pages

import (
	"database/sql"
	"net/http"
	"net/mail"
	"time"

	"github.com/gorilla/sessions"
	"github.com/upframe/fest/email"
	"github.com/upframe/fest/models"
)

// DeactivateGET creates a new deactivation link
func DeactivateGET(w http.ResponseWriter, r *http.Request, s *sessions.Session) (int, error) {
	// Checks if the hash is indicated in the URL
	if r.URL.Query().Get("deactivate") == "" {
		return http.StatusNotFound, nil
	}

	// Fetches the link from the database
	link, err := models.GetLinkByHash(r.URL.Query().Get("confirm"))

	// If the error is no rows, or the link is used, or it's expired or the path
	// is incorrect, show a 404 Not Found page.
	if err == sql.ErrNoRows || link.Used || link.Expires.Unix() < time.Now().Unix() || link.Path != "/settings/deactivate" {
		return http.StatusNotFound, nil
	}

	// If there is any other error, return a 500
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Gets the users and checks for error
	g, err := models.GetUserByID(link.User)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Deactivates the user and checks for error
	user := g.(*models.User)
	err = user.Deactivate()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	// Marks the link as used and checks the errors
	link.Used = true
	err = link.Update("used")
	if err != nil {
		return http.StatusInternalServerError, err
	}

	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	return http.StatusOK, nil
}

// DeactivatePOST creates the deactivation email and sends it to the user
func DeactivatePOST(w http.ResponseWriter, r *http.Request, s *sessions.Session) (int, error) {
	if !IsLoggedIn(s) {
		return http.StatusBadRequest, errNotLoggedIn
	}

	// Sets the current time and expiration time of the deactivation email
	now := time.Now()
	expires := time.Now().Add(time.Hour * 2)

	link := &models.Link{
		Path:    "/register",
		Hash:    models.UniqueHash(s.Values["Email"].(string)),
		User:    s.Values["UserID"].(int),
		Used:    false,
		Time:    &now,
		Expires: &expires,
	}

	err := link.Insert()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	data := make(map[string]interface{})
	data["Name"] = s.Values["FirstName"].(string) + " " + s.Values["LastName"].(string)
	data["Hash"] = link.Hash
	data["Host"] = BaseAddress

	email := &email.Email{
		From: &mail.Address{
			Name:    "Upframe",
			Address: email.FromDefaultEmail,
		},
		To: &mail.Address{
			Name:    data["Name"].(string),
			Address: s.Values["Email"].(string),
		},
		Subject: "Deactivate your account",
	}

	err = email.UseTemplate("deactivation", data)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = email.Send()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}
<|endoftext|>


<commit_before>package boardgame

import (
	"time"
)

//StateStorageRecord is a record representing a state that can be written to
//storage and later returned. It is an opaque blob, so in most cases storage
//managers can just write straight to disk with no transformations.
type StateStorageRecord []byte

//MoveStorageRecord is a record representing the Move that was made to get the
//game to its most recent version.
type MoveStorageRecord struct {
	Name      string
	Version   int
	Initiator int
	//The Phase as returned by Delegate.CurrentPhase() for the state the move
	//was in before it was applied.
	Phase     int
	Timestamp time.Time
	Blob      []byte
}

//GameStorageRecord is a simple struct with public fields representing the
//important aspects of a game that should be serialized to storage. The fields
//are broken out specifically so that the storage layer can understand these
//properties in queries.
type GameStorageRecord struct {
	//Name is the type of the game, from its manager. Used for sanity
	//checking.
	Name string
	Id   string
	//SecretSalt for this game for things like component Ids. Should never be
	//transmitted to an insecure or untrusted environment; the only way to
	//access it outside this package is via this field, because it must be
	//able to be persisted to and read from storage.
	SecretSalt string `json:",omitempty"`
	Version    int
	Winners    []PlayerIndex
	Finished   bool
	Created    time.Time
	//NumPlayers is the reported number of players when it was created.
	//Primarily for convenience to storage layer so they know how many players
	//are in the game.
	NumPlayers int
	Agents     []string
}

//StorageManager is an interface that anything can implement to handle the
//persistence of Games and States.
type StorageManager interface {
	//State returns the StateWrapper for the game at the given version, or
	//nil.
	State(gameId string, version int) (StateStorageRecord, error)

	//Move returns the MoveStorageRecord for the game at the given version, or
	//nil.
	Move(gameId string, version int) (*MoveStorageRecord, error)

	//Moves is like Move but returns all moves from fromVersion (exclusive) to
	//toVersion (inclusive). If fromVersion == toVersion, should return
	//toVersion. In many storage subsystems this is cheaper than repeated
	//calls to Move.
	Moves(gameId string, fromVersion, toVersion int) ([]*MoveStorageRecord, error)

	//Game fetches the game with the given ID from the store, if it exists.
	Game(id string) (*GameStorageRecord, error)

	//AgentState retrieves the most recent state for the given agent
	AgentState(gameId string, player PlayerIndex) ([]byte, error)

	//SaveGameAndCurrentState stores the game and the current state (at
	//game.Version()) into the store at the same time in a transaction. If
	//Game.Modifiable() is false, storage should fail. Move can be nil (if game.Version() is 0)
	SaveGameAndCurrentState(game *GameStorageRecord, state StateStorageRecord, move *MoveStorageRecord) error

	//SaveAgentState saves the agent state for the given player
	SaveAgentState(gameId string, player PlayerIndex, state []byte) error

	//PlayerMoveApplied is called after a PlayerMove and all of its resulting
	//FixUp moves have been applied. Most StorageManagers don't need to do
	//anything here; it's primarily useful for signaling that a run of moves
	//has been applied, e.g. in the server.
	PlayerMoveApplied(game *GameStorageRecord) error
}
<commit_msg>MoveStorageRecord has a String() method that outputs something a bit more useful for debugging.<commit_after>package boardgame

import (
	"strconv"
	"time"
)

//StateStorageRecord is a record representing a state that can be written to
//storage and later returned. It is an opaque blob, so in most cases storage
//managers can just write straight to disk with no transformations.
type StateStorageRecord []byte

//MoveStorageRecord is a record representing the Move that was made to get the
//game to its most recent version.
type MoveStorageRecord struct {
	Name      string
	Version   int
	Initiator int
	//The Phase as returned by Delegate.CurrentPhase() for the state the move
	//was in before it was applied.
	Phase     int
	Timestamp time.Time
	Blob      []byte
}

func (m *MoveStorageRecord) String() string {
	return m.Name + ": " + strconv.Itoa(m.Version)
}

//GameStorageRecord is a simple struct with public fields representing the
//important aspects of a game that should be serialized to storage. The fields
//are broken out specifically so that the storage layer can understand these
//properties in queries.
type GameStorageRecord struct {
	//Name is the type of the game, from its manager. Used for sanity
	//checking.
	Name string
	Id   string
	//SecretSalt for this game for things like component Ids. Should never be
	//transmitted to an insecure or untrusted environment; the only way to
	//access it outside this package is via this field, because it must be
	//able to be persisted to and read from storage.
	SecretSalt string `json:",omitempty"`
	Version    int
	Winners    []PlayerIndex
	Finished   bool
	Created    time.Time
	//NumPlayers is the reported number of players when it was created.
	//Primarily for convenience to storage layer so they know how many players
	//are in the game.
	NumPlayers int
	Agents     []string
}

//StorageManager is an interface that anything can implement to handle the
//persistence of Games and States.
type StorageManager interface {
	//State returns the StateWrapper for the game at the given version, or
	//nil.
	State(gameId string, version int) (StateStorageRecord, error)

	//Move returns the MoveStorageRecord for the game at the given version, or
	//nil.
	Move(gameId string, version int) (*MoveStorageRecord, error)

	//Moves is like Move but returns all moves from fromVersion (exclusive) to
	//toVersion (inclusive). If fromVersion == toVersion, should return
	//toVersion. In many storage subsystems this is cheaper than repeated
	//calls to Move.
	Moves(gameId string, fromVersion, toVersion int) ([]*MoveStorageRecord, error)

	//Game fetches the game with the given ID from the store, if it exists.
	Game(id string) (*GameStorageRecord, error)

	//AgentState retrieves the most recent state for the given agent
	AgentState(gameId string, player PlayerIndex) ([]byte, error)

	//SaveGameAndCurrentState stores the game and the current state (at
	//game.Version()) into the store at the same time in a transaction. If
	//Game.Modifiable() is false, storage should fail. Move can be nil (if game.Version() is 0)
	SaveGameAndCurrentState(game *GameStorageRecord, state StateStorageRecord, move *MoveStorageRecord) error

	//SaveAgentState saves the agent state for the given player
	SaveAgentState(gameId string, player PlayerIndex, state []byte) error

	//PlayerMoveApplied is called after a PlayerMove and all of its resulting
	//FixUp moves have been applied. Most StorageManagers don't need to do
	//anything here; it's primarily useful for signaling that a run of moves
	//has been applied, e.g. in the server.
	PlayerMoveApplied(game *GameStorageRecord) error
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"net/http"
	"sort"
	"sync"

	"github.com/google/go-github/github"
)

type Storage struct {
	files map[string]string
	mu    *sync.RWMutex

	token *Token
}

func NewStorage() *Storage {
	s := &Storage{
		files: make(map[string]string),
		token: &Token{},
		mu:    &sync.RWMutex{},
	}
	return s
}

func (s *Storage) AddFiles(paths []string) {
	s.mu.Lock()
	defer s.mu.Unlock()

	if !s.token.hasToken() {
		for _, path := range paths {
			s.files[path] = ""
		}
		return
	}

	for _, path := range paths {
		md, err := ioutil.ReadFile(path)
		if err != nil {
			s.files[path] = err.Error()
			continue
		}

		html, err := s.md2html(string(md))
		if err != nil {
			s.files[path] = html
			continue
		}
		html = s.insertCSS(html)
		s.files[path] = html
	}
}
func (s *Storage) UpdateAll() {
	s.AddFiles(s.Index())
}

func (s *Storage) Get(path string) (string, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	html, ok := s.files[path]
	if ok {
		return html, ok
	} else {
		html, ok := s.files["/"+path]
		return html, ok
	}
}

func (s *Storage) Index() []string {
	s.mu.RLock()
	defer s.mu.RUnlock()

	res := make([]string, 0, len(s.files))

	for path := range s.files {
		res = append(res, path)
	}

	sort.Strings(res)
	return res
}

func (s *Storage) md2html(md string) (string, error) {
	client := github.NewClient(&http.Client{
		Transport: s.token,
	})
	html, _, err := client.Markdown(md, nil)
	return html, err
}

func (_ *Storage) insertCSS(html string) string {
	tags := `<!DOCTYPE html>
<link rel="stylesheet" href="/css/github-markdown.css">

`
	tagEnd := `

`
	return tags + html + tagEnd
}
<commit_msg>WIP storage<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"sync"

	"github.com/google/go-github/github"
)

type Storage struct {
	files map[string]string
	mu    *sync.RWMutex

	token   *Token
	watcher *Watcher
}

func NewStorage() *Storage {
	w, err := NewWatcher()
	if err != nil {
		panic(err)
	}

	s := &Storage{
		files:   make(map[string]string),
		token:   &Token{},
		mu:      &sync.RWMutex{},
		watcher: w,
	}

	go func() {
		ch := w.OnUpdate()
		for {
			fname := <-ch
			fmt.Println(fname)
		}
	}()

	return s
}

func (s *Storage) AddFiles(paths []string) {
	s.mu.Lock()
	defer s.mu.Unlock()

	if !s.token.hasToken() {
		for _, path := range paths {
			s.files[path] = ""
		}
		return
	}

	err := s.watcher.AddFiles(paths)
	if err != nil {
		panic(err)
	}

	for _, path := range paths {
		s.AddFile(path)
	}
}

// without mutex
func (s *Storage) AddFile(path string) error {
	md, err := ioutil.ReadFile(path)
	if err != nil {
		s.files[path] = err.Error()
		return err
	}

	html, err := s.md2html(string(md))
	if err != nil {
		s.files[path] = html
		return err
	}
	html = s.insertCSS(html)
	s.files[path] = html
	return nil
}

func (s *Storage) UpdateAll() {
	s.AddFiles(s.Index())
}

func (s *Storage) Get(path string) (string, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	html, ok := s.files[path]
	if ok {
		return html, ok
	} else {
		html, ok := s.files["/"+path]
		return html, ok
	}
}

func (s *Storage) Index() []string {
	s.mu.RLock()
	defer s.mu.RUnlock()

	res := make([]string, 0, len(s.files))

	for path := range s.files {
		res = append(res, path)
	}

	sort.Strings(res)
	return res
}

func (s *Storage) md2html(md string) (string, error) {
	client := github.NewClient(&http.Client{
		Transport: s.token,
	})
	html, _, err := client.Markdown(md, nil)
	return html, err
}

func (_ *Storage) insertCSS(html string) string {
	tags := `<!DOCTYPE html>
<link rel="stylesheet" href="/css/github-markdown.css">

`
	tagEnd := `

`
	return tags + html + tagEnd
}
<|endoftext|>


<commit_before>// Package log provides a log interface
package log

// Logger is a generic logging interface
type Logger interface {
	Log(v ...interface{})
	Logf(format string, v ...interface{})
}

var (
	// The global default logger
	DefaultLogger Logger = &noOpLogger{}
)

// noOpLogger is used as a placeholder for the default logger
type noOpLogger struct{}

func (n *noOpLogger) Log(v ...interface{}) {}

func (n *noOpLogger) Logf(format string, v ...interface{}) {}
<commit_msg>add top level funcs to use default logger<commit_after>// Package log provides a log interface
package log

// Logger is a generic logging interface
type Logger interface {
	Log(v ...interface{})
	Logf(format string, v ...interface{})
}

var (
	// The global default logger
	DefaultLogger Logger = &noOpLogger{}
)

// noOpLogger is used as a placeholder for the default logger
type noOpLogger struct{}

func (n *noOpLogger) Log(v ...interface{}) {}

func (n *noOpLogger) Logf(format string, v ...interface{}) {}

// Log logs using the default logger
func Log(v ...interface{}) {
	DefaultLogger.Log(v...)
}

// Logf logs formatted using the default logger
func Logf(format string, v ...interface{}) {
	DefaultLogger.Logf(format, v...)
}
<|endoftext|>


<commit_before>package venom

import (
	"fmt"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

type logConfig struct {
	LogLevel     string `mapstructure:"log-level"`
	LogFormatter string `mapstructure:"log-format"`
}

func initLogFlags(flags *pflag.FlagSet) error {
	var errors []string
	flags.VisitAll(func(f *pflag.Flag) {
		if f.Name == "log-level" || f.Name == "log-format" {
			errors = append(errors, fmt.Sprintf("Flag %s already defined!", f.Name))
		}
	})
	if len(errors) > 0 {
		return fmt.Errorf("%d errors:\n%s", len(errors), strings.Join(errors, "\n"))
	}

	var levels []string
	for _, l := range logrus.AllLevels {
		levels = append(levels, l.String())
	}
	flags.StringP("log-level", "", "info", fmt.Sprintf("Log level [%s]", strings.Join(levels, "|")))

	formats := []string{
		"json",
		"text",
	}
	flags.StringP("log-format", "", "text", fmt.Sprintf("Log format [%s]", strings.Join(formats, "|")))
	return nil
}

func readLog(viperMaybe ...*viper.Viper) error {
	v := viper.GetViper()
	if len(viperMaybe) != 0 {
		v = viperMaybe[0]
	}

	var cfg logConfig
	err := v.Unmarshal(&cfg)
	if err != nil {
		return err
	}

	l, err := logrus.ParseLevel(cfg.LogLevel)
	if err != nil {
		return err
	}

	switch cfg.LogFormatter {
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	default:
		return fmt.Errorf("Invalid log format: %s", cfg.LogFormatter)
	}

	logrus.SetLevel(l)
	return nil
}
<commit_msg>Add LogFormats & LogLevels<commit_after>package venom

import (
	"fmt"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	LogLevels  = []string{}
	LogFormats = []string{"text", "json"}
)

func init() {
	for _, l := range logrus.AllLevels {
		LogLevels = append(LogLevels, l.String())
	}
}

type logConfig struct {
	LogLevel     string `mapstructure:"log-level"`
	LogFormatter string `mapstructure:"log-format"`
}

func initLogFlags(flags *pflag.FlagSet) error {
	var errors []string
	flags.VisitAll(func(f *pflag.Flag) {
		if f.Name == "log-level" || f.Name == "log-format" {
			errors = append(errors, fmt.Sprintf("Flag %s already defined!", f.Name))
		}
	})
	if len(errors) > 0 {
		return fmt.Errorf("%d errors:\n%s", len(errors), strings.Join(errors, "\n"))
	}

	flags.StringP("log-level", "", "info", fmt.Sprintf("Log level [%s]", strings.Join(LogLevels, "|")))
	flags.StringP("log-format", "", "text", fmt.Sprintf("Log format [%s]", strings.Join(LogFormats, "|")))
	return nil
}

func readLog(viperMaybe ...*viper.Viper) error {
	v := viper.GetViper()
	if len(viperMaybe) != 0 {
		v = viperMaybe[0]
	}

	var cfg logConfig
	err := v.Unmarshal(&cfg)
	if err != nil {
		return err
	}

	l, err := logrus.ParseLevel(cfg.LogLevel)
	if err != nil {
		return err
	}

	switch cfg.LogFormatter {
	case "json":
		logrus.SetFormatter(&logrus.JSONFormatter{})
	case "text":
		logrus.SetFormatter(&logrus.TextFormatter{})
	default:
		return fmt.Errorf("Invalid log format: %s", cfg.LogFormatter)
	}

	logrus.SetLevel(l)
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 realglobe, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 main

import (
	"github.com/realglobe-Inc/go-lib/rglog"
)

var log = rglog.Logger("github.com/realglobe-Inc/edo-id-provider")

const mosaicThres = 10

// ログにそのまま書くのが憚られるので隠す。
func mosaic(str string) string {
	if len(str) <= mosaicThres {
		return str
	} else {
		return str[:mosaicThres] + "..."
	}
}
<commit_msg>隠し情報のログ表示文字数を変更<commit_after>// Copyright 2015 realglobe, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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 main

import (
	"github.com/realglobe-Inc/go-lib/rglog"
)

var log = rglog.Logger("github.com/realglobe-Inc/edo-id-provider")

const mosaicThres = 8

// ログにそのまま書くのが憚られるので隠す。
func mosaic(str string) string {
	if len(str) <= mosaicThres {
		return str
	} else {
		return str[:mosaicThres] + "..."
	}
}
<|endoftext|>


<commit_before>package lru

import (
	"container/list"
	"encoding/base64"
	"fmt"
	"hash/fnv"
	"io/ioutil"
	"os"
	"sync"
	"time"
)

type object struct {
	key        string
	size       uint64
	accessTime time.Time
}

type Cache struct {
	sync.Mutex

	list  *list.List
	table map[string]*list.Element
	size  uint64

	maxSize uint64
	path    string
}

func hashCacheKey(data string) string {
	hash := fnv.New64a()
	hash.Write([]byte(data))

	return base64.URLEncoding.EncodeToString(hash.Sum(nil))
}

func New(maxSize uint64, path string) *Cache {
	fmt.Printf("lru: new cache of size %d", maxSize)
	return &Cache{
		list:    list.New(),
		table:   make(map[string]*list.Element),
		maxSize: maxSize,
		path:    path,
	}
}

func (cache *Cache) FilePath(key string) string {
	return cache.path + "/" + hashCacheKey(key)
}

func (cache *Cache) Get(key string) ([]byte, bool) {
	cache.Lock()
	defer cache.Unlock()

	element := cache.table[key]

	if element == nil {
		return nil, false
	}

	cache.moveToFront(element)

	value, err := ioutil.ReadFile(cache.FilePath(element.Value.(*object).key))

	if err != nil {
		return nil, false
	}

	return value, true
}

func (cache *Cache) Set(key string, value []byte) {
	cache.Lock()
	defer cache.Unlock()

	if element := cache.table[key]; element != nil {
		cache.moveToFront(element)
	} else {
		cache.addNew(key, value)
	}
}

func (cache *Cache) Delete(key string) bool {
	cache.Lock()
	defer cache.Unlock()

	element := cache.table[key]

	if element == nil {
		return false
	}

	err := os.Remove(cache.FilePath(key))

	if err != nil {
		return false
	}

	cache.list.Remove(element)
	delete(cache.table, key)

	cache.size -= element.Value.(*object).size

	return true
}

func (cache *Cache) Clear() {
	cache.Lock()
	defer cache.Unlock()

	cache.clearFiles()
	cache.list.Init()
	cache.table = make(map[string]*list.Element)
	cache.size = 0
}

func (cache *Cache) Size() uint64 {
	cache.Lock()
	defer cache.Unlock()

	return cache.size
}

func (cache *Cache) MaxSize() uint64 {
	cache.Lock()
	defer cache.Unlock()

	return cache.maxSize
}

func (cache *Cache) Oldest() (oldest time.Time) {
	cache.Lock()
	defer cache.Unlock()

	if lastElem := cache.list.Back(); lastElem != nil {
		oldest = lastElem.Value.(*object).accessTime
	}

	return
}

func (cache *Cache) keys() []string {
	keys := make([]string, 0, cache.list.Len())

	for element := cache.list.Front(); element != nil; element = element.Next() {
		keys = append(keys, element.Value.(*object).key)
	}

	return keys
}

func (cache *Cache) moveToFront(element *list.Element) {
	cache.list.MoveToFront(element)
	element.Value.(*object).accessTime = time.Now()
}

func (cache *Cache) addNew(key string, value []byte) {
	size := uint64(len(value))

	fmt.Printf("lru: new object of size %d\n", size)

	if size > cache.maxSize {
		fmt.Println("lru: file is too large")
		return
	}

	newObject := &object{key, size, time.Now()}

	cache.trim(cache.size + newObject.size)

	if _, err := os.Stat(cache.FilePath(key)); os.IsNotExist(err) {
		err := ioutil.WriteFile(cache.FilePath(key), value, 0644)

		if err != nil {
			fmt.Println("lru: " + err.Error())
			return
		}

		element := cache.list.PushFront(newObject)
		cache.table[key] = element
		cache.size += (*newObject).size
		fmt.Printf("lru: added %d, new size is %d\n", (*newObject).size, cache.size)
	} else {
		fmt.Println("lru: file already exist")
	}
}

func (cache *Cache) trim(futureSize uint64) {
	for futureSize > cache.maxSize {
		element := cache.list.Back()

		if element == nil {
			fmt.Println("lru: file is too large")
			return
		}

		value := cache.list.Remove(element).(*object)

		if err := os.RemoveAll(cache.FilePath(value.key)); err != nil {
			fmt.Printf("lru: couldn't delete %s\n", cache.FilePath(value.key))
		}

		delete(cache.table, value.key)

		cache.size -= value.size
		futureSize -= value.size
	}
}

func (cache *Cache) clearFiles() {
	for _, key := range cache.keys() {
		os.RemoveAll(cache.FilePath(key))
	}
}
<commit_msg>Log which file is deleted<commit_after>package lru

import (
	"container/list"
	"encoding/base64"
	"fmt"
	"hash/fnv"
	"io/ioutil"
	"os"
	"sync"
	"time"
)

type object struct {
	key        string
	size       uint64
	accessTime time.Time
}

type Cache struct {
	sync.Mutex

	list  *list.List
	table map[string]*list.Element
	size  uint64

	maxSize uint64
	path    string
}

func hashCacheKey(data string) string {
	hash := fnv.New64a()
	hash.Write([]byte(data))

	return base64.URLEncoding.EncodeToString(hash.Sum(nil))
}

func New(maxSize uint64, path string) *Cache {
	fmt.Printf("lru: new cache of size %d\n", maxSize)

	return &Cache{
		list:    list.New(),
		table:   make(map[string]*list.Element),
		maxSize: maxSize,
		path:    path,
	}
}

func (cache *Cache) FilePath(key string) string {
	return cache.path + "/" + hashCacheKey(key)
}

func (cache *Cache) Get(key string) ([]byte, bool) {
	cache.Lock()
	defer cache.Unlock()

	element := cache.table[key]

	if element == nil {
		return nil, false
	}

	cache.moveToFront(element)

	value, err := ioutil.ReadFile(cache.FilePath(element.Value.(*object).key))

	if err != nil {
		return nil, false
	}

	return value, true
}

func (cache *Cache) Set(key string, value []byte) {
	cache.Lock()
	defer cache.Unlock()

	if element := cache.table[key]; element != nil {
		cache.moveToFront(element)
	} else {
		cache.addNew(key, value)
	}
}

func (cache *Cache) Delete(key string) bool {
	cache.Lock()
	defer cache.Unlock()

	element := cache.table[key]

	if element == nil {
		return false
	}

	err := os.Remove(cache.FilePath(key))

	if err != nil {
		return false
	}

	cache.list.Remove(element)
	delete(cache.table, key)

	cache.size -= element.Value.(*object).size

	return true
}

func (cache *Cache) Clear() {
	cache.Lock()
	defer cache.Unlock()

	cache.clearFiles()
	cache.list.Init()
	cache.table = make(map[string]*list.Element)
	cache.size = 0
}

func (cache *Cache) Size() uint64 {
	cache.Lock()
	defer cache.Unlock()

	return cache.size
}

func (cache *Cache) MaxSize() uint64 {
	cache.Lock()
	defer cache.Unlock()

	return cache.maxSize
}

func (cache *Cache) Oldest() (oldest time.Time) {
	cache.Lock()
	defer cache.Unlock()

	if lastElem := cache.list.Back(); lastElem != nil {
		oldest = lastElem.Value.(*object).accessTime
	}

	return
}

func (cache *Cache) keys() []string {
	keys := make([]string, 0, cache.list.Len())

	for element := cache.list.Front(); element != nil; element = element.Next() {
		keys = append(keys, element.Value.(*object).key)
	}

	return keys
}

func (cache *Cache) moveToFront(element *list.Element) {
	cache.list.MoveToFront(element)
	element.Value.(*object).accessTime = time.Now()
}

func (cache *Cache) addNew(key string, value []byte) {
	size := uint64(len(value))

	fmt.Printf("lru: new object of size %d\n", size)

	if size > cache.maxSize {
		fmt.Println("lru: file is too large")
		return
	}

	newObject := &object{key, size, time.Now()}

	cache.trim(cache.size + newObject.size)

	if _, err := os.Stat(cache.FilePath(key)); os.IsNotExist(err) {
		err := ioutil.WriteFile(cache.FilePath(key), value, 0644)

		if err != nil {
			fmt.Println("lru: " + err.Error())
			return
		}

		element := cache.list.PushFront(newObject)
		cache.table[key] = element
		cache.size += (*newObject).size
		fmt.Printf("lru: added %d, new size is %d\n", (*newObject).size, cache.size)
	} else {
		fmt.Println("lru: file already exist")
	}
}

func (cache *Cache) trim(futureSize uint64) {
	for futureSize > cache.maxSize {
		element := cache.list.Back()

		fmt.Printf("lru: deleting %s\n", cache.FilePath(value.key))

		if element == nil {
			fmt.Println("lru: file is too large")
			return
		}

		value := cache.list.Remove(element).(*object)

		if err := os.RemoveAll(cache.FilePath(value.key)); err != nil {
			fmt.Printf("lru: couldn't delete %s\n", cache.FilePath(value.key))
		}

		delete(cache.table, value.key)

		cache.size -= value.size
		futureSize -= value.size
	}
}

func (cache *Cache) clearFiles() {
	for _, key := range cache.keys() {
		os.RemoveAll(cache.FilePath(key))
	}
}
<|endoftext|>


<commit_before>package libkb

import (
	"sync"
	"testing"
	"time"

	"crypto/rand"

	"github.com/keybase/client/go/kex2"
)

type ktester struct {
	sender   kex2.DeviceID
	receiver kex2.DeviceID
	I        kex2.SessionID
	seqno    kex2.Seqno
}

func newKtester() *ktester {
	kt := &ktester{}
	if _, err := rand.Read(kt.sender[:]); err != nil {
		panic(err)
	}
	if _, err := rand.Read(kt.receiver[:]); err != nil {
		panic(err)
	}
	if _, err := rand.Read(kt.I[:]); err != nil {
		panic(err)
	}

	return kt
}

func (k *ktester) post(mr kex2.MessageRouter, b []byte) error {
	k.seqno++
	return mr.Post(k.I, k.sender, k.seqno, b)
}

func (k *ktester) get(mr kex2.MessageRouter, low kex2.Seqno, poll time.Duration) ([][]byte, error) {
	return mr.Get(k.I, k.receiver, low, poll)
}

func TestKex2Router(t *testing.T) {
	tc := SetupTest(t, "kex2 router")
	mr := NewKexRouter(tc.G)
	kt := newKtester()

	m1 := "hello everybody"
	m2 := "goodbye everybody"
	m3 := "plaid shirt"

	// test send 2 messages
	if err := kt.post(mr, []byte(m1)); err != nil {
		t.Fatal(err)
	}

	if err := kt.post(mr, []byte(m2)); err != nil {
		t.Fatal(err)
	}

	// test receive 2 messages
	msgs, err := kt.get(mr, 0, 100*time.Millisecond)
	if err != nil {
		t.Fatal(err)
	}
	if len(msgs) != 2 {
		t.Fatalf("number of messages: %d, expected 2", len(msgs))
	}
	if string(msgs[0]) != m1 {
		t.Errorf("message 0: %q, expected %q", msgs[0], m1)
	}
	if string(msgs[1]) != m2 {
		t.Errorf("message 1: %q, expected %q", msgs[1], m2)
	}

	// test calling receive before send
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		var merr error
		msgs, merr = kt.get(mr, 3, 1*time.Second)
		if merr != nil {
			t.Errorf("receive error: %s", merr)
		}
	}()

	time.Sleep(3 * time.Millisecond)
	if err := kt.post(mr, []byte(m3)); err != nil {
		t.Fatal(err)
	}

	wg.Wait()
	if len(msgs) != 1 {
		t.Fatalf("number of messages: %d, expected 1", len(msgs))
	}
	if string(msgs[0]) != m3 {
		t.Errorf("message: %q, expected %q", msgs[0], m3)
		t.Errorf("Full message vector was: %v\n", msgs)
	}

	// test no messages ready
	msgs, err = kt.get(mr, 4, 1*time.Millisecond)
	if err != nil {
		t.Fatal(err)
	}
	if len(msgs) != 0 {
		t.Errorf("number of messages: %d, expected 0", len(msgs))
	}
}
<commit_msg>CI can be slow, so pump up this timeout<commit_after>package libkb

import (
	"sync"
	"testing"
	"time"

	"crypto/rand"

	"github.com/keybase/client/go/kex2"
)

type ktester struct {
	sender   kex2.DeviceID
	receiver kex2.DeviceID
	I        kex2.SessionID
	seqno    kex2.Seqno
}

func newKtester() *ktester {
	kt := &ktester{}
	if _, err := rand.Read(kt.sender[:]); err != nil {
		panic(err)
	}
	if _, err := rand.Read(kt.receiver[:]); err != nil {
		panic(err)
	}
	if _, err := rand.Read(kt.I[:]); err != nil {
		panic(err)
	}

	return kt
}

func (k *ktester) post(mr kex2.MessageRouter, b []byte) error {
	k.seqno++
	return mr.Post(k.I, k.sender, k.seqno, b)
}

func (k *ktester) get(mr kex2.MessageRouter, low kex2.Seqno, poll time.Duration) ([][]byte, error) {
	return mr.Get(k.I, k.receiver, low, poll)
}

func TestKex2Router(t *testing.T) {
	tc := SetupTest(t, "kex2 router")
	mr := NewKexRouter(tc.G)
	kt := newKtester()

	m1 := "hello everybody"
	m2 := "goodbye everybody"
	m3 := "plaid shirt"

	// test send 2 messages
	if err := kt.post(mr, []byte(m1)); err != nil {
		t.Fatal(err)
	}

	if err := kt.post(mr, []byte(m2)); err != nil {
		t.Fatal(err)
	}

	// test receive 2 messages
	msgs, err := kt.get(mr, 0, 100*time.Millisecond)
	if err != nil {
		t.Fatal(err)
	}
	if len(msgs) != 2 {
		t.Fatalf("number of messages: %d, expected 2", len(msgs))
	}
	if string(msgs[0]) != m1 {
		t.Errorf("message 0: %q, expected %q", msgs[0], m1)
	}
	if string(msgs[1]) != m2 {
		t.Errorf("message 1: %q, expected %q", msgs[1], m2)
	}

	// test calling receive before send
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		var merr error
		// Very large timeout, for the benefit of CI, which maybe be
		// slow
		msgs, merr = kt.get(mr, 3, 10*time.Second)
		if merr != nil {
			t.Errorf("receive error: %s", merr)
		}
	}()

	time.Sleep(3 * time.Millisecond)
	if err := kt.post(mr, []byte(m3)); err != nil {
		t.Fatal(err)
	}

	wg.Wait()
	if len(msgs) != 1 {
		t.Fatalf("number of messages: %d, expected 1", len(msgs))
	}
	if string(msgs[0]) != m3 {
		t.Errorf("message: %q, expected %q", msgs[0], m3)
		t.Errorf("Full message vector was: %v\n", msgs)
	}

	// test no messages ready
	msgs, err = kt.get(mr, 4, 1*time.Millisecond)
	if err != nil {
		t.Fatal(err)
	}
	if len(msgs) != 0 {
		t.Errorf("number of messages: %d, expected 0", len(msgs))
	}
}
<|endoftext|>


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

// +build windows

package logger

// These had a weird unicode character which made it look messy on Windows

const (
	fancyFormat   = "%{color}%{time:15:04:05.000000} - [%{level:.4s} %{module} %{shortfile}] %{id:03x}%{color:reset} %{message}"
	plainFormat   = "[%{level:.4s}] %{id:03x} %{message}"
	fileFormat    = "%{time:15:04:05.000000} - [%{level:.4s} %{module} %{shortfile}] %{id:03x} %{message}"
	defaultFormat = "%{color}- %{level} %{message}%{color:reset}"
)
<commit_msg>logger: add date to format on Windows too<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

// +build windows

package logger

// These had a weird unicode character which made it look messy on Windows

const (
	fancyFormat   = "%{color}%{time:2006-01-02T15:04:05.000000} - [%{level:.4s} %{module} %{shortfile}] %{id:03x}%{color:reset} %{message}"
	plainFormat   = "[%{level:.4s}] %{id:03x} %{message}"
	fileFormat    = "%{time:2006-01-02T15:04:05.000000} - [%{level:.4s} %{module} %{shortfile}] %{id:03x} %{message}"
	defaultFormat = "%{color}- %{level} %{message}%{color:reset}"
)
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"sync"
)

// gen takes a list of ints and returns channel which produces these numbers.
func gen(done chan struct{}, nums ...int) <-chan int {
	var (
		out = make(chan int)
		n   int
	)
	go func() {
		for _, n = range nums {
			select {
			case out <- n:
			case <-done:
				fmt.Println("gen closed")
				close(out)
				return
			}
		}
		close(out)
	}()
	return out
}

// sq takes a channel of ints and return a channel which outputs the squares of the inputs.
func sq(done chan struct{}, nums <-chan int) <-chan int {
	var (
		out = make(chan int)
		n   int
	)
	go func() {
		for n = range nums {
			select {
			case out <- n * n:
			case <-done:
				fmt.Println("sq closed")
				close(out)
				return
			}
		}
		close(out)
	}()
	return out
}

// consume is a helper method for merge. It reads values from c and writes them to out, until c is closed, calling Done the input WaitGroup.
func consume(done chan struct{}, wg *sync.WaitGroup, c <-chan int, out chan<- int) {
	defer wg.Done()
	for n := range c {
		select {
		case out<- n:
		case <-done:
			fmt.Println("consume closed")
			return
		}
	}
}

// merge will read from two channels and produce a single output channel
func merge(done chan struct{}, cs ...<-chan int) <-chan int {
	var (
		out chan int
		wg  sync.WaitGroup
		c   <-chan int
	)
	out = make(chan int)
	wg = sync.WaitGroup{}
	wg.Add(len(cs))
	for _, c = range cs {
		go consume(done, &wg, c, out)
	}
	go func() {
		wg.Wait()
		fmt.Println("merge closed")
		close(out)
	}()
	return out
}

func main() {
	var (
		c1, c2, c3, c4, c5 <-chan int
		done chan struct{}
		n, i int
	)
	done = make(chan struct{})

	c1 = gen(done, 1, 2, 3, 4, 5)
	c2 = sq(done, c1)
	c3 = sq(done, c2)
	c4 = gen(done, 1, 2, 3, 4, 4, 5)
	c5 = merge(done, c3, c4)

	i = 0
	for n = range c5 {
		i += 1
		fmt.Println(n)
		if i == 3 {
			fmt.Println("main closed")
			close(done)
		}
	}
}

//// merge alternative version only for two channels without the use of a WaitGroup.
//func merge(c1, c2 <-chan int) <-chan int {
//	var (
//		out chan int
//	)
//	out = make(chan int)
//	go func() {
//		var (
//			n int
//			open1, open2 bool
//		)
//		for {
//			select {
//			case n, open1 = <-c1:
//				if open1 == false && open2 == false {
//					close(out)
//					return
//				} else if open1 == false {
//					continue
//				} else {
//					out <- n
//				}
//			case n, open2 = <-c2:
//				if open1 == false && open2 == false {
//					close(out)
//					return
//				} else if open2 == false {
//					continue
//				} else {
//					out <- n
//				}
//			}
//		}
//	}()
//	return out
//}
<commit_msg>my context version of pipeline cancelation<commit_after>package main

import (
	"context"
	"fmt"
	"sync"
)

// gen takes a list of ints and returns channel which produces these numbers.
func gen(ctx context.Context, nums ...int) <-chan int {
	var (
		out = make(chan int)
		n   int
	)
	go func() {
		for _, n = range nums {
			select {
			case out <- n:
			case <-ctx.Done():
				fmt.Println("gen closed")
				close(out)
				return
			}
		}
		close(out)
	}()
	return out
}

// sq takes a channel of ints and return a channel which outputs the squares of the inputs.
func sq(ctx context.Context, nums <-chan int) <-chan int {
	var (
		out = make(chan int)
		n   int
	)
	go func() {
		for n = range nums {
			select {
			case out <- n * n:
			case <-ctx.Done():
				fmt.Println("sq closed")
				close(out)
				return
			}
		}
		close(out)
	}()
	return out
}

// consume is a helper method for merge. It reads values from c and writes them to out, until c is closed, calling Done the input WaitGroup.
func consume(ctx context.Context, wg *sync.WaitGroup, c <-chan int, out chan<- int) {
	defer wg.Done()
	for n := range c {
		select {
		case out <- n:
		case <-ctx.Done():
			fmt.Println("consume closed")
			return
		}
	}
}

// merge will read from two channels and produce a single output channel
func merge(ctx context.Context, cs ...<-chan int) <-chan int {
	var (
		out chan int
		wg  sync.WaitGroup
		c   <-chan int
	)
	out = make(chan int)
	wg = sync.WaitGroup{}
	wg.Add(len(cs))
	for _, c = range cs {
		go consume(ctx, &wg, c, out)
	}
	go func() {
		wg.Wait()
		fmt.Println("merge closed")
		close(out)
	}()
	return out
}

func main() {
	var (
		c1, c2, c3, c4, c5 <-chan int
		ctx                context.Context
		cancel             context.CancelFunc
		n, i               int
	)
	ctx, cancel = context.WithCancel(context.Background())

	c1 = gen(ctx, 1, 2, 3, 4, 5)
	c2 = sq(ctx, c1)
	c3 = sq(ctx, c2)
	c4 = gen(ctx, 1, 2, 3, 4, 4, 5)
	c5 = merge(ctx, c3, c4)

	i = 0
	for n = range c5 {
		i += 1
		fmt.Println(n)
		if i == 3 {
			fmt.Println("main closed")
			cancel()
		}
	}
}

//// merge alternative version only for two channels without the use of a WaitGroup.
//func merge(c1, c2 <-chan int) <-chan int {
//	var (
//		out chan int
//	)
//	out = make(chan int)
//	go func() {
//		var (
//			n int
//			open1, open2 bool
//		)
//		for {
//			select {
//			case n, open1 = <-c1:
//				if open1 == false && open2 == false {
//					close(out)
//					return
//				} else if open1 == false {
//					continue
//				} else {
//					out <- n
//				}
//			case n, open2 = <-c2:
//				if open1 == false && open2 == false {
//					close(out)
//					return
//				} else if open2 == false {
//					continue
//				} else {
//					out <- n
//				}
//			}
//		}
//	}()
//	return out
//}
<|endoftext|>


<commit_before>package main

import (
	"exp/inotify"
	"fmt"
	"io"
	"koding/tools/dnode"
	"koding/tools/kite"
	"koding/tools/log"
	"koding/virt"
	"os"
	"path"
	"regexp"
	"strconv"
	"time"
)

func init() {
	go func() {
		for err := range virt.WatchErrors {
			log.Warn("Watcher error", err)
		}
	}()
}

func registerFileSystemMethods(k *kite.Kite) {
	registerVmMethod(k, "fs.readDirectory", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path                string
			OnChange            dnode.Callback
			WatchSubdirectories bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], onChange: [function], watchSubdirectories: [bool] }"}
		}

		response := make(map[string]interface{})

		if params.OnChange != nil {
			watch, err := vos.WatchDirectory(params.Path, params.WatchSubdirectories, func(ev *inotify.Event, info os.FileInfo) {
				defer log.RecoverAndLog()

				if (ev.Mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO | inotify.IN_ATTRIB)) != 0 {
					if info == nil {
						return // skip this event, file was deleted and deletion event will follow
					}
					params.OnChange(map[string]interface{}{
						"event": "added",
						"file":  makeFileEntry(vos, ev.Name, info),
					})
					return
				}
				if (ev.Mask & (inotify.IN_DELETE | inotify.IN_MOVED_FROM)) != 0 {
					params.OnChange(map[string]interface{}{
						"event": "removed",
						"file":  FileEntry{Name: path.Base(ev.Name), FullPath: ev.Name},
					})
					return
				}
			})
			if err != nil {
				return nil, err
			}
			channel.OnDisconnect(func() { watch.Close() })
			response["stopWatching"] = func() { watch.Close() }
		}

		dir, err := vos.Open(params.Path)
		if err != nil {
			return nil, err
		}
		defer dir.Close()

		infos, err := dir.Readdir(0)
		if err != nil {
			return nil, err
		}

		files := make([]FileEntry, len(infos))
		for i, info := range infos {
			files[i] = makeFileEntry(vos, path.Join(params.Path, info.Name()), info)
		}
		response["files"] = files

		return response, nil
	})

	registerVmMethod(k, "fs.glob", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Pattern string
		}
		if args.Unmarshal(&params) != nil || params.Pattern == "" {
			return nil, &kite.ArgumentError{Expected: "{ pattern: [string] }"}
		}

		matches, err := vos.Glob(params.Pattern)
		if err == nil && matches == nil {
			matches = []string{}
		}
		return matches, err
	})

	registerVmMethod(k, "fs.readFile", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		file, err := vos.Open(params.Path)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		fi, err := file.Stat()
		if err != nil {
			return nil, err
		}

		if fi.Size() > 10*1024*1024 {
			return nil, fmt.Errorf("File larger than 10MiB.")
		}

		buf := make([]byte, fi.Size())
		if _, err := io.ReadFull(file, buf); err != nil {
			return nil, err
		}

		return map[string]interface{}{"content": buf}, nil
	})

	registerVmMethod(k, "fs.writeFile", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path           string
			Content        []byte
			DoNotOverwrite bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" || params.Content == nil {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], content: [base64], doNotOverwrite: [bool] }"}
		}

		flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
		if params.DoNotOverwrite {
			flags |= os.O_EXCL
		}
		file, err := vos.OpenFile(params.Path, flags, 0666)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		return file.Write(params.Content)
	})

	suffixRegexp, err := regexp.Compile(`.((_\d+)?)(\.\w*)?$`)
	if err != nil {
		panic(err)
	}

	registerVmMethod(k, "fs.ensureNonexistentPath", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		name := params.Path
		index := 1
		for {
			_, err := vos.Stat(name)
			if err != nil {
				if os.IsNotExist(err) {
					break
				}
				return nil, err
			}

			loc := suffixRegexp.FindStringSubmatchIndex(name)
			name = name[:loc[2]] + "_" + strconv.Itoa(index) + name[loc[3]:]
			index++
		}

		return name, nil
	})

	registerVmMethod(k, "fs.getInfo", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		fi, err := vos.Stat(params.Path)
		if err != nil {
			if os.IsNotExist(err) {
				return nil, nil
			}
			return nil, err
		}

		return makeFileEntry(vos, params.Path, fi), nil
	})

	registerVmMethod(k, "fs.setPermissions", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Mode      os.FileMode
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], mode: [integer], recursive: [bool] }"}
		}

		var doChange func(name string) error
		doChange = func(name string) error {
			if err := vos.Chmod(name, params.Mode); err != nil {
				return err
			}
			if !params.Recursive {
				return nil
			}
			fi, err := vos.Stat(name)
			if err != nil {
				return err
			}
			if !fi.IsDir() {
				return nil
			}
			dir, err := vos.Open(name)
			if err != nil {
				return err
			}
			defer dir.Close()
			entries, err := dir.Readdirnames(0)
			if err != nil {
				return err
			}
			var firstErr error
			for _, entry := range entries {
				err := doChange(name + "/" + entry)
				if err != nil && firstErr == nil {
					firstErr = err
				}
			}
			return firstErr
		}
		if err := doChange(params.Path); err != nil {
			return nil, err
		}

		return true, nil
	})

	registerVmMethod(k, "fs.remove", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], recursive: [bool] }"}
		}

		if params.Recursive {
			if err := vos.RemoveAll(params.Path); err != nil {
				return nil, err
			}
			return true, nil
		}

		if err := vos.Remove(params.Path); err != nil {
			return nil, err
		}
		return true, nil
	})

	registerVmMethod(k, "fs.rename", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			OldPath string
			NewPath string
		}
		if args.Unmarshal(&params) != nil || params.OldPath == "" || params.NewPath == "" {
			return nil, &kite.ArgumentError{Expected: "{ oldPath: [string], newPath: [string] }"}
		}

		if err := vos.Rename(params.OldPath, params.NewPath); err != nil {
			return nil, err
		}

		return true, nil
	})

	registerVmMethod(k, "fs.createDirectory", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], recursive: [bool] }"}
		}

		if params.Recursive {
			if err := vos.MkdirAll(params.Path, 0755); err != nil {
				return nil, err
			}
			return true, nil
		}

		if err := vos.Mkdir(params.Path, 0755); err != nil {
			return nil, err
		}
		return true, nil
	})
}

type FileEntry struct {
	Name     string      `json:"name"`
	FullPath string      `json:"fullPath"`
	IsDir    bool        `json:"isDir"`
	Size     int64       `json:"size"`
	Mode     os.FileMode `json:"mode"`
	Time     time.Time   `json:"time"`
	IsBroken bool        `json:"isBroken"`
	Readable bool        `json:"readable"`
	Writable bool        `json:"writable"`
}

func makeFileEntry(vos *virt.VOS, fullPath string, fi os.FileInfo) FileEntry {
	entry := FileEntry{
		Name:     fi.Name(),
		FullPath: fullPath,
		IsDir:    fi.IsDir(),
		Size:     fi.Size(),
		Mode:     fi.Mode(),
		Time:     fi.ModTime(),
		Readable: vos.IsReadable(fi),
		Writable: vos.IsWritable(fi),
	}

	if fi.Mode()&os.ModeSymlink != 0 {
		symlinkInfo, err := vos.Stat(path.Dir(fullPath) + "/" + fi.Name())
		if err != nil {
			entry.IsBroken = true
			return entry
		}
		entry.IsDir = symlinkInfo.IsDir()
		entry.Size = symlinkInfo.Size()
		entry.Mode = symlinkInfo.Mode()
		entry.Time = symlinkInfo.ModTime()
	}

	return entry
}
<commit_msg>os kite: Distinct "attributesChanged" event for watchers.<commit_after>package main

import (
	"exp/inotify"
	"fmt"
	"io"
	"koding/tools/dnode"
	"koding/tools/kite"
	"koding/tools/log"
	"koding/virt"
	"os"
	"path"
	"regexp"
	"strconv"
	"time"
)

func init() {
	go func() {
		for err := range virt.WatchErrors {
			log.Warn("Watcher error", err)
		}
	}()
}

func registerFileSystemMethods(k *kite.Kite) {
	registerVmMethod(k, "fs.readDirectory", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path                string
			OnChange            dnode.Callback
			WatchSubdirectories bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], onChange: [function], watchSubdirectories: [bool] }"}
		}

		response := make(map[string]interface{})

		if params.OnChange != nil {
			watch, err := vos.WatchDirectory(params.Path, params.WatchSubdirectories, func(ev *inotify.Event, info os.FileInfo) {
				defer log.RecoverAndLog()

				if (ev.Mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO | inotify.IN_ATTRIB)) != 0 {
					if info == nil {
						return // skip this event, file was deleted and deletion event will follow
					}
					event := "added"
					if ev.Mask&inotify.IN_ATTRIB != 0 {
						event = "attributesChanged"
					}
					params.OnChange(map[string]interface{}{
						"event": event,
						"file":  makeFileEntry(vos, ev.Name, info),
					})
					return
				}
				if (ev.Mask & (inotify.IN_DELETE | inotify.IN_MOVED_FROM)) != 0 {
					params.OnChange(map[string]interface{}{
						"event": "removed",
						"file":  FileEntry{Name: path.Base(ev.Name), FullPath: ev.Name},
					})
					return
				}
			})
			if err != nil {
				return nil, err
			}
			channel.OnDisconnect(func() { watch.Close() })
			response["stopWatching"] = func() { watch.Close() }
		}

		dir, err := vos.Open(params.Path)
		if err != nil {
			return nil, err
		}
		defer dir.Close()

		infos, err := dir.Readdir(0)
		if err != nil {
			return nil, err
		}

		files := make([]FileEntry, len(infos))
		for i, info := range infos {
			files[i] = makeFileEntry(vos, path.Join(params.Path, info.Name()), info)
		}
		response["files"] = files

		return response, nil
	})

	registerVmMethod(k, "fs.glob", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Pattern string
		}
		if args.Unmarshal(&params) != nil || params.Pattern == "" {
			return nil, &kite.ArgumentError{Expected: "{ pattern: [string] }"}
		}

		matches, err := vos.Glob(params.Pattern)
		if err == nil && matches == nil {
			matches = []string{}
		}
		return matches, err
	})

	registerVmMethod(k, "fs.readFile", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		file, err := vos.Open(params.Path)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		fi, err := file.Stat()
		if err != nil {
			return nil, err
		}

		if fi.Size() > 10*1024*1024 {
			return nil, fmt.Errorf("File larger than 10MiB.")
		}

		buf := make([]byte, fi.Size())
		if _, err := io.ReadFull(file, buf); err != nil {
			return nil, err
		}

		return map[string]interface{}{"content": buf}, nil
	})

	registerVmMethod(k, "fs.writeFile", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path           string
			Content        []byte
			DoNotOverwrite bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" || params.Content == nil {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], content: [base64], doNotOverwrite: [bool] }"}
		}

		flags := os.O_RDWR | os.O_CREATE | os.O_TRUNC
		if params.DoNotOverwrite {
			flags |= os.O_EXCL
		}
		file, err := vos.OpenFile(params.Path, flags, 0666)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		return file.Write(params.Content)
	})

	suffixRegexp, err := regexp.Compile(`.((_\d+)?)(\.\w*)?$`)
	if err != nil {
		panic(err)
	}

	registerVmMethod(k, "fs.ensureNonexistentPath", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		name := params.Path
		index := 1
		for {
			_, err := vos.Stat(name)
			if err != nil {
				if os.IsNotExist(err) {
					break
				}
				return nil, err
			}

			loc := suffixRegexp.FindStringSubmatchIndex(name)
			name = name[:loc[2]] + "_" + strconv.Itoa(index) + name[loc[3]:]
			index++
		}

		return name, nil
	})

	registerVmMethod(k, "fs.getInfo", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path string
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string] }"}
		}

		fi, err := vos.Stat(params.Path)
		if err != nil {
			if os.IsNotExist(err) {
				return nil, nil
			}
			return nil, err
		}

		return makeFileEntry(vos, params.Path, fi), nil
	})

	registerVmMethod(k, "fs.setPermissions", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Mode      os.FileMode
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], mode: [integer], recursive: [bool] }"}
		}

		var doChange func(name string) error
		doChange = func(name string) error {
			if err := vos.Chmod(name, params.Mode); err != nil {
				return err
			}
			if !params.Recursive {
				return nil
			}
			fi, err := vos.Stat(name)
			if err != nil {
				return err
			}
			if !fi.IsDir() {
				return nil
			}
			dir, err := vos.Open(name)
			if err != nil {
				return err
			}
			defer dir.Close()
			entries, err := dir.Readdirnames(0)
			if err != nil {
				return err
			}
			var firstErr error
			for _, entry := range entries {
				err := doChange(name + "/" + entry)
				if err != nil && firstErr == nil {
					firstErr = err
				}
			}
			return firstErr
		}
		if err := doChange(params.Path); err != nil {
			return nil, err
		}

		return true, nil
	})

	registerVmMethod(k, "fs.remove", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], recursive: [bool] }"}
		}

		if params.Recursive {
			if err := vos.RemoveAll(params.Path); err != nil {
				return nil, err
			}
			return true, nil
		}

		if err := vos.Remove(params.Path); err != nil {
			return nil, err
		}
		return true, nil
	})

	registerVmMethod(k, "fs.rename", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			OldPath string
			NewPath string
		}
		if args.Unmarshal(&params) != nil || params.OldPath == "" || params.NewPath == "" {
			return nil, &kite.ArgumentError{Expected: "{ oldPath: [string], newPath: [string] }"}
		}

		if err := vos.Rename(params.OldPath, params.NewPath); err != nil {
			return nil, err
		}

		return true, nil
	})

	registerVmMethod(k, "fs.createDirectory", false, func(args *dnode.Partial, channel *kite.Channel, vos *virt.VOS) (interface{}, error) {
		var params struct {
			Path      string
			Recursive bool
		}
		if args.Unmarshal(&params) != nil || params.Path == "" {
			return nil, &kite.ArgumentError{Expected: "{ path: [string], recursive: [bool] }"}
		}

		if params.Recursive {
			if err := vos.MkdirAll(params.Path, 0755); err != nil {
				return nil, err
			}
			return true, nil
		}

		if err := vos.Mkdir(params.Path, 0755); err != nil {
			return nil, err
		}
		return true, nil
	})
}

type FileEntry struct {
	Name     string      `json:"name"`
	FullPath string      `json:"fullPath"`
	IsDir    bool        `json:"isDir"`
	Size     int64       `json:"size"`
	Mode     os.FileMode `json:"mode"`
	Time     time.Time   `json:"time"`
	IsBroken bool        `json:"isBroken"`
	Readable bool        `json:"readable"`
	Writable bool        `json:"writable"`
}

func makeFileEntry(vos *virt.VOS, fullPath string, fi os.FileInfo) FileEntry {
	entry := FileEntry{
		Name:     fi.Name(),
		FullPath: fullPath,
		IsDir:    fi.IsDir(),
		Size:     fi.Size(),
		Mode:     fi.Mode(),
		Time:     fi.ModTime(),
		Readable: vos.IsReadable(fi),
		Writable: vos.IsWritable(fi),
	}

	if fi.Mode()&os.ModeSymlink != 0 {
		symlinkInfo, err := vos.Stat(path.Dir(fullPath) + "/" + fi.Name())
		if err != nil {
			entry.IsBroken = true
			return entry
		}
		entry.IsDir = symlinkInfo.IsDir()
		entry.Size = symlinkInfo.Size()
		entry.Mode = symlinkInfo.Mode()
		entry.Time = symlinkInfo.ModTime()
	}

	return entry
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"hash"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"go.mozilla.org/autograph/signer/apk"
	"go.mozilla.org/autograph/signer/contentsignature"
	"go.mozilla.org/autograph/signer/xpi"
	"go.mozilla.org/hawk"
)

type signaturerequest struct {
	Input string `json:"input"`
	KeyID string `json:"keyid"`
}

type signatureresponse struct {
	Ref        string `json:"ref"`
	Type       string `json:"type"`
	SignerID   string `json:"signer_id"`
	PublicKey  string `json:"public_key,omitempty"`
	Signature  string `json:"signature"`
	SignedFile string `json:"signed_file"`
}

func main() {
	var (
		userid, pass, data, url, infile, outfile, keyid string
		iter, maxworkers                                int
		debug                                           bool
		err                                             error
		requests                                        []signaturerequest
	)
	flag.StringVar(&userid, "u", "alice", "User ID")
	flag.StringVar(&pass, "p", "fs5wgcer9qj819kfptdlp8gm227ewxnzvsuj9ztycsx08hfhzu", "Secret passphrase")
	flag.StringVar(&data, "d", "Y2FyaWJvdW1hdXJpY2UK", "Base64 data to sign")
	flag.StringVar(&infile, "f", ``, "Input file. Will decide on signing mode based on extension (apk or xpi). Overrides -r.")
	flag.StringVar(&outfile, "o", ``, "Output file. If set, writes the signature to this file")
	flag.StringVar(&keyid, "k", ``, "Key ID to request a signature from a specific signer.")
	flag.StringVar(&url, "t", `http://localhost:8000/sign/data`, "signing api URL")
	flag.IntVar(&iter, "i", 1, "number of signatures to request")
	flag.IntVar(&maxworkers, "m", 1, "maximum number of parallel workers")
	flag.BoolVar(&debug, "D", false, "debug logs: show raw requests & responses")
	flag.Parse()

	switch {
	case strings.HasSuffix(infile, ".xpi"):
		// go parse an xpi
	case strings.HasSuffix(infile, ".apk"):
		apkbytes, err := ioutil.ReadFile(infile)
		if err != nil {
			log.Fatal(err)
		}
		data = base64.StdEncoding.EncodeToString(apkbytes)
	}
	request := signaturerequest{
		Input: data,
		KeyID: keyid,
	}
	requests = append(requests, request)
	reqBody, err := json.Marshal(requests)
	if err != nil {
		log.Fatal(err)
	}
	tr := &http.Transport{
		DisableKeepAlives: false,
	}
	cli := &http.Client{Transport: tr}

	workers := 0
	for i := 0; i < iter; i++ {
		for {
			if workers < maxworkers {
				break
			}
			time.Sleep(time.Second)
		}
		workers++
		go func() {
			// prepare the http request, with hawk token
			rdr := bytes.NewReader(reqBody)
			req, err := http.NewRequest("POST", url, rdr)
			if err != nil {
				log.Fatal(err)
			}
			req.Header.Set("Content-Type", "application/json")
			authheader := getAuthHeader(req, userid, pass, sha256.New, fmt.Sprintf("%d", time.Now().Nanosecond()), "application/json", reqBody)
			req.Header.Set("Authorization", authheader)
			if debug {
				fmt.Printf("DEBUG: sending request\nDEBUG: %+v\nDEBUG: %s\n", req, reqBody)
			}
			resp, err := cli.Do(req)
			if err != nil || resp == nil {
				log.Fatal(err)
			}
			if debug {
				fmt.Printf("DEBUG: received response\nDEBUG: %+v\n", resp)
			}
			defer resp.Body.Close()
			body, err := ioutil.ReadAll(resp.Body)
			if debug {
				fmt.Printf("DEBUG: %s\n", body)
			}

			// verify that we got a proper signature response, with a valid signature
			var responses []signatureresponse
			err = json.Unmarshal(body, &responses)
			if err != nil {
				log.Fatal(err)
			}
			if len(requests) != len(responses) {
				log.Fatalf("sent %d signature requests and got %d responses, something's wrong", len(requests), len(responses))
			}
			for i, response := range responses {
				input, err := base64.StdEncoding.DecodeString(requests[i].Input)
				if err != nil {
					log.Fatal(err)
				}
				var sigStatus bool
				switch response.Type {
				case contentsignature.Type:
					sigStatus = verifyContentSignature(input, response, req.URL.RequestURI())
				case xpi.Type:
					sigStatus = verifyXPI(input, response)
				case apk.Type:
					sigStatus = verifyAPK(input, response)
				default:
					log.Fatal("unsupported signature type", response.Type)
				}
				if sigStatus {
					log.Printf("signature %d from signer %q passes", i, response.SignerID)
				} else {
					log.Fatalf("response %d from signer %q does not pass!", i, response.SignerID)
				}
				if outfile != "" {
					sigData, err := base64.StdEncoding.DecodeString(response.SignedFile)
					if err != nil {
						log.Fatal(err)
					}
					err = ioutil.WriteFile(outfile, sigData, 0644)
					if err != nil {
						log.Fatal(err)
					}
					log.Println("response written to", outfile)
				}
			}
			workers--
		}()
	}
	for {
		if workers <= 0 {
			break
		}
		time.Sleep(time.Second)
	}
}

func getAuthHeader(req *http.Request, user, token string, hash func() hash.Hash, ext, contenttype string, payload []byte) string {
	auth := hawk.NewRequestAuth(req,
		&hawk.Credentials{
			ID:   user,
			Key:  token,
			Hash: hash},
		0)
	auth.Ext = ext
	payloadhash := auth.PayloadHash(contenttype)
	payloadhash.Write(payload)
	auth.SetHash(payloadhash)
	return auth.RequestHeader()
}

// verify an ecdsa signature
func verifyContentSignature(input []byte, resp signatureresponse, endpoint string) bool {
	keyBytes, err := base64.StdEncoding.DecodeString(resp.PublicKey)
	if err != nil {
		log.Fatal(err)
	}
	keyInterface, err := x509.ParsePKIXPublicKey(keyBytes)
	if err != nil {
		log.Fatal(err)
	}
	pubKey := keyInterface.(*ecdsa.PublicKey)
	if endpoint == "/sign/data" {
		var templated []byte
		templated = make([]byte, len("Content-Signature:\x00")+len(input))
		copy(templated[:len("Content-Signature:\x00")], []byte("Content-Signature:\x00"))
		copy(templated[len("Content-Signature:\x00"):], input)

		var md hash.Hash
		switch pubKey.Params().Name {
		case "P-256":
			md = sha256.New()
		case "P-384":
			md = sha512.New384()
		case "P-521":
			md = sha512.New()
		default:
			log.Fatalf("unsupported curve algorithm %q", pubKey.Params().Name)
		}
		md.Write(templated)
		input = md.Sum(nil)
	}
	sig, err := contentsignature.Unmarshal(resp.Signature)
	if err != nil {
		log.Fatal(err)
	}
	return ecdsa.Verify(pubKey, input, sig.R, sig.S)
}

func verifyXPI(input []byte, resp signatureresponse) bool {
	sig, err := xpi.Unmarshal(resp.Signature, input)
	if err != nil {
		log.Fatal(err)
	}
	err = sig.VerifyWithChain(nil)
	if err != nil {
		log.Fatal(err)
	}
	return true
}

func verifyAPK(input []byte, resp signatureresponse) bool {
	return true
}
<commit_msg>autograph-client: fix all the things<commit_after>package main

import (
	"archive/zip"
	"bytes"
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"hash"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"go.mozilla.org/autograph/signer/apk"
	"go.mozilla.org/autograph/signer/contentsignature"
	"go.mozilla.org/autograph/signer/xpi"
	"go.mozilla.org/hawk"
)

type signaturerequest struct {
	Input   string `json:"input"`
	KeyID   string `json:"keyid"`
	Options interface{}
}

type signatureresponse struct {
	Ref        string `json:"ref"`
	Type       string `json:"type"`
	SignerID   string `json:"signer_id"`
	PublicKey  string `json:"public_key,omitempty"`
	Signature  string `json:"signature"`
	SignedFile string `json:"signed_file"`
	X5U        string `json:"x5u,omitempty"`
}

func main() {
	var (
		userid, pass, data, hash, url, infile, outfile, keyid, cn string
		iter, maxworkers                                          int
		debug                                                     bool
		err                                                       error
		requests                                                  []signaturerequest
	)
	flag.Usage = func() {
		fmt.Print("autograph-client - simple command line client to the autograph service\n\n")
		flag.PrintDefaults()
		fmt.Print(`
examples:
* sign an APK, returns a signed APK
	$ go run client.go -f signed.apk -o test.apk -k testapp-android
	$ /opt/android-sdk/build-tools/27.0.3/apksigner verify -v test.apk
	Verifies
	Verified using v1 scheme (JAR signing): true
	Verified using v2 scheme (APK Signature Scheme v2): false
	Number of signers: 1

* issue a content signature on a hash, returns a CS header string:
	$ echo -en "Content-Signature:\0\0foo bar baz" | openssl dgst -sha256 -binary | openssl enc -base64
	$ go run client.go -a rniK3StMMdrWbXuJxVqEjALHR4cIp6mn3Coilj1kozk= -o testcs.txt
	$ cat testcs.txt
	keyid=appkey1;p384ecdsa=gf_X5JHv1KItwnpgGxmIdJ9KdjZ7EZMcleM-BTMGLnDuPpRvaGUdUDUg...

* sign an XPI, returns a PKCS7 detached signature:
	$ base64 -w 0 mozilla.sf
	U2lnbmF0dXJlLVZlcnNpb246IDEuMApNRDUt...
	$ go run client.go -d U2lnbmF0dXJlLVZlcnNpb2...  -cn cariboumaurice -k webextensions-rsa -o detachedxpisig.pkcs7

`)
	}
	flag.StringVar(&userid, "u", "alice", "User ID")
	flag.StringVar(&pass, "p", "fs5wgcer9qj819kfptdlp8gm227ewxnzvsuj9ztycsx08hfhzu", "Secret passphrase")
	flag.StringVar(&data, "d", "base64(data)", "Base64 data to sign, will use the /sign/data endpoint")
	flag.StringVar(&hash, "a", "base64(sha256(data))", "Base64 hash to sign, will use the /sign/hash endpoint")
	flag.StringVar(&infile, "f", "/path/to/file", "Input file to sign, will use the /sign/file endpoint")
	flag.StringVar(&outfile, "o", ``, "Output file. If set, writes the signature or file to this location")
	flag.StringVar(&keyid, "k", ``, "Key ID to request a signature from a specific signer")
	flag.StringVar(&url, "t", `http://localhost:8000`, "target server, do not specific a URI or trailing slash")
	flag.IntVar(&iter, "i", 1, "number of signatures to request")
	flag.IntVar(&maxworkers, "m", 1, "maximum number of parallel workers")
	flag.StringVar(&cn, "cn", "", "when signing XPI, sets the CN to the add-on ID")
	flag.BoolVar(&debug, "D", false, "debug logs: show raw requests & responses")
	flag.Parse()

	if data != "base64(data)" {
		log.Printf("signing data %q", data)
		url = url + "/sign/data"
	} else if hash != "base64(sha256(data))" {
		log.Printf("signing hash %q", hash)
		url = url + "/sign/hash"
		data = hash
	} else if infile != "/path/to/file" {
		log.Printf("signing file %q", infile)
		url = url + "/sign/file"
		filebytes, err := ioutil.ReadFile(infile)
		if err != nil {
			log.Fatal(err)
		}
		data = base64.StdEncoding.EncodeToString(filebytes)
	}
	request := signaturerequest{
		Input: data,
		KeyID: keyid,
	}
	// if signing an xpi, the CN is set in the options
	if cn != "" {
		request.Options = xpi.Options{ID: cn}
	}
	requests = append(requests, request)
	reqBody, err := json.Marshal(requests)
	if err != nil {
		log.Fatal(err)
	}
	tr := &http.Transport{
		DisableKeepAlives: false,
	}
	cli := &http.Client{Transport: tr}

	workers := 0
	for i := 0; i < iter; i++ {
		for {
			if workers < maxworkers {
				break
			}
			time.Sleep(time.Second)
		}
		workers++
		go func() {
			// prepare the http request, with hawk token
			rdr := bytes.NewReader(reqBody)
			req, err := http.NewRequest("POST", url, rdr)
			if err != nil {
				log.Fatal(err)
			}
			req.Header.Set("Content-Type", "application/json")
			authheader := getAuthHeader(req, userid, pass, sha256.New, fmt.Sprintf("%d", time.Now().Nanosecond()), "application/json", reqBody)
			req.Header.Set("Authorization", authheader)
			if debug {
				fmt.Printf("DEBUG: sending request\nDEBUG: %+v\nDEBUG: %s\n", req, reqBody)
			}
			resp, err := cli.Do(req)
			if err != nil || resp == nil {
				log.Fatal(err)
			}
			if debug {
				fmt.Printf("DEBUG: received response\nDEBUG: %+v\n", resp)
			}
			defer resp.Body.Close()
			body, err := ioutil.ReadAll(resp.Body)
			if debug {
				fmt.Printf("DEBUG: %s\n", body)
			}
			if resp.StatusCode != http.StatusCreated {
				log.Fatalf("%s %s", resp.Status, body)
			}
			// verify that we got a proper signature response, with a valid signature
			var responses []signatureresponse
			err = json.Unmarshal(body, &responses)
			if err != nil {
				log.Fatal(err)
			}
			if len(requests) != len(responses) {
				log.Fatalf("sent %d signature requests and got %d responses, something's wrong", len(requests), len(responses))
			}
			for i, response := range responses {
				input, err := base64.StdEncoding.DecodeString(requests[i].Input)
				if err != nil {
					log.Fatal(err)
				}
				var (
					sigStatus bool
					sigData   []byte
				)
				switch response.Type {
				case contentsignature.Type:
					sigStatus = verifyContentSignature(input, response, req.URL.RequestURI())
					sig, err := contentsignature.Unmarshal(response.Signature)
					if err != nil {
						log.Fatal(err)
					}
					var sigStr string
					if response.X5U != "" {
						sigStr = "x5u=" + response.X5U + ";"
					} else {
						sigStr = "keyid=" + response.SignerID + ";"
					}
					sigStr += sig.Mode + "=" + response.Signature + "\n"
					sigData = []byte(sigStr)
				case xpi.Type:
					sigStatus = verifyXPI(input, response)
					sigData, err = base64.StdEncoding.DecodeString(response.Signature)
					if err != nil {
						log.Fatal(err)
					}
				case apk.Type:
					sigStatus = verifyAPK(input)
					sigData, err = base64.StdEncoding.DecodeString(response.SignedFile)
					if err != nil {
						log.Fatal(err)
					}
				default:
					log.Fatal("unsupported signature type", response.Type)
				}
				if sigStatus {
					log.Printf("signature %d from signer %q passes", i, response.SignerID)
				} else {
					log.Fatalf("response %d from signer %q does not pass!", i, response.SignerID)
				}
				if outfile != "" {
					err = ioutil.WriteFile(outfile, sigData, 0644)
					if err != nil {
						log.Fatal(err)
					}
					log.Println("response written to", outfile)
				}
			}
			workers--
		}()
	}
	for {
		if workers <= 0 {
			break
		}
		time.Sleep(time.Second)
	}
}

func getAuthHeader(req *http.Request, user, token string, hash func() hash.Hash, ext, contenttype string, payload []byte) string {
	auth := hawk.NewRequestAuth(req,
		&hawk.Credentials{
			ID:   user,
			Key:  token,
			Hash: hash},
		0)
	auth.Ext = ext
	payloadhash := auth.PayloadHash(contenttype)
	payloadhash.Write(payload)
	auth.SetHash(payloadhash)
	return auth.RequestHeader()
}

// verify an ecdsa signature
func verifyContentSignature(input []byte, resp signatureresponse, endpoint string) bool {
	keyBytes, err := base64.StdEncoding.DecodeString(resp.PublicKey)
	if err != nil {
		log.Fatal(err)
	}
	keyInterface, err := x509.ParsePKIXPublicKey(keyBytes)
	if err != nil {
		log.Fatal(err)
	}
	pubKey := keyInterface.(*ecdsa.PublicKey)
	if endpoint == "/sign/data" {
		var templated []byte
		templated = make([]byte, len("Content-Signature:\x00")+len(input))
		copy(templated[:len("Content-Signature:\x00")], []byte("Content-Signature:\x00"))
		copy(templated[len("Content-Signature:\x00"):], input)

		var md hash.Hash
		switch pubKey.Params().Name {
		case "P-256":
			md = sha256.New()
		case "P-384":
			md = sha512.New384()
		case "P-521":
			md = sha512.New()
		default:
			log.Fatalf("unsupported curve algorithm %q", pubKey.Params().Name)
		}
		md.Write(templated)
		input = md.Sum(nil)
	}
	sig, err := contentsignature.Unmarshal(resp.Signature)
	if err != nil {
		log.Fatal(err)
	}
	return ecdsa.Verify(pubKey, input, sig.R, sig.S)
}

func verifyXPI(input []byte, resp signatureresponse) bool {
	sig, err := xpi.Unmarshal(resp.Signature, input)
	if err != nil {
		log.Fatal(err)
	}
	err = sig.VerifyWithChain(nil)
	if err != nil {
		log.Fatal(err)
	}
	return true
}

func verifyAPK(signedAPK []byte) bool {
	zipReader := bytes.NewReader(signedAPK)
	r, err := zip.NewReader(zipReader, int64(len(signedAPK)))
	if err != nil {
		log.Fatal(err)
	}
	var (
		sigstr  string
		sigdata []byte
	)
	for _, f := range r.File {
		switch f.Name {
		case "META-INF/SIGNATURE.SF":
			rc, err := f.Open()
			defer rc.Close()
			if err != nil {
				log.Fatal(err)
			}
			sigdata, err = ioutil.ReadAll(rc)
			if err != nil {
				log.Fatal(err)
			}
		case "META-INF/SIGNATURE.RSA":
			rc, err := f.Open()
			defer rc.Close()
			if err != nil {
				log.Fatal(err)
			}
			rawsig, err := ioutil.ReadAll(rc)
			if err != nil {
				log.Fatal(err)
			}
			sigstr = base64.StdEncoding.EncodeToString(rawsig)
		}
	}
	// convert string format back to signature
	sig, err := apk.Unmarshal(sigstr, sigdata)
	if err != nil {
		log.Fatalf("failed to unmarshal signature: %v", err)
	}
	// verify signature on input data
	if sig.Verify() != nil {
		log.Fatalf("failed to verify apk signature: %v", sig.Verify())
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

const (
	width      = 1200
	height     = 640
	cells      = 200
	xyrange    = 30.0
	xyscale    = width / 2 / xyrange
	multiplier = 0.4
	zscale     = height * multiplier
	angle      = math.Pi / 6
)

var (
	sin30 = math.Sin(angle)
	cos30 = math.Cos(angle)
)

func main() {
	fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
		"style='stroke: green; fill: black; stroke-width: 0.7' "+
		"width='%d' height='%d'>\n", width, height)
	for i := 0; i < cells; i++ {
		for j := 0; j < cells; j++ {
			ax, ay := corner(i+1, j)
			bx, by := corner(i, j)
			cx, cy := corner(i, j+1)
			dx, dy := corner(i+1, j+1)
			fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g'/>\n",
				ax, ay, bx, by, cx, cy, dx, dy)
		}
	}
	fmt.Println("</svg>")
}

func corner(i, j int) (float64, float64) {
	x := xyrange * (float64(i)/cells - 0.5)
	y := xyrange * (float64(j)/cells - 0.5)

	z := f(x, y)

	sx := width/2 + (x-y)*cos30*xyscale
	sy := height/2 + (x+y)*sin30*xyscale - z*zscale

	return sx, sy
}

func f(x, y float64) float64 {
	r := math.Hypot(x, y)

	return math.Sin(r) / r
}
<commit_msg>Preporation for coloring max/min.<commit_after>package main

import (
	"fmt"
	"math"
)

const (
	width      = 600
	height     = 300
	cells      = 100
	xyrange    = 30.0
	xyscale    = width / 2 / xyrange
	multiplier = 0.4
	zscale     = height * multiplier
	angle      = math.Pi / 6
)

var (
	sin30 = math.Sin(angle)
	cos30 = math.Cos(angle)
)

func main() {
	fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+
		"width='%d' height='%d'>\n", width, height)
	for i := 0; i < cells; i++ {
		for j := 0; j < cells; j++ {
			ax, ay := corner(i+1, j)
			bx, by := corner(i, j)
			cx, cy := corner(i, j+1)
			dx, dy := corner(i+1, j+1)
			fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g' "+
				"style='stroke:green; fill:rgb(0,0,0); stroke-width:0.7'/>\n",
				ax, ay, bx, by, cx, cy, dx, dy)
		}
	}
	fmt.Println("</svg>")
}

func corner(i, j int) (float64, float64) {
	x := xyrange * (float64(i)/cells - 0.5)
	y := xyrange * (float64(j)/cells - 0.5)

	z := f(x, y)

	sx := width/2 + (x-y)*cos30*xyscale
	sy := height/2 + (x+y)*sin30*xyscale - z*zscale

	return sx, sy
}

func f(x, y float64) float64 {
	r := math.Hypot(x, y)

	return math.Sin(r) / r
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "crypto/sha256"
)

var pc int

func popCount(x byte) int {
    return int((x & 0x80) >> 7 +
               (x & 0x40) >> 6 +
               (x & 0x20) >> 5 +
               (x & 0x10) >> 4 +
               (x & 0x08) >> 3 +
               (x & 0x04) >> 2 +
               (x & 0x02) >> 1 +
               (x & 0x01))
}

func diff(c1, c2 *[32]byte) int {
    r := 0
    for i := 0; i < len(c1); i++ {
        r += popCount(c1[i] ^ c2[i])
    }
    return r
}

func main() {
    c1 := sha256.Sum256([]byte("x"))
    c2 := sha256.Sum256([]byte("X"))

    fmt.Printf("%d\n", diff(&c1, &c2))
}
<commit_msg>modified ch04/p01_sha256.<commit_after>package main

import (
    "fmt"
    "crypto/sha256"
)

func popCount(x byte) int {
    return int((x & 0x80) >> 7 +
               (x & 0x40) >> 6 +
               (x & 0x20) >> 5 +
               (x & 0x10) >> 4 +
               (x & 0x08) >> 3 +
               (x & 0x04) >> 2 +
               (x & 0x02) >> 1 +
               (x & 0x01))
}

func diff(c1, c2 *[32]byte) int {
    r := 0
    for i := 0; i < len(c1); i++ {
        r += popCount(c1[i] ^ c2[i])
    }
    return r
}

func main() {
    c1 := sha256.Sum256([]byte("x"))
    c2 := sha256.Sum256([]byte("X"))

    fmt.Printf("%d\n", diff(&c1, &c2))
}
<|endoftext|>


<commit_before>package k8s_test

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

	. "github.com/concourse/concourse/topgun"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("Garden Config", func() {

	var (
		garden              Endpoint
		helmDeployTestFlags []string
	)

	BeforeEach(func() {
		setReleaseNameAndNamespace("gc")
	})

	JustBeforeEach(func() {
		deployConcourseChart(releaseName, helmDeployTestFlags...)

		waitAllPodsInNamespaceToBeReady(namespace)

		pods := getPods(namespace, "--selector=app="+releaseName+"-worker")
		Expect(pods).To(HaveLen(1))

		garden = endpointFactory.NewPodEndpoint(
			namespace,
			pods[0].Metadata.Name,
			"7777",
		)
	})

	AfterEach(func() {
		garden.Close()
		cleanup(releaseName, namespace)
	})

	Context("passing a config map location to the worker to be used by gdn", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.additionalVolumes[0].name=garden-config`,
				`--set=worker.additionalVolumes[0].configMap.name=garden-config`,
				`--set=worker.additionalVolumeMounts[0].name=garden-config`,
				`--set=worker.additionalVolumeMounts[0].mountPath=/foo`,
				`--set=concourse.worker.garden.config=/foo/garden-config.ini`,
			}

			configMapCreationArgs := []string{
				"create",
				"configmap",
				"garden-config",
				"--namespace=" + namespace,
				`--from-literal=garden-config.ini=
[server]
  max-containers = 100`,
			}

			Run(nil, "kubectl", "create", "namespace", namespace)
			Run(nil, "kubectl", configMapCreationArgs...)
		})

		It("returns the configured number of max containers", func() {
			Expect(getMaxContainers(garden.Address())).To(Equal(100))
		})
	})

	Context("passing the CONCOURSE_GARDEN_ env vars to the gdn server", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.env[0].name=CONCOURSE_GARDEN_MAX_CONTAINERS`,
				`--set=worker.env[0].value="100"`,
			}
		})

		It("returns the configured number of max containers", func() {
			Expect(getMaxContainers(garden.Address())).To(Equal(100))
		})
	})

	Context("passing the CONCOURSE_GARDEN_DENY_NETWORK env var to the gdn server", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.env[0].name=CONCOURSE_GARDEN_DENY_NETWORK`,
				`--set=worker.env[0].value="8.8.8.8/24"`,
			}
		})

		It("causes requests to the specified IP range to fail", func() {
			atc := waitAndLogin(namespace, releaseName+"-web")
			defer atc.Close()
			buildSession := fly.Start("execute", "-c", "tasks/garden-deny-network.yml")
			<-buildSession.Exited

			Expect(buildSession.ExitCode()).NotTo(Equal(0))
		})
	})

	Context("passing the CONCOURSE_GARDEN_USE_CONTAINERD env var to the gdn server with non existing work dir", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=concourse.worker.garden.useContainerd=true`,
				`--set=concourse.worker.workDir=/dummy-worker-dir`,
			}
		})

		It("creates the worker dir and starts running", func() {
			pods := getPods(namespace, "--selector=app="+releaseName+"-worker")
			Expect(pods).To(HaveLen(1))

			args := []string{"exec", pods[0].Metadata.Name, "-n", releaseName, "ls", "--", "/"}

			session := Start(nil, "kubectl", args...)
			<-session.Exited

			Expect(session.Out).To(gbytes.Say(`dummy-worker-dir`))
			Expect(session.ExitCode()).To(Equal(0))
		})
	})
})

type gardenCap struct {
	MaxContainers int `json:"max_containers"`
}

func getMaxContainers(addr string) int {
	req, err := http.NewRequest("GET", "http://"+addr+"/capacity", nil)
	Expect(err).ToNot(HaveOccurred())

	resp, err := http.DefaultClient.Do(req)
	Expect(err).ToNot(HaveOccurred())

	defer resp.Body.Close()

	gardenCapObject := gardenCap{}

	err = json.NewDecoder(resp.Body).Decode(&gardenCapObject)
	Expect(err).ToNot(HaveOccurred())

	return gardenCapObject.MaxContainers
}
<commit_msg>k8s-topgun: remove containerd test<commit_after>package k8s_test

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

	. "github.com/concourse/concourse/topgun"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Garden Config", func() {

	var (
		garden              Endpoint
		helmDeployTestFlags []string
	)

	BeforeEach(func() {
		setReleaseNameAndNamespace("gc")
	})

	JustBeforeEach(func() {
		deployConcourseChart(releaseName, helmDeployTestFlags...)

		waitAllPodsInNamespaceToBeReady(namespace)

		pods := getPods(namespace, "--selector=app="+releaseName+"-worker")
		Expect(pods).To(HaveLen(1))

		garden = endpointFactory.NewPodEndpoint(
			namespace,
			pods[0].Metadata.Name,
			"7777",
		)
	})

	AfterEach(func() {
		garden.Close()
		cleanup(releaseName, namespace)
	})

	Context("passing a config map location to the worker to be used by gdn", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.additionalVolumes[0].name=garden-config`,
				`--set=worker.additionalVolumes[0].configMap.name=garden-config`,
				`--set=worker.additionalVolumeMounts[0].name=garden-config`,
				`--set=worker.additionalVolumeMounts[0].mountPath=/foo`,
				`--set=concourse.worker.garden.config=/foo/garden-config.ini`,
			}

			configMapCreationArgs := []string{
				"create",
				"configmap",
				"garden-config",
				"--namespace=" + namespace,
				`--from-literal=garden-config.ini=
[server]
  max-containers = 100`,
			}

			Run(nil, "kubectl", "create", "namespace", namespace)
			Run(nil, "kubectl", configMapCreationArgs...)
		})

		It("returns the configured number of max containers", func() {
			Expect(getMaxContainers(garden.Address())).To(Equal(100))
		})
	})

	Context("passing the CONCOURSE_GARDEN_ env vars to the gdn server", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.env[0].name=CONCOURSE_GARDEN_MAX_CONTAINERS`,
				`--set=worker.env[0].value="100"`,
			}
		})

		It("returns the configured number of max containers", func() {
			Expect(getMaxContainers(garden.Address())).To(Equal(100))
		})
	})

	Context("passing the CONCOURSE_GARDEN_DENY_NETWORK env var to the gdn server", func() {
		BeforeEach(func() {
			helmDeployTestFlags = []string{
				`--set=worker.replicas=1`,
				`--set=worker.env[0].name=CONCOURSE_GARDEN_DENY_NETWORK`,
				`--set=worker.env[0].value="8.8.8.8/24"`,
			}
		})

		It("causes requests to the specified IP range to fail", func() {
			atc := waitAndLogin(namespace, releaseName+"-web")
			defer atc.Close()
			buildSession := fly.Start("execute", "-c", "tasks/garden-deny-network.yml")
			<-buildSession.Exited

			Expect(buildSession.ExitCode()).NotTo(Equal(0))
		})
	})
})

type gardenCap struct {
	MaxContainers int `json:"max_containers"`
}

func getMaxContainers(addr string) int {
	req, err := http.NewRequest("GET", "http://"+addr+"/capacity", nil)
	Expect(err).ToNot(HaveOccurred())

	resp, err := http.DefaultClient.Do(req)
	Expect(err).ToNot(HaveOccurred())

	defer resp.Body.Close()

	gardenCapObject := gardenCap{}

	err = json.NewDecoder(resp.Body).Decode(&gardenCapObject)
	Expect(err).ToNot(HaveOccurred())

	return gardenCapObject.MaxContainers
}
<|endoftext|>