<commit_before>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	rest "github.com/emicklei/go-restful"
)

func main() {
	// Create the storage directories on disk
	err := os.MkdirAll(filepath.Join(STORAGEDIR, "files"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the files dir: %v\n", err.Error())
		return
	}
	err = os.MkdirAll(filepath.Join(STORAGEDIR, "meta"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the meta dir: %v\n", err.Error())
		return
	}

	// Create and start the API server
	ws := new(rest.WebService)
	ws.Filter(rest.NoBrowserCacheFilter)
	ws.Route(ws.POST("/branch_create").Consumes("application/x-www-form-urlencoded").To(branchCreate))
	ws.Route(ws.GET("/branch_history").To(branchHistory))
	ws.Route(ws.GET("/branch_list").To(branchList))
	ws.Route(ws.POST("/branch_remove").Consumes("application/x-www-form-urlencoded").To(branchRemove))
	ws.Route(ws.PUT("/db_upload").To(dbUpload))
	ws.Route(ws.GET("/db_download").To(dbDownload))
	ws.Route(ws.GET("/db_list").To(dbList))
	rest.Add(ws)
	http.ListenAndServe(":8080", nil)
}

// Creates a new branch for a database.
// Can be tested with: curl -d database=a.db -d from-branch=master -d new-branch=mynewbranch http://localhost:8080/branch_create
func branchCreate(r *rest.Request, w *rest.Response) {
	// We do this such that a branch can only fork from an existing branch head of the database. The alternative
	// would be to allow giving a direct commit ID for branching from, but that seems like it would be a security
	// problem due to being able to potentially point at other people's commits in our multi-user environment

	// Retrieve the database and branch names
	err := r.Request.ParseForm()
	if err != nil {
		w.WriteErrorString(http.StatusBadRequest, err.Error())
		return
	}
	dbName := r.Request.FormValue("database")
	fromBranch := r.Request.FormValue("from-branch")
	newBranch := r.Request.FormValue("new-branch")

	// Sanity check the inputs
	if dbName == "" || fromBranch == "" || newBranch == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the "from" branch exists in the database
	fromId, ok := branches[fromBranch]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Ensure the new branch doesn't already exist in the database
	_, ok = branches[newBranch]
	if ok {
		w.WriteHeader(http.StatusConflict)
		return
	}

	// Add the new branch
	branches[newBranch] = fromId
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// Returns the history for a branch.
// Can be tested with: curl -H "Database: a.db" -H "Branch: master" http://localhost:8080/branch_history
func branchHistory(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Database")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the requested branch exists in the database
	id, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Walk the commit history, assembling it into something useful
	var history []commit
	c, err := getCommit(id)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	history = append(history, c)
	for c.Parent != "" {
		c, err = getCommit(c.Parent)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		history = append(history, c)
	}
	w.WriteAsJson(history)
}

// Returns the list of branch heads for a database.
// Can be tested with: curl -H "Database: a.db" http://localhost:8080/branch_list
func branchList(r *rest.Request, w *rest.Response) {
	// Retrieve the database name
	dbName := r.Request.Header.Get("Database")

	// TODO: Validate the database name

	// Sanity check the input
	if dbName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Return the list of branch heads
	w.WriteAsJson(branches)
}

// Removes a branch from a database.
// Can be tested with: curl -d database=a.db -d branch=master http://localhost:8080/branch_remove
func branchRemove(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	err := r.Request.ParseForm()
	if err != nil {
		w.WriteErrorString(http.StatusBadRequest, err.Error())
		return
	}
	dbName := r.Request.FormValue("database")
	branchName := r.Request.FormValue("branch")

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the branch exists in the database
	_, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Remove the branch
	delete(branches, branchName)
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// Upload a database.
// Can be tested with: curl -T a.db -H "Name: a.db" -w \%{response_code} -D headers.out http://localhost:8080/db_upload
func dbUpload(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Name")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Default to "master" if no branch name was given
	if branchName == "" {
		branchName = "master"
	}

	// Read the database into a buffer
	var buf bytes.Buffer
	buf.ReadFrom(r.Request.Body)
	sha := sha256.Sum256(buf.Bytes())

	// Create a dbTree entry for the individual database file
	var e dbTreeEntry
	e.AType = DATABASE
	e.Sha256 = hex.EncodeToString(sha[:])
	e.Name = dbName
	e.Last_Modified = time.Now()
	e.Size = buf.Len()

	// Create a dbTree structure for the database entry
	var t dbTree
	t.Entries = append(t.Entries, e)
	t.ID = createDBTreeID(t.Entries)

	// Construct a commit structure pointing to the tree
	var c commit
	c.AuthorEmail = "justin@postgresql.org" // TODO: Author and Committer info should come from the client, so we
	c.AuthorName = "Justin Clift"           // TODO  hard code these for now.  Proper auth will need adding later
	c.Timestamp = time.Now()                // TODO: Would it be better to accept a timestamp from the client?
	c.Tree = t.ID

	// Check if the database already exists
	var err error
	var branches map[string]string
	if dbExists(dbName) {
		// Load the existing branchHeads from disk
		branches, err = getBranches(dbName)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// We check if the desired branch already exists.  If it does, we use the commit ID from that as the
		// "parent" for our new commit.  Then we update the branch with the commit created for this new
		// database upload
		if id, ok := branches[branchName]; ok {
			c.Parent = id
		}
		c.ID = createCommitID(c)
		branches[branchName] = c.ID
	} else {
		// No existing branches, so this will be the first
		c.ID = createCommitID(c)
		branches = make(map[string]string)
		branches[branchName] = c.ID
	}

	// Write the database to disk
	err = storeDatabase(buf.Bytes())
	if err != nil {
		log.Printf("Error when writing database '%s' to disk: %v\n", dbName, err.Error())

		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the tree to disk
	err = storeTree(t)
	if err != nil {
		log.Printf("Something went wrong when storing the tree file: %v\n", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the commit to disk
	err = storeCommit(c)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the updated branch heads to disk
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Log the upload
	log.Printf("Database uploaded.  Name: '%s', size: %d bytes, branch: '%s'\n", dbName, buf.Len(),
		branchName)

	// Send a 201 "Created" response, along with the location of the URL for working with the (new) database
	w.AddHeader("Location", "/"+dbName)
	w.WriteHeader(http.StatusCreated)
}

// Download a database
func dbDownload(r *rest.Request, w *rest.Response) {
	log.Println("dbDownload() called")
}

// Get a list of databases
func dbList(r *rest.Request, w *rest.Response) {
	log.Println("dbList() called")
}
<commit_msg>Branch creation now takes a commit ID instead<commit_after>package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"time"

	rest "github.com/emicklei/go-restful"
)

func main() {
	// Create the storage directories on disk
	err := os.MkdirAll(filepath.Join(STORAGEDIR, "files"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the files dir: %v\n", err.Error())
		return
	}
	err = os.MkdirAll(filepath.Join(STORAGEDIR, "meta"), os.ModeDir|0755)
	if err != nil {
		log.Printf("Something went wrong when creating the meta dir: %v\n", err.Error())
		return
	}

	// Create and start the API server
	ws := new(rest.WebService)
	ws.Filter(rest.NoBrowserCacheFilter)
	ws.Route(ws.POST("/branch_create").Consumes("application/x-www-form-urlencoded").To(branchCreate))
	ws.Route(ws.GET("/branch_history").To(branchHistory))
	ws.Route(ws.GET("/branch_list").To(branchList))
	ws.Route(ws.POST("/branch_remove").Consumes("application/x-www-form-urlencoded").To(branchRemove))
	ws.Route(ws.PUT("/db_upload").To(dbUpload))
	ws.Route(ws.GET("/db_download").To(dbDownload))
	ws.Route(ws.GET("/db_list").To(dbList))
	rest.Add(ws)
	http.ListenAndServe(":8080", nil)
}

// Creates a new branch for a database.
// Can be tested with: curl -d database=a.db -d branch=master -d commit=xxx http://localhost:8080/branch_create
func branchCreate(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	err := r.Request.ParseForm()
	if err != nil {
		w.WriteErrorString(http.StatusBadRequest, err.Error())
		return
	}
	dbName := r.Request.FormValue("database")
	branchName := r.Request.FormValue("branch")
	commit := r.Request.FormValue("commit")

	// Sanity check the inputs
	if dbName == "" || branchName == "" || commit == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the new branch name doesn't already exist in the database
	_, ok := branches[branchName]
	if ok {
		w.WriteHeader(http.StatusConflict)
		return
	}

	// Ensure the requested commit exists in the database history
	// This is important, because if we didn't do it then people could supply any commit ID.  Even one's belonging
	// to completely unrelated databases, which they shouldn't have access to.
	// By ensuring the requested commit is already part of the existing database history, we solve that problem.
	commitExists := false
	for _, ID := range branches {
		// Because there seems to be no valid way of adding this condition in the loop declaration?
		// Do I just need more coffee? :D
		if commitExists == true {
			continue
		}

		// Check if the head commit of the branch matches the requested commit
		if ID == commit {
			commitExists = true
			continue
		}

		// It didn't, so walk the commit history looking for the commit there
		c, err := getCommit(ID)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		for c.Parent != "" {
			if c.ID == commit {
				// This commit in the history matches the requested commit, so we're good
				commitExists = true
			}
			c, err = getCommit(c.Parent)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}
		}
	}

	// The commit wasn't found, so don't create the new branch
	if commitExists != true {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Create the new branch
	branches[branchName] = commit
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// Returns the history for a branch.
// Can be tested with: curl -H "Database: a.db" -H "Branch: master" http://localhost:8080/branch_history
func branchHistory(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Database")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the requested branch exists in the database
	id, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Walk the commit history, assembling it into something useful
	var history []commit
	c, err := getCommit(id)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	history = append(history, c)
	for c.Parent != "" {
		c, err = getCommit(c.Parent)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		history = append(history, c)
	}
	w.WriteAsJson(history)
}

// Returns the list of branch heads for a database.
// Can be tested with: curl -H "Database: a.db" http://localhost:8080/branch_list
func branchList(r *rest.Request, w *rest.Response) {
	// Retrieve the database name
	dbName := r.Request.Header.Get("Database")

	// TODO: Validate the database name

	// Sanity check the input
	if dbName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Return the list of branch heads
	w.WriteAsJson(branches)
}

// Removes a branch from a database.
// Can be tested with: curl -d database=a.db -d branch=master http://localhost:8080/branch_remove
func branchRemove(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	err := r.Request.ParseForm()
	if err != nil {
		w.WriteErrorString(http.StatusBadRequest, err.Error())
		return
	}
	dbName := r.Request.FormValue("database")
	branchName := r.Request.FormValue("branch")

	// Sanity check the inputs
	if dbName == "" || branchName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// TODO: Validate the database and branch names

	// Ensure the requested database is in our system
	if !dbExists(dbName) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Load the existing branch heads from disk
	branches, err := getBranches(dbName)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Ensure the branch exists in the database
	_, ok := branches[branchName]
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Remove the branch
	delete(branches, branchName)
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// Upload a database.
// Can be tested with: curl -T a.db -H "Name: a.db" -w \%{response_code} -D headers.out http://localhost:8080/db_upload
func dbUpload(r *rest.Request, w *rest.Response) {
	// Retrieve the database and branch names
	dbName := r.Request.Header.Get("Name")
	branchName := r.Request.Header.Get("Branch")

	// TODO: Validate the database and branch names

	// Sanity check the inputs
	if dbName == "" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Default to "master" if no branch name was given
	if branchName == "" {
		branchName = "master"
	}

	// Read the database into a buffer
	var buf bytes.Buffer
	buf.ReadFrom(r.Request.Body)
	sha := sha256.Sum256(buf.Bytes())

	// Create a dbTree entry for the individual database file
	var e dbTreeEntry
	e.AType = DATABASE
	e.Sha256 = hex.EncodeToString(sha[:])
	e.Name = dbName
	e.Last_Modified = time.Now()
	e.Size = buf.Len()

	// Create a dbTree structure for the database entry
	var t dbTree
	t.Entries = append(t.Entries, e)
	t.ID = createDBTreeID(t.Entries)

	// Construct a commit structure pointing to the tree
	var c commit
	c.AuthorEmail = "justin@postgresql.org" // TODO: Author and Committer info should come from the client, so we
	c.AuthorName = "Justin Clift"           // TODO  hard code these for now.  Proper auth will need adding later
	c.Timestamp = time.Now()                // TODO: Would it be better to accept a timestamp from the client?
	c.Tree = t.ID

	// Check if the database already exists
	var err error
	var branches map[string]string
	if dbExists(dbName) {
		// Load the existing branchHeads from disk
		branches, err = getBranches(dbName)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// We check if the desired branch already exists.  If it does, we use the commit ID from that as the
		// "parent" for our new commit.  Then we update the branch with the commit created for this new
		// database upload
		if id, ok := branches[branchName]; ok {
			c.Parent = id
		}
		c.ID = createCommitID(c)
		branches[branchName] = c.ID
	} else {
		// No existing branches, so this will be the first
		c.ID = createCommitID(c)
		branches = make(map[string]string)
		branches[branchName] = c.ID
	}

	// Write the database to disk
	err = storeDatabase(buf.Bytes())
	if err != nil {
		log.Printf("Error when writing database '%s' to disk: %v\n", dbName, err.Error())

		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the tree to disk
	err = storeTree(t)
	if err != nil {
		log.Printf("Something went wrong when storing the tree file: %v\n", err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the commit to disk
	err = storeCommit(c)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the updated branch heads to disk
	err = storeBranches(dbName, branches)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Log the upload
	log.Printf("Database uploaded.  Name: '%s', size: %d bytes, branch: '%s'\n", dbName, buf.Len(),
		branchName)

	// Send a 201 "Created" response, along with the location of the URL for working with the (new) database
	w.AddHeader("Location", "/"+dbName)
	w.WriteHeader(http.StatusCreated)
}

// Download a database
func dbDownload(r *rest.Request, w *rest.Response) {
	log.Println("dbDownload() called")
}

// Get a list of databases
func dbList(r *rest.Request, w *rest.Response) {
	log.Println("dbList() called")
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Eliott Teissonniere

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package api

import (
	"net/http"
	"github.com/gin-gonic/gin"

	"github.com/Bit-Nation/BITNATION-Panthalassa/repo"
	"github.com/Bit-Nation/BITNATION-Panthalassa/tracker"
)

type API struct {
	Repo    repo.LedgerInterface
	Tracker tracker.Tracker

	listen_address string
	r              *gin.Engine
}

func doResult(c *gin.Context, value interface{}, err error) {
	if  err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	} else if value == "" {
		c.JSON(http.StatusNotFound, nil)
	} else {
		c.JSON(http.StatusOK, value)
	}
}

func NewAPI(listen string, rep repo.LedgerInterface, track tracker.Tracker) API {
	a := API{Repo: rep, Tracker: track}
	a.listen_address = listen

	a.r = gin.Default()

	// Build the router api
	a.r.GET("/:version/sync", a.sync)

	// Messages
	a.r.GET("/:version/messages/:user/:seq", a.getMessage)
	//a.r.GET("/messages/:user/last", a.getLastSeq) Do we need to expose a method to retrieve last sequence?
	a.r.GET("/:version/messages/:user", a.getFeed)

	// Profiles
	a.r.GET("/:version/profiles/", a.me)
	a.r.GET("/:version/profiles/:user", a.about)

	// a.r.POST("/:version/profiles", a.setAbout)

	// Social actions
	a.r.GET("/:version/follow/:user", a.follow)
	a.r.DELETE("/:version/follow/:user", a.unFollow)
	//TODO: Add limit and offset as parameter
	a.r.GET("/:version/following", a.getFollowing)

	// Publishing
	a.r.POST("/:version/publish", a.publish)
	a.r.POST("/:version/upload", a.upload)
	a.r.POST("/:version/download/:id", a.download)

	return a
}

func (a *API) Run() error {
	return a.r.Run(a.listen_address)
}

func (a *API) sync(c *gin.Context) {
	var err error = nil
	//Ignore ipfs sync when running tests
	err = a.Repo.Sync()

	doResult(c, nil, err)
}

func (a *API) getMessage(c *gin.Context) {
	user := c.Params.ByName("user")
	seq := c.Params.ByName("seq")

	msg, err := a.Repo.GetMessage(user, seq)

	doResult(c, msg, err)
}

func (a *API) getLastSeq(c *gin.Context) {
	user := c.Params.ByName("user")

	seq, err := a.Repo.GetLastSeq(user)

	doResult(c, seq, err)
}

func (a *API) getFeed(c *gin.Context) {
	user := c.Params.ByName("user")

	feed, err := a.Repo.GetFeed(user)

	doResult(c, feed, err)
}

func (a *API) me(c *gin.Context) {
	id := a.Repo.Whoami()

	doResult(c, id, nil)
}

func (a *API) about(c *gin.Context) {
	user := c.Params.ByName("user")

	about, err := a.Repo.About(user)

	doResult(c, about, err)
}

func (a *API) setAbout(c *gin.Context) {
	about := repo.About{}

	about.Pseudo = c.PostForm("pseudo")
	about.Image = c.PostForm("image")
	about.ETHAddress = c.PostForm("eth_address")
	about.Description = c.PostForm("description")

	err := a.Repo.SetAbout(about)

	doResult(c, about, err)
}

func (a *API) follow(c *gin.Context) {
	user := c.Params.ByName("user")

	err := a.Tracker.Follow(user)

	doResult(c, nil, err)
}

func (a *API) unFollow(c *gin.Context) {
	user := c.Params.ByName("user")

	err := a.Tracker.UnFollow(user)

	doResult(c, nil, err)
}

func (a *API) getFollowing(c *gin.Context) {
	followed, err := a.Tracker.GetUsersFollowed()

	doResult(c, followed, err)
}

func (a *API) publish(c *gin.Context) {
	data := c.PostForm("data")

	err := a.Repo.Publish(data)

	doResult(c, nil, err)
}

func (a *API) upload(c *gin.Context) {
	data := c.PostForm("data_b64")

	id, err := a.Repo.AddRessource(data)

	doResult(c, id, err)

}

func (a *API) download(c *gin.Context) {
	id := c.Params.ByName("id")

	data, err := a.Repo.GetRessource(id)

	doResult(c, data, err)
}
<commit_msg>[api] Missing uncomment of profiles function<commit_after>/*
Copyright 2017 Eliott Teissonniere

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package api

import (
	"net/http"
	"github.com/gin-gonic/gin"

	"github.com/Bit-Nation/BITNATION-Panthalassa/repo"
	"github.com/Bit-Nation/BITNATION-Panthalassa/tracker"
)

type API struct {
	Repo    repo.LedgerInterface
	Tracker tracker.Tracker

	listen_address string
	r              *gin.Engine
}

func doResult(c *gin.Context, value interface{}, err error) {
	if  err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	} else if value == "" {
		c.JSON(http.StatusNotFound, nil)
	} else {
		c.JSON(http.StatusOK, value)
	}
}

func NewAPI(listen string, rep repo.LedgerInterface, track tracker.Tracker) API {
	a := API{Repo: rep, Tracker: track}
	a.listen_address = listen

	a.r = gin.Default()

	// Build the router api
	a.r.GET("/:version/sync", a.sync)

	// Messages
	a.r.GET("/:version/messages/:user/:seq", a.getMessage)
	//a.r.GET("/messages/:user/last", a.getLastSeq) Do we need to expose a method to retrieve last sequence?
	a.r.GET("/:version/messages/:user", a.getFeed)

	// Profiles
	a.r.GET("/:version/profiles/", a.me)
	a.r.GET("/:version/profiles/:user", a.about)

	a.r.POST("/:version/profiles", a.setAbout)

	// Social actions
	a.r.GET("/:version/follow/:user", a.follow)
	a.r.DELETE("/:version/follow/:user", a.unFollow)
	//TODO: Add limit and offset as parameter
	a.r.GET("/:version/following", a.getFollowing)

	// Publishing
	a.r.POST("/:version/publish", a.publish)
	a.r.POST("/:version/upload", a.upload)
	a.r.POST("/:version/download/:id", a.download)

	return a
}

func (a *API) Run() error {
	return a.r.Run(a.listen_address)
}

func (a *API) sync(c *gin.Context) {
	var err error = nil
	//Ignore ipfs sync when running tests
	err = a.Repo.Sync()

	doResult(c, nil, err)
}

func (a *API) getMessage(c *gin.Context) {
	user := c.Params.ByName("user")
	seq := c.Params.ByName("seq")

	msg, err := a.Repo.GetMessage(user, seq)

	doResult(c, msg, err)
}

func (a *API) getLastSeq(c *gin.Context) {
	user := c.Params.ByName("user")

	seq, err := a.Repo.GetLastSeq(user)

	doResult(c, seq, err)
}

func (a *API) getFeed(c *gin.Context) {
	user := c.Params.ByName("user")

	feed, err := a.Repo.GetFeed(user)

	doResult(c, feed, err)
}

func (a *API) me(c *gin.Context) {
	id := a.Repo.Whoami()

	doResult(c, id, nil)
}

func (a *API) about(c *gin.Context) {
	user := c.Params.ByName("user")

	about, err := a.Repo.About(user)

	doResult(c, about, err)
}

func (a *API) setAbout(c *gin.Context) {
	about := repo.About{}

	about.Pseudo = c.PostForm("pseudo")
	about.Image = c.PostForm("image")
	about.ETHAddress = c.PostForm("eth_address")
	about.Description = c.PostForm("description")

	err := a.Repo.SetAbout(about)

	doResult(c, about, err)
}

func (a *API) follow(c *gin.Context) {
	user := c.Params.ByName("user")

	err := a.Tracker.Follow(user)

	doResult(c, nil, err)
}

func (a *API) unFollow(c *gin.Context) {
	user := c.Params.ByName("user")

	err := a.Tracker.UnFollow(user)

	doResult(c, nil, err)
}

func (a *API) getFollowing(c *gin.Context) {
	followed, err := a.Tracker.GetUsersFollowed()

	doResult(c, followed, err)
}

func (a *API) publish(c *gin.Context) {
	data := c.PostForm("data")

	err := a.Repo.Publish(data)

	doResult(c, nil, err)
}

func (a *API) upload(c *gin.Context) {
	data := c.PostForm("data_b64")

	id, err := a.Repo.AddRessource(data)

	doResult(c, id, err)

}

func (a *API) download(c *gin.Context) {
	id := c.Params.ByName("id")

	data, err := a.Repo.GetRessource(id)

	doResult(c, data, err)
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"

	"time"

	rice "github.com/GeertJohan/go.rice"
	"github.com/Sirupsen/logrus"
	"github.com/hyperhq/hyperd/client"
	"github.com/hyperhq/hyperd/client/api"
	"github.com/kelseyhightower/envconfig"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/robfig/cron"
)

type ApiConfig struct {
	Env        string `default:"development"`
	Addr       string `default:":7842"`
	TlsCert    string
	TlsKey     string
	AutoTls    bool
	HyperProto string `default:"unix"`
	HyperAddr  string `default:"/var/run/hyper.sock"`
	RCSitekey  string
	RCSecret   string
}

func (a *ApiConfig) Debug() bool {
	return a.Env != "production"
}

type Api struct {
	Log         *logrus.Logger
	Config      *ApiConfig
	Echo        *echo.Echo
	Images      *[]Image
	Hyper       *api.Client
	HyperClient *client.HyperClient
	Cron        *cron.Cron
}

func New() *Api {

	// -- Logging

	Log := logrus.New()

	// -- Configuration

	var Config ApiConfig
	if err := envconfig.Process("termbox", &Config); err != nil {
		Log.Fatal(err)
	}

	if Config.Debug() {
		Log.Level = logrus.DebugLevel
	}

	// -- Echo

	Echo := echo.New()
	Echo.Debug = Config.Debug()

	assetHandler := http.FileServer(rice.MustFindBox("../app").HTTPBox())
	Echo.GET("/app/*", echo.WrapHandler(http.StripPrefix("/app/", assetHandler)))
	// fonts are still loaded from /jspm_packages/..
	Echo.GET("/jspm_packages/*", echo.WrapHandler(assetHandler))

	funcs := template.FuncMap{
		"marshal": func(v interface{}) template.JS {
			a, _ := json.Marshal(v)
			return template.JS(a)
		},
	}

	templates := rice.MustFindBox("./views")
	index, _ := templates.String("index.html")
	Echo.Renderer = &Template{
		templates: template.Must(template.New("index").Funcs(funcs).Parse(index)),
	}

	if !Config.Debug() {
		Echo.Use(middleware.Gzip())
	}

	// -- Images

	dat, err := rice.MustFindBox("../images").Bytes("images.json")
	if err != nil {
		Log.Fatal(err)
	}

	var Images []Image
	if err := json.Unmarshal([]byte(dat), &Images); err != nil {
		Log.Fatal(err)
	}

	// -- Hyper

	Hyper := api.NewClient(Config.HyperProto, Config.HyperAddr, nil)

	HyperClient := client.NewHyperClient(Config.HyperProto, Config.HyperAddr, nil)

	// -- Cron

	Cron := cron.New()
	Cron.AddFunc("@every 10m", func() {
		remoteInfo, err := Hyper.List("pod", "", "", true)
		if err != nil {
			Log.Error(err)
			return
		}

		for _, podData := range remoteInfo.GetList("podData") {
			fields := strings.Split(podData, ":")
			podID, podName := fields[0], fields[1]

			if podName != "termbox" {
				continue
			}

			podInfo, err := Hyper.GetPodInfo(podID)
			if err != nil {
				Log.Error(err)
				continue
			}

			if (time.Now().Unix() - podInfo.CreatedAt) > 10800 {
				//if time.Duration(time.Now().Unix()-podInfo.CreatedAt) > time.Hour*6 {
				if err := Hyper.RmPod(podID); err != nil {
					Log.Error(err)
					continue
				}
				Log.Info("Deleted ", podID)
			}

		}
	})

	Cron.AddFunc("@daily", func() {
		for _, image := range Images {
			for _, version := range image.Versions {
				imageName := fmt.Sprintf("%s:%s", image.Image, version)
				Log.Info("Pulling image ", imageName)
				if err := HyperClient.PullImage(imageName); err != nil {
					Log.Error(err)
				}
			}
		}
	})

	// -- Api

	a := &Api{Log, &Config, Echo, &Images, Hyper, HyperClient, Cron}

	Echo.POST("/boxes", a.CreateBox)
	Echo.GET("/boxes/:id/exec", a.ExecBox)
	Echo.GET("/", func(c echo.Context) error { return c.Render(http.StatusOK, "index", a) })

	return a
}

func (a *Api) Run() {
	a.Echo.HTTPErrorHandler = func(err error, c echo.Context) {
		httpError, ok := err.(*echo.HTTPError)
		if ok {
			errorCode := httpError.Code
			switch errorCode {
			case http.StatusNotFound:
				// Render index in case of 404 and let the frontend take over
				if err := c.Render(http.StatusOK, "index", a); err != nil {
					a.Log.Error(err)
				}
				return
			}
		}
		a.Log.Info(err)
		a.Echo.DefaultHTTPErrorHandler(err, c)
	}

	a.Cron.Start()

	var err error

	if a.Config.AutoTls {
		err = a.Echo.StartAutoTLS(a.Config.Addr)
	} else if a.Config.TlsCert != "" && a.Config.TlsKey != "" {
		err = a.Echo.StartTLS(a.Config.Addr, a.Config.TlsCert, a.Config.TlsKey)
	} else {
		err = a.Echo.Start(a.Config.Addr)
	}

	if err != nil {
		a.Log.Fatal(err)
	}
}

type Template struct {
	templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}
<commit_msg>ok reddit, 1h only<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"

	"time"

	rice "github.com/GeertJohan/go.rice"
	"github.com/Sirupsen/logrus"
	"github.com/hyperhq/hyperd/client"
	"github.com/hyperhq/hyperd/client/api"
	"github.com/kelseyhightower/envconfig"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/robfig/cron"
)

type ApiConfig struct {
	Env        string `default:"development"`
	Addr       string `default:":7842"`
	TlsCert    string
	TlsKey     string
	AutoTls    bool
	HyperProto string `default:"unix"`
	HyperAddr  string `default:"/var/run/hyper.sock"`
	RCSitekey  string
	RCSecret   string
}

func (a *ApiConfig) Debug() bool {
	return a.Env != "production"
}

type Api struct {
	Log         *logrus.Logger
	Config      *ApiConfig
	Echo        *echo.Echo
	Images      *[]Image
	Hyper       *api.Client
	HyperClient *client.HyperClient
	Cron        *cron.Cron
}

func New() *Api {

	// -- Logging

	Log := logrus.New()

	// -- Configuration

	var Config ApiConfig
	if err := envconfig.Process("termbox", &Config); err != nil {
		Log.Fatal(err)
	}

	if Config.Debug() {
		Log.Level = logrus.DebugLevel
	}

	// -- Echo

	Echo := echo.New()
	Echo.Debug = Config.Debug()

	assetHandler := http.FileServer(rice.MustFindBox("../app").HTTPBox())
	Echo.GET("/app/*", echo.WrapHandler(http.StripPrefix("/app/", assetHandler)))
	// fonts are still loaded from /jspm_packages/..
	Echo.GET("/jspm_packages/*", echo.WrapHandler(assetHandler))

	funcs := template.FuncMap{
		"marshal": func(v interface{}) template.JS {
			a, _ := json.Marshal(v)
			return template.JS(a)
		},
	}

	templates := rice.MustFindBox("./views")
	index, _ := templates.String("index.html")
	Echo.Renderer = &Template{
		templates: template.Must(template.New("index").Funcs(funcs).Parse(index)),
	}

	if !Config.Debug() {
		Echo.Use(middleware.Gzip())
	}

	// -- Images

	dat, err := rice.MustFindBox("../images").Bytes("images.json")
	if err != nil {
		Log.Fatal(err)
	}

	var Images []Image
	if err := json.Unmarshal([]byte(dat), &Images); err != nil {
		Log.Fatal(err)
	}

	// -- Hyper

	Hyper := api.NewClient(Config.HyperProto, Config.HyperAddr, nil)

	HyperClient := client.NewHyperClient(Config.HyperProto, Config.HyperAddr, nil)

	// -- Cron

	Cron := cron.New()
	Cron.AddFunc("@every 10m", func() {
		remoteInfo, err := Hyper.List("pod", "", "", true)
		if err != nil {
			Log.Error(err)
			return
		}

		for _, podData := range remoteInfo.GetList("podData") {
			fields := strings.Split(podData, ":")
			podID, podName := fields[0], fields[1]

			if podName != "termbox" {
				continue
			}

			podInfo, err := Hyper.GetPodInfo(podID)
			if err != nil {
				Log.Error(err)
				continue
			}

			if (time.Now().Unix() - podInfo.CreatedAt) > 3600 {
				if err := Hyper.RmPod(podID); err != nil {
					Log.Error(err)
					continue
				}
				Log.Info("Deleted ", podID)
			}

		}
	})

	Cron.AddFunc("@daily", func() {
		for _, image := range Images {
			for _, version := range image.Versions {
				imageName := fmt.Sprintf("%s:%s", image.Image, version)
				Log.Info("Pulling image ", imageName)
				if err := HyperClient.PullImage(imageName); err != nil {
					Log.Error(err)
				}
			}
		}
	})

	// -- Api

	a := &Api{Log, &Config, Echo, &Images, Hyper, HyperClient, Cron}

	Echo.POST("/boxes", a.CreateBox)
	Echo.GET("/boxes/:id/exec", a.ExecBox)
	Echo.GET("/", func(c echo.Context) error { return c.Render(http.StatusOK, "index", a) })

	return a
}

func (a *Api) Run() {
	a.Echo.HTTPErrorHandler = func(err error, c echo.Context) {
		httpError, ok := err.(*echo.HTTPError)
		if ok {
			errorCode := httpError.Code
			switch errorCode {
			case http.StatusNotFound:
				// Render index in case of 404 and let the frontend take over
				if err := c.Render(http.StatusOK, "index", a); err != nil {
					a.Log.Error(err)
				}
				return
			}
		}
		a.Log.Info(err)
		a.Echo.DefaultHTTPErrorHandler(err, c)
	}

	a.Cron.Start()

	var err error

	if a.Config.AutoTls {
		err = a.Echo.StartAutoTLS(a.Config.Addr)
	} else if a.Config.TlsCert != "" && a.Config.TlsKey != "" {
		err = a.Echo.StartTLS(a.Config.Addr, a.Config.TlsCert, a.Config.TlsKey)
	} else {
		err = a.Echo.Start(a.Config.Addr)
	}

	if err != nil {
		a.Log.Fatal(err)
	}
}

type Template struct {
	templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}
<|endoftext|>


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

package api

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

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/api/context"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/log"
	"golang.org/x/net/websocket"
)

func addLogs(ws *websocket.Conn) {
	var err error
	defer func() {
		data := map[string]interface{}{}
		if err != nil {
			data["error"] = err.Error()
			log.Error(err.Error())
		} else {
			data["error"] = nil
		}
		msg, _ := json.Marshal(data)
		ws.Write(msg)
		ws.Close()
	}()
	req := ws.Request()
	t := context.GetAuthToken(req)
	if t == nil {
		err = fmt.Errorf("wslogs: no token")
		return
	}
	if t.GetAppName() != app.InternalAppName {
		err = fmt.Errorf("wslogs: invalid token app name: %q", t.GetAppName())
		return
	}
	err = scanLogs(ws)
	if err != nil {
		return
	}
}

func scanLogs(stream io.Reader) error {
	queueSize, _ := config.GetInt("server:app-log-buffer-size")
	if queueSize == 0 {
		queueSize = 500000
	}
	dispatcher := app.NewlogDispatcher(queueSize, runtime.NumCPU())
	decoder := json.NewDecoder(stream)
	for {
		var entry app.Applog
		err := decoder.Decode(&entry)
		if err != nil {
			if err == io.EOF {
				break
			}
			dispatcher.Stop()
			return fmt.Errorf("wslogs: parsing log line: %s", err)
		}
		dispatcher.Send(&entry)
	}
	dispatcher.Stop()
	return nil
}
<commit_msg>Simplify err receive<commit_after>// Copyright 2016 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package api

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

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/api/context"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/log"
	"golang.org/x/net/websocket"
)

func addLogs(ws *websocket.Conn) {
	var err error
	defer func() {
		msg := &errMsg{}
		if err != nil {
			msg.Error = err.Error()
			log.Error(err.Error())
		}
		websocket.JSON.Send(ws, msg)
		ws.Close()
	}()
	req := ws.Request()
	t := context.GetAuthToken(req)
	if t == nil {
		err = fmt.Errorf("wslogs: no token")
		return
	}
	if t.GetAppName() != app.InternalAppName {
		err = fmt.Errorf("wslogs: invalid token app name: %q", t.GetAppName())
		return
	}
	err = scanLogs(ws)
	if err != nil {
		return
	}
}

func scanLogs(stream io.Reader) error {
	queueSize, _ := config.GetInt("server:app-log-buffer-size")
	if queueSize == 0 {
		queueSize = 500000
	}
	dispatcher := app.NewlogDispatcher(queueSize, runtime.NumCPU())
	decoder := json.NewDecoder(stream)
	for {
		var entry app.Applog
		err := decoder.Decode(&entry)
		if err != nil {
			if err == io.EOF {
				break
			}
			dispatcher.Stop()
			return fmt.Errorf("wslogs: parsing log line: %s", err)
		}
		dispatcher.Send(&entry)
	}
	dispatcher.Stop()
	return nil
}

type errMsg struct {
	Error string `json:"error"`
}
<|endoftext|>


<commit_before>package version_test

import (
	"."
	"labix.org/v2/mgo/bson"
	. "launchpad.net/gocheck"
	"strings"
	"testing"
)

type suite struct{}

var _ = Suite(suite{})

func Test(t *testing.T) {
	TestingT(t)
}

// N.B. The FORCE-VERSION logic is tested in the environs package.

var cmpTests = []struct {
	v1, v2 string
	less   bool
	eq     bool
}{
	{"1.0.0", "1.0.0", false, true},
	{"01.0.0", "1.0.0", false, true},
	{"10.0.0", "9.0.0", false, false},
	{"1.0.0", "1.0.1", true, false},
	{"1.0.1", "1.0.0", false, false},
	{"1.0.0", "1.1.0", true, false},
	{"1.1.0", "1.0.0", false, false},
	{"1.0.0", "2.0.0", true, false},
	{"2.0.0", "1.0.0", false, false},
	{"2.0.0.0", "2.0.0", false, true},
	{"2.0.0.0", "2.0.0.0", false, true},
	{"2.0.0.1", "2.0.0.0", false, false},
	{"2.0.1.10", "2.0.0.0", false, false},
}

func (suite) TestComparison(c *C) {
	for i, test := range cmpTests {
		c.Logf("test %d", i)
		v1, err := version.Parse(test.v1)
		c.Assert(err, IsNil)
		v2, err := version.Parse(test.v2)
		c.Assert(err, IsNil)
		less := v1.Less(v2)
		gt := v2.Less(v1)
		c.Check(less, Equals, test.less)
		if test.eq {
			c.Check(gt, Equals, false)
		} else {
			c.Check(gt, Equals, !test.less)
		}
	}
}

var parseTests = []struct {
	v      string
	err    string
	expect version.Number
	dev    bool
}{
	{
		v:   "0.0.0",
		dev: false,
	},
	{
		v:      "1.0.0",
		expect: version.Number{Major: 1},
		dev:    true,
	},
	{
		v:      "0.1.0",
		expect: version.Number{Minor: 1},
		dev:    true,
	},
	{
		v:      "0.0.1",
		expect: version.Number{Patch: 1},
		dev:    true,
	},
	{
		v:      "10.234.3456",
		expect: version.Number{Major: 10, Minor: 234, Patch: 3456},
		dev:    false,
	},
	{v: "1.2.3.4",
		expect: version.Number{Major: 1, Minor: 2, Patch: 3, Build: 4},
		dev:    true,
	},
	{
		v:   "1234567890.2.1",
		err: "invalid version.*",
	},
	{
		v:   "0.2..1",
		err: "invalid version.*",
	},
}

func (suite) TestParse(c *C) {
	for i, test := range parseTests {
		c.Logf("test %d", i)
		got, err := version.Parse(test.v)
		if test.err != "" {
			c.Assert(err, ErrorMatches, test.err)
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, test.expect)
			c.Check(got.IsDev(), Equals, test.dev)
		}
	}
}

func binaryVersion(major, minor, patch, build int, series, arch string) version.Binary {
	return version.Binary{
		Number: version.Number{
			Major: major,
			Minor: minor,
			Patch: patch,
			Build: build,
		},
		Series: series,
		Arch:   arch,
	}
}

var parseBinaryTests = []struct {
	v      string
	err    string
	expect version.Binary
}{
	{
		v:      "1.2.3-a-b",
		expect: binaryVersion(1, 2, 3, 0, "a", "b"),
	},
	{
		v:      "1.2.3.4-a-b",
		expect: binaryVersion(1, 2, 3, 4, "a", "b"),
	},
	{
		v:   "1.2.3--b",
		err: "invalid binary version.*",
	},
	{
		v:   "1.2.3-a-",
		err: "invalid binary version.*",
	},
}

func (suite) TestParseBinary(c *C) {
	for i, test := range parseBinaryTests {
		c.Logf("test 1: %d", i)
		got, err := version.ParseBinary(test.v)
		if test.err != "" {
			c.Assert(err, ErrorMatches, test.err)
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, test.expect)
		}
	}

	for i, test := range parseTests {
		c.Logf("test 2: %d", i)
		v := test.v + "-a-b"
		got, err := version.ParseBinary(v)
		expect := version.Binary{
			Number: test.expect,
			Series: "a",
			Arch:   "b",
		}
		if test.err != "" {
			c.Assert(err, ErrorMatches, strings.Replace(test.err, "version", "binary version", 1))
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, expect)
			c.Check(got.IsDev(), Equals, test.dev)
		}
	}
}

func (suite) TestBinaryBSON(c *C) {
	type doc struct {
		Version version.Binary
	}
	v := doc{version.MustParseBinary("1.2.3-foo-bar")}
	data, err := bson.Marshal(v)
	c.Assert(err, IsNil)
	var nv doc
	err = bson.Unmarshal(data, &nv)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, nv)
}

func (suite) TestNumberBSON(c *C) {
	type doc struct {
		Version version.Number
	}
	v := doc{version.MustParse("1.2.3")}
	data, err := bson.Marshal(&v)
	c.Assert(err, IsNil)
	var nv doc
	err = bson.Unmarshal(data, &nv)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, nv)
}
<commit_msg>version: add String check<commit_after>package version_test

import (
	"."
	"labix.org/v2/mgo/bson"
	. "launchpad.net/gocheck"
	"strings"
	"testing"
)

type suite struct{}

var _ = Suite(suite{})

func Test(t *testing.T) {
	TestingT(t)
}

// N.B. The FORCE-VERSION logic is tested in the environs package.

var cmpTests = []struct {
	v1, v2 string
	less   bool
	eq     bool
}{
	{"1.0.0", "1.0.0", false, true},
	{"01.0.0", "1.0.0", false, true},
	{"10.0.0", "9.0.0", false, false},
	{"1.0.0", "1.0.1", true, false},
	{"1.0.1", "1.0.0", false, false},
	{"1.0.0", "1.1.0", true, false},
	{"1.1.0", "1.0.0", false, false},
	{"1.0.0", "2.0.0", true, false},
	{"2.0.0", "1.0.0", false, false},
	{"2.0.0.0", "2.0.0", false, true},
	{"2.0.0.0", "2.0.0.0", false, true},
	{"2.0.0.1", "2.0.0.0", false, false},
	{"2.0.1.10", "2.0.0.0", false, false},
}

func (suite) TestComparison(c *C) {
	for i, test := range cmpTests {
		c.Logf("test %d", i)
		v1, err := version.Parse(test.v1)
		c.Assert(err, IsNil)
		v2, err := version.Parse(test.v2)
		c.Assert(err, IsNil)
		less := v1.Less(v2)
		gt := v2.Less(v1)
		c.Check(less, Equals, test.less)
		if test.eq {
			c.Check(gt, Equals, false)
		} else {
			c.Check(gt, Equals, !test.less)
		}
	}
}

var parseTests = []struct {
	v      string
	err    string
	expect version.Number
	dev    bool
}{
	{
		v:   "0.0.0",
		dev: false,
	},
	{
		v:      "1.0.0",
		expect: version.Number{Major: 1},
		dev:    true,
	},
	{
		v:      "0.1.0",
		expect: version.Number{Minor: 1},
		dev:    true,
	},
	{
		v:      "0.0.1",
		expect: version.Number{Patch: 1},
		dev:    true,
	},
	{
		v:      "10.234.3456",
		expect: version.Number{Major: 10, Minor: 234, Patch: 3456},
		dev:    false,
	},
	{v: "1.2.3.4",
		expect: version.Number{Major: 1, Minor: 2, Patch: 3, Build: 4},
		dev:    true,
	},
	{
		v:   "1234567890.2.1",
		err: "invalid version.*",
	},
	{
		v:   "0.2..1",
		err: "invalid version.*",
	},
}

func (suite) TestParse(c *C) {
	for i, test := range parseTests {
		c.Logf("test %d", i)
		got, err := version.Parse(test.v)
		if test.err != "" {
			c.Assert(err, ErrorMatches, test.err)
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, test.expect)
			c.Check(got.IsDev(), Equals, test.dev)
			c.Check(got.String(), Equals, test.v)
		}
	}
}

func binaryVersion(major, minor, patch, build int, series, arch string) version.Binary {
	return version.Binary{
		Number: version.Number{
			Major: major,
			Minor: minor,
			Patch: patch,
			Build: build,
		},
		Series: series,
		Arch:   arch,
	}
}

var parseBinaryTests = []struct {
	v      string
	err    string
	expect version.Binary
}{
	{
		v:      "1.2.3-a-b",
		expect: binaryVersion(1, 2, 3, 0, "a", "b"),
	},
	{
		v:      "1.2.3.4-a-b",
		expect: binaryVersion(1, 2, 3, 4, "a", "b"),
	},
	{
		v:   "1.2.3--b",
		err: "invalid binary version.*",
	},
	{
		v:   "1.2.3-a-",
		err: "invalid binary version.*",
	},
}

func (suite) TestParseBinary(c *C) {
	for i, test := range parseBinaryTests {
		c.Logf("test 1: %d", i)
		got, err := version.ParseBinary(test.v)
		if test.err != "" {
			c.Assert(err, ErrorMatches, test.err)
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, test.expect)
		}
	}

	for i, test := range parseTests {
		c.Logf("test 2: %d", i)
		v := test.v + "-a-b"
		got, err := version.ParseBinary(v)
		expect := version.Binary{
			Number: test.expect,
			Series: "a",
			Arch:   "b",
		}
		if test.err != "" {
			c.Assert(err, ErrorMatches, strings.Replace(test.err, "version", "binary version", 1))
		} else {
			c.Assert(err, IsNil)
			c.Assert(got, Equals, expect)
			c.Check(got.IsDev(), Equals, test.dev)
		}
	}
}

func (suite) TestBinaryBSON(c *C) {
	type doc struct {
		Version version.Binary
	}
	v := doc{version.MustParseBinary("1.2.3-foo-bar")}
	data, err := bson.Marshal(v)
	c.Assert(err, IsNil)
	var nv doc
	err = bson.Unmarshal(data, &nv)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, nv)
}

func (suite) TestNumberBSON(c *C) {
	type doc struct {
		Version version.Number
	}
	v := doc{version.MustParse("1.2.3")}
	data, err := bson.Marshal(&v)
	c.Assert(err, IsNil)
	var nv doc
	err = bson.Unmarshal(data, &nv)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, nv)
}
<|endoftext|>


<commit_before>package video

import "io"
import "github.com/32bitkid/mpeg/util"
import "errors"

var ErrUnsupportedVideoStream_ISO_IEC_11172_2 = errors.New("unsupported video stream ISO/IEC 11172-2")

type FrameProvider interface {
	Next() (interface{}, error)
}

func NewFrameProvider(source io.Reader) FrameProvider {
	return &frameProvider{
		NewVideoSequence(util.NewBitReader(source)),
	}
}

type frameProvider struct {
	VideoSequence
}

func (self *frameProvider) Next() (interface{}, error) {

	// Align to next start code
	err := next_start_code(self)
	if err != nil {
		panic(err)
	}

	// Read sequence_header
	err = self.sequence_header()
	if err != nil {
		panic(err)
	}

	// peek for sequence_extension
	val, err := self.Peek32(32)
	if err != nil {
		panic(err)
	}

	if val == ExtensionStartCode {

		err := self.sequence_extension()

		for {
			err = extension_and_user_data(0, self)
			if err != nil {
				panic("extension_and_user_data")
			}

			for {
				nextbits, err := self.Peek32(32)
				if err != nil {
					panic("Peek32")
				}

				if StartCode(nextbits) == GroupStartCode {
					err = self.group_of_pictures_header()
					if err != nil {
						panic("group_of_pictures_header")
					}
					err = extension_and_user_data(1, self)
					if err != nil {
						panic("extension_and_user_data")
					}
				}
				err = self.picture_header()
				if err != nil {
					panic("picture_header")
				}
				err = self.picture_coding_extension()
				if err != nil {
					panic("picture_coding_extension")
				}
				err = extension_and_user_data(2, self)
				if err != nil {
					panic("extension_and_user_data")
				}

				self.picture_data()

				panic("not implemented")
			}

			val, err := self.Peek32(32)
			log.Printf("%x\n", val)
			if err != nil {
				panic("Peek32")
			}

			if val == SequenceEndStartCode {
				break
			}
		}

		err = self.Trash(32)

		return nil, err
	} else {
		// Stream is MPEG-1 Video
		return nil, ErrUnsupportedVideoStream_ISO_IEC_11172_2
	}

}
<commit_msg>some debugging stuff<commit_after>package video

import "io"
import "github.com/32bitkid/mpeg/util"
import "errors"

var ErrUnsupportedVideoStream_ISO_IEC_11172_2 = errors.New("unsupported video stream ISO/IEC 11172-2")

type FrameProvider interface {
	Next() (interface{}, error)
}

func NewFrameProvider(source io.Reader) FrameProvider {
	return &frameProvider{
		NewVideoSequence(util.NewBitReader(source)),
	}
}

type frameProvider struct {
	VideoSequence
}

func (self *frameProvider) Next() (interface{}, error) {

	// Align to next start code
	err := next_start_code(self)
	if err != nil {
		panic(err)
	}

	// Read sequence_header
	err = self.sequence_header()
	if err != nil {
		panic(err)
	}

	// peek for sequence_extension
	val, err := self.Peek32(32)
	if err != nil {
		panic(err)
	}

	if val == ExtensionStartCode {

		err := self.sequence_extension()

		for {
			err = extension_and_user_data(0, self)
			if err != nil {
				panic("extension_and_user_data")
			}

			for {
				nextbits, err := self.Peek32(32)
				if err != nil {
					panic("Peek32")
				}

				if StartCode(nextbits) == GroupStartCode {
					err = self.group_of_pictures_header()
					if err != nil {
						panic("group_of_pictures_header")
					}
					err = extension_and_user_data(1, self)
					if err != nil {
						panic("extension_and_user_data")
					}
				}
				err = self.picture_header()
				if err != nil {
					panic("picture_header")
				}
				err = self.picture_coding_extension()
				if err != nil {
					panic("picture_coding_extension")
				}
				err = extension_and_user_data(2, self)
				if err != nil {
					panic("extension_and_user_data")
				}
				err = self.picture_data()
				if err != nil {
					panic(err)
				}

				panic("not implemented: frame_provider")
			}

			val, err := self.Peek32(32)
			log.Printf("%x\n", val)
			if err != nil {
				panic("Peek32")
			}

			if val == SequenceEndStartCode {
				break
			}
		}

		err = self.Trash(32)

		return nil, err
	} else {
		// Stream is MPEG-1 Video
		return nil, ErrUnsupportedVideoStream_ISO_IEC_11172_2
	}

}
<|endoftext|>


<commit_before>package myaws

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/pkg/errors"
)

// EC2LsOptions customize the behavior of the Ls command.
type EC2LsOptions struct {
	All       bool
	Quiet     bool
	FilterTag string
	Fields    []string
}

// EC2Ls describes EC2 instances.
func (client *Client) EC2Ls(options EC2LsOptions) error {
	params := &ec2.DescribeInstancesInput{
		Filters: []*ec2.Filter{
			buildEC2StateFilter(options.All),
			buildEC2TagFilter(options.FilterTag),
		},
	}

	response, err := client.EC2.DescribeInstances(params)
	if err != nil {
		return errors.Wrap(err, "DescribeInstances failed")
	}

	for _, reservation := range response.Reservations {
		for _, instance := range reservation.Instances {
			fmt.Println(formatEC2Instance(client, options, instance))
		}
	}

	return nil
}

func buildEC2StateFilter(all bool) *ec2.Filter {
	var stateFilter *ec2.Filter
	if !all {
		stateFilter = &ec2.Filter{
			Name: aws.String("instance-state-name"),
			Values: []*string{
				aws.String("running"),
			},
		}
	}
	return stateFilter
}

func buildEC2TagFilter(filterTag string) *ec2.Filter {
	var tagFilter *ec2.Filter
	if filterTag != "" {
		tagParts := strings.Split(filterTag, ":")
		tagFilter = &ec2.Filter{
			Name: aws.String("tag:" + tagParts[0]),
			Values: []*string{
				aws.String("*" + tagParts[1] + "*"),
			},
		}
	}
	return tagFilter
}

func formatEC2Instance(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	formatFuncs := map[string]func(client *Client, options EC2LsOptions, instance *ec2.Instance) string{
		"InstanceId":       formatEC2InstanceID,
		"InstanceType":     formatEC2InstanceType,
		"PublicIpAddress":  formatEC2PublicIPAddress,
		"PrivateIpAddress": formatEC2PrivateIPAddress,
		"StateName":        formatEC2StateName,
		"LaunchTime":       formatEC2LaunchTime,
	}

	var outputFields []string
	if options.Quiet {
		outputFields = []string{"InstanceId"}
	} else {
		outputFields = options.Fields
	}

	output := []string{}

	for _, field := range outputFields {
		value := ""
		if strings.Index(field, "Tag:") != -1 {
			key := strings.Split(field, ":")[1]
			value = formatEC2Tag(instance, key)
		} else {
			value = formatFuncs[field](client, options, instance)
		}
		output = append(output, value)
	}
	return strings.Join(output[:], "\t")
}

func formatEC2InstanceID(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return *instance.InstanceId
}

func formatEC2InstanceType(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return fmt.Sprintf("%-11s", *instance.InstanceType)
}

func formatEC2PublicIPAddress(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	if instance.PublicIpAddress == nil {
		return "___.___.___.___"
	}
	return *instance.PublicIpAddress
}

func formatEC2PrivateIPAddress(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	if instance.PrivateIpAddress == nil {
		return "___.___.___.___"
	}
	return *instance.PrivateIpAddress
}

func formatEC2StateName(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return *instance.State.Name
}

func formatEC2LaunchTime(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return client.FormatTime(instance.LaunchTime)
}

func formatEC2Tag(instance *ec2.Instance, key string) string {
	var value string
	for _, t := range instance.Tags {
		if *t.Key == key {
			value = *t.Value
			break
		}
	}
	return value
}
<commit_msg>Extract find EC2 instances logic to method<commit_after>package myaws

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/pkg/errors"
)

// EC2LsOptions customize the behavior of the Ls command.
type EC2LsOptions struct {
	All       bool
	Quiet     bool
	FilterTag string
	Fields    []string
}

// EC2Ls describes EC2 instances.
func (client *Client) EC2Ls(options EC2LsOptions) error {
	instances, err := client.FindEC2Instances(options)
	if err != nil {
		return err
	}

	for _, instance := range instances {
		fmt.Println(formatEC2Instance(client, options, instance))
	}
	return nil
}

// FindEC2Instances returns an array of instances matching the conditions.
func (client *Client) FindEC2Instances(options EC2LsOptions) ([]*ec2.Instance, error) {
	params := &ec2.DescribeInstancesInput{
		Filters: []*ec2.Filter{
			buildEC2StateFilter(options.All),
			buildEC2TagFilter(options.FilterTag),
		},
	}

	response, err := client.EC2.DescribeInstances(params)
	if err != nil {
		return nil, errors.Wrap(err, "DescribeInstances failed")
	}

	var instances []*ec2.Instance
	for _, reservation := range response.Reservations {
		for _, instance := range reservation.Instances {
			instances = append(instances, instance)
		}
	}

	return instances, nil
}

func buildEC2StateFilter(all bool) *ec2.Filter {
	var stateFilter *ec2.Filter
	if !all {
		stateFilter = &ec2.Filter{
			Name: aws.String("instance-state-name"),
			Values: []*string{
				aws.String("running"),
			},
		}
	}
	return stateFilter
}

func buildEC2TagFilter(filterTag string) *ec2.Filter {
	var tagFilter *ec2.Filter
	if filterTag != "" {
		tagParts := strings.Split(filterTag, ":")
		tagFilter = &ec2.Filter{
			Name: aws.String("tag:" + tagParts[0]),
			Values: []*string{
				aws.String("*" + tagParts[1] + "*"),
			},
		}
	}
	return tagFilter
}

func formatEC2Instance(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	formatFuncs := map[string]func(client *Client, options EC2LsOptions, instance *ec2.Instance) string{
		"InstanceId":       formatEC2InstanceID,
		"InstanceType":     formatEC2InstanceType,
		"PublicIpAddress":  formatEC2PublicIPAddress,
		"PrivateIpAddress": formatEC2PrivateIPAddress,
		"StateName":        formatEC2StateName,
		"LaunchTime":       formatEC2LaunchTime,
	}

	var outputFields []string
	if options.Quiet {
		outputFields = []string{"InstanceId"}
	} else {
		outputFields = options.Fields
	}

	output := []string{}

	for _, field := range outputFields {
		value := ""
		if strings.Index(field, "Tag:") != -1 {
			key := strings.Split(field, ":")[1]
			value = formatEC2Tag(instance, key)
		} else {
			value = formatFuncs[field](client, options, instance)
		}
		output = append(output, value)
	}
	return strings.Join(output[:], "\t")
}

func formatEC2InstanceID(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return *instance.InstanceId
}

func formatEC2InstanceType(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return fmt.Sprintf("%-11s", *instance.InstanceType)
}

func formatEC2PublicIPAddress(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	if instance.PublicIpAddress == nil {
		return "___.___.___.___"
	}
	return *instance.PublicIpAddress
}

func formatEC2PrivateIPAddress(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	if instance.PrivateIpAddress == nil {
		return "___.___.___.___"
	}
	return *instance.PrivateIpAddress
}

func formatEC2StateName(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return *instance.State.Name
}

func formatEC2LaunchTime(client *Client, options EC2LsOptions, instance *ec2.Instance) string {
	return client.FormatTime(instance.LaunchTime)
}

func formatEC2Tag(instance *ec2.Instance, key string) string {
	var value string
	for _, t := range instance.Tags {
		if *t.Key == key {
			value = *t.Value
			break
		}
	}
	return value
}
<|endoftext|>


<commit_before><commit_msg>show larger matrices by default<commit_after><|endoftext|>


<commit_before><commit_msg>Add test for handler, POST only<commit_after><|endoftext|>


<commit_before><commit_msg>Fix typo in 'Your revision is building' message<commit_after><|endoftext|>


<commit_before>package framework

type ValueType int

const (
	TYPE_STRING ValueType = iota
	TYPE_INT
	TYPE_INT64
	TYPE_FLOAT
	TYPE_FLOAT64
	TYPE_BOOL
	TYPE_STRUCT

	METHOD_GET    = "GET"
	METHOD_POST   = "POST"
	METHOD_PUT    = "PUT"
	METHOD_DELETE = "DELETE"

	SCHEME_HTTP  = "http"
	SCHEME_HTTPS = "https"

	MIME_HTML = "text/html"
	MIME_XML  = "application/xml"
	MIME_JSON = "application/json"

)
<commit_msg>Added YAML renderer<commit_after>package framework

type ValueType int

const (
	TYPE_STRING ValueType = iota
	TYPE_INT
	TYPE_INT64
	TYPE_FLOAT
	TYPE_FLOAT64
	TYPE_BOOL
	TYPE_STRUCT

	METHOD_GET    = "GET"
	METHOD_POST   = "POST"
	METHOD_PUT    = "PUT"
	METHOD_DELETE = "DELETE"

	SCHEME_HTTP  = "http"
	SCHEME_HTTPS = "https"

	MIME_HTML = "text/html"
	MIME_XML  = "application/xml"
	MIME_JSON = "application/json"
	MIME_YAML = "application/x-yaml"

)
<|endoftext|>


<commit_before>/*
    Author: Pavel Abramov
    Examples taken from golang docs and Mozilla's
    nodejs clientside session library
*/

package sessioncookie

import (
    "io"
    "time"
    "errors"
    "strings"
    "crypto/aes"
    "crypto/rand"
    "crypto/hmac"
    "crypto/cipher"
    "crypto/sha256"
    "encoding/base64"
)

func concatValue(hash_mac string, timestamp string, data string, sep string) string {
    if sep == "" {
        sep = "."
    }
    return hash_mac + sep+ timestamp + sep + data
}

func encryptData(secret_key []byte, data []byte) ([]byte, error)  {
    // add padding to block size
    remainder := len(data) % aes.BlockSize
    if remainder != 0 {
        padding_length := aes.BlockSize - remainder
        padding := ""
        for i := 0; i < padding_length; i++ {
            padding += "="
        }
        data = append(data, padding...)
    }

    block, err := aes.NewCipher(secret_key)
    if err != nil {
        return []byte{}, err
    }

    // empty array of size block + data
    ciphertext := make([]byte, aes.BlockSize+len(data))

    // iv is appended to ciphertext
    iv := ciphertext[:aes.BlockSize]

    // reads from rand.Reader global singleton PRNG into iv
    _, err = io.ReadFull(rand.Reader, iv)
    if err != nil {
        return []byte{}, err
    }

    // data is encrypted
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext[aes.BlockSize:], data)

    return ciphertext, nil
}

func decryptData(secret_key []byte, encrypted_data []byte) (string, error) {
    block, err := aes.NewCipher(secret_key)
    if err != nil {
        return "", err
    }

    if len(encrypted_data) < aes.BlockSize {
        return "", errors.New("encrypted data is less than BlockSize")
    }

    iv := encrypted_data[:aes.BlockSize]
    data := encrypted_data[aes.BlockSize:]

    if len(data) % aes.BlockSize != 0 {
        return "", errors.New("encrypted data is not a multiple of block size")
    }

    mode := cipher.NewCBCDecrypter(block, iv)

    mode.CryptBlocks(data, data)

    // remove padding
    trimmed_data := strings.TrimRight(string(data), "=")

    return trimmed_data, nil
}

func generateHMAC(secret_key []byte, timestamp []byte, encrypted_data []byte) []byte {
    message := append(timestamp, encrypted_data...)

    // create hash mac
    hash_mac := hmac.New(sha256.New, secret_key)
    hash_mac.Write(message)

    // return byte array
    return hash_mac.Sum(nil)
}

func EncryptCookieValue(secret_key []byte, plaintext_data []byte, sep string) (string, error) {
    // generate timestamp
    now := time.Now()
    timestamp := []byte(now.Format(time.UnixDate))
    encoded_timestamp := base64.URLEncoding.EncodeToString(timestamp)

    // generate data blob
    encrypted_data, err := encryptData(secret_key, plaintext_data)
    if err != nil {
        return "", err
    }

    encoded_data := base64.URLEncoding.EncodeToString(encrypted_data)

    // generate data blob
    // generate hmac
    hash_mac := generateHMAC(secret_key, timestamp, encrypted_data)
    encoded_hash_mac := base64.URLEncoding.EncodeToString(hash_mac)

    // return encoded values
    return concatValue(encoded_hash_mac, encoded_timestamp, encoded_data, sep), nil
}

func DecryptCookieValue(secret_key []byte, cookie_value string, sep string) (string, error) {
    if sep == "" {
        sep = "."
    }

    // extract value
    value := strings.Split(cookie_value, sep)
    encoded_hash_mac := value[0]
    encoded_timestamp := value[1]
    encoded_data := value[2]

    //decode
    encrypted_data, err := base64.URLEncoding.DecodeString(encoded_data)
    if err != nil {
        return "", err
    }

    timestamp, err := base64.URLEncoding.DecodeString(encoded_timestamp)
    if err != nil {
        return "", err
    }

    returned_hmac, err := base64.URLEncoding.DecodeString(encoded_hash_mac)
    if err != nil {
        return "", err
    }

    // compute and compare
    computed_hmac := generateHMAC(secret_key, timestamp, encrypted_data)

    if !hmac.Equal(returned_hmac, computed_hmac) {
        return "", errors.New("Returned HMAC does not match")
    }

    // hmac mathces, now decrypt data.
    data, err := decryptData(secret_key, encrypted_data)
    if err != nil {
        return "", err
    }

    return string(data), nil
}

<commit_msg>Fixes typo<commit_after>/*
    Author: Pavel Abramov
    Examples taken from golang docs and Mozilla's
    nodejs clientside session library
*/

package sessioncookie

import (
    "io"
    "time"
    "errors"
    "strings"
    "crypto/aes"
    "crypto/rand"
    "crypto/hmac"
    "crypto/cipher"
    "crypto/sha256"
    "encoding/base64"
)

func concatValue(hash_mac string, timestamp string, data string, sep string) string {
    if sep == "" {
        sep = "."
    }
    return hash_mac + sep+ timestamp + sep + data
}

func encryptData(secret_key []byte, data []byte) ([]byte, error)  {
    // add padding to block size
    remainder := len(data) % aes.BlockSize
    if remainder != 0 {
        padding_length := aes.BlockSize - remainder
        padding := ""
        for i := 0; i < padding_length; i++ {
            padding += "="
        }
        data = append(data, padding...)
    }

    block, err := aes.NewCipher(secret_key)
    if err != nil {
        return []byte{}, err
    }

    // empty array of size block + data
    ciphertext := make([]byte, aes.BlockSize+len(data))

    // iv is appended to ciphertext
    iv := ciphertext[:aes.BlockSize]

    // reads from rand.Reader global singleton PRNG into iv
    _, err = io.ReadFull(rand.Reader, iv)
    if err != nil {
        return []byte{}, err
    }

    // data is encrypted
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext[aes.BlockSize:], data)

    return ciphertext, nil
}

func decryptData(secret_key []byte, encrypted_data []byte) (string, error) {
    block, err := aes.NewCipher(secret_key)
    if err != nil {
        return "", err
    }

    if len(encrypted_data) < aes.BlockSize {
        return "", errors.New("encrypted data is less than BlockSize")
    }

    iv := encrypted_data[:aes.BlockSize]
    data := encrypted_data[aes.BlockSize:]

    if len(data) % aes.BlockSize != 0 {
        return "", errors.New("encrypted data is not a multiple of block size")
    }

    mode := cipher.NewCBCDecrypter(block, iv)

    mode.CryptBlocks(data, data)

    // remove padding
    trimmed_data := strings.TrimRight(string(data), "=")

    return trimmed_data, nil
}

func generateHMAC(secret_key []byte, timestamp []byte, encrypted_data []byte) []byte {
    message := append(timestamp, encrypted_data...)

    // create hash mac
    hash_mac := hmac.New(sha256.New, secret_key)
    hash_mac.Write(message)

    // return byte array
    return hash_mac.Sum(nil)
}

func EncryptCookieValue(secret_key []byte, plaintext_data []byte, sep string) (string, error) {
    // generate timestamp
    now := time.Now()
    timestamp := []byte(now.Format(time.UnixDate))
    encoded_timestamp := base64.URLEncoding.EncodeToString(timestamp)

    // generate data blob
    encrypted_data, err := encryptData(secret_key, plaintext_data)
    if err != nil {
        return "", err
    }

    encoded_data := base64.URLEncoding.EncodeToString(encrypted_data)

    // generate data blob
    // generate hmac
    hash_mac := generateHMAC(secret_key, timestamp, encrypted_data)
    encoded_hash_mac := base64.URLEncoding.EncodeToString(hash_mac)

    // return encoded values
    return concatValue(encoded_hash_mac, encoded_timestamp, encoded_data, sep), nil
}

func DecryptCookieValue(secret_key []byte, cookie_value string, sep string) (string, error) {
    if sep == "" {
        sep = "."
    }

    // extract value
    value := strings.Split(cookie_value, sep)
    encoded_hash_mac := value[0]
    encoded_timestamp := value[1]
    encoded_data := value[2]

    //decode
    encrypted_data, err := base64.URLEncoding.DecodeString(encoded_data)
    if err != nil {
        return "", err
    }

    timestamp, err := base64.URLEncoding.DecodeString(encoded_timestamp)
    if err != nil {
        return "", err
    }

    returned_hmac, err := base64.URLEncoding.DecodeString(encoded_hash_mac)
    if err != nil {
        return "", err
    }

    // compute and compare
    computed_hmac := generateHMAC(secret_key, timestamp, encrypted_data)

    if !hmac.Equal(returned_hmac, computed_hmac) {
        return "", errors.New("Returned HMAC does not match")
    }

    // hmac matches, now decrypt data.
    data, err := decryptData(secret_key, encrypted_data)
    if err != nil {
        return "", err
    }

    return string(data), nil
}
<|endoftext|>


<commit_before>// BSD licensed

package interfacetools

import (
	"errors"
	"reflect"
	"bytes"
	"fmt"
)

// Copier is the interface implemented by objects
// that can decode input interfaces themselves.
// The Copier must copy the input data if it wishes
// to retain the data after returning. Unhandled
// input must return an error.
type Copier interface {
	CopyIn(interface{}) error
}

// Performs a deep-copy of source object to the passed in interface.
//
// If the object is a struct, then the copy is attempted based on the tag
// of the json tag of the field; the same rules apply per encoding/json.
// If a field is not available, then a copier skips it.
func CopyOut(src interface{}, out interface{}) (err error) {
	return CopyOutTagged(src, out, "json")
}

func CopyOutTagged(src interface{}, out interface{}, tag string) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	v := reflect.ValueOf(out)
	if v.Kind() != reflect.Ptr {
		return errors.New("output interface must be a pointer")
	}

	dec := newDecoder(tag)
	iv := reflect.ValueOf(src)
	ov := reflect.ValueOf(out)
	return dec.decode(iv, ov)
}

type decoder struct {
	tag  string
	path []string
}

func newDecoder(tag string) *decoder {
	return &decoder{tag, make([]string, 0, 12)}
}

func (d *decoder) pathString() string {
	if len(d.path) == 0 {
		return ""
	}

	var buf bytes.Buffer
	for i := range d.path {
		if i > 0 {
			buf.WriteString(".")
		}
		buf.WriteString(d.path[i])
	}
	buf.WriteString(" ")
	return buf.String()
}

func (d *decoder) pushPath(s string) {
	if d.path != nil {
		d.path = append(d.path, s)
	}
}

func (d *decoder) popPath() string {
	if len(d.path) > 0 {
		s := d.path[len(d.path)-1]
		d.path = d.path[:len(d.path)-1]
		return s
	}
	return ""
}

func (d *decoder) tryCopyIn(sv reflect.Value, v reflect.Value) bool {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
				v = e
				continue
			}
		}
		if v.Kind() != reflect.Ptr {
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.Type().NumMethod() > 0 {
			if u, ok := v.Interface().(Copier); ok {
				// Can now attempt CopyIn
				if u.CopyIn(sv.Interface()) == nil {
					return true
				}
			}
		}
		v = v.Elem()
	}

	return false
}

func (d *decoder) decode(sv reflect.Value, v reflect.Value) error {
	if v.Kind() == reflect.Ptr && !v.IsNil() {
		v = v.Elem()
	}

	if sv.Kind() == reflect.Ptr {
		sv = sv.Elem()
	}

	if sv.Kind() == reflect.Interface {
		if sv.IsNil() {
			return nil
		}
		sv = sv.Elem()
	}

	if !v.CanSet() {
		return errors.New("cannot set field " + v.String())
	}

	var e reflect.Type
	if v.Kind() == reflect.Ptr {
		e = v.Type().Elem()
	} else {
		e = v.Type()
	}

	switch e.Kind() {
	case reflect.Map:
		if sv.Kind() != reflect.Map {
			return errors.New("src not map")
		}
		t := v.Type()
		if t.Key().Kind() != reflect.String {
			return errors.New("dest<map> does not use string key")
		}
		if v.IsNil() {
			v.Set(reflect.MakeMap(t))
		}

		if d.tryCopyIn(sv, v) {
			return nil
		}

		return d.mapCopy(sv, v)

	case reflect.Struct:
		// Decode map[string] interface{} into struct
		if sv.Kind() != reflect.Map {
			return errors.New("src not map")
		}
		if v.Kind() == reflect.Ptr && v.IsNil() {
			v.Set(reflect.New(e))
		}

		if d.tryCopyIn(sv, v) {
			return nil
		}

		if v.Kind() == reflect.Ptr {
			return d.mapToStruct(sv, v.Elem())
		} else {
			return d.mapToStruct(sv, v)
		}

	case reflect.Slice, reflect.Array:
		if sv.Kind() != reflect.Slice {
			return errors.New("src not slice")
		}

		if v.Kind() == reflect.Slice && v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type(), sv.Len(), sv.Len()))
		}

		if d.tryCopyIn(sv, v) {
			return nil
		}

		return d.sliceCopy(sv, v)
	}

	if v.Kind() == reflect.Ptr {
		nv := reflect.New(e)

		if d.tryCopyIn(sv, nv) {
			return nil
		}

		err := d.decodeScalar(sv, nv)
		if err == nil {
			v.Set(nv)
		}
		return err
	}

	if d.tryCopyIn(sv, v) {
		return nil
	}

	return d.decodeScalar(sv, v)
}

func (d *decoder) mapCopy(src reflect.Value, dst reflect.Value) error {
	sv := src.MapKeys()
	dt := dst.Type().Elem()

	for i := range sv {
		ot := reflect.New(dt)

		if dt.Kind() == reflect.Ptr {
			ot = reflect.New(ot.Type().Elem())
		}

		d.pushPath(sv[i].String())
		err := d.decode(src.MapIndex(sv[i]), ot)
		if err != nil {
			err = errors.New(d.pathString() + err.Error())
			d.path = nil
			return err
		}
		d.popPath()

		dst.SetMapIndex(sv[i], ot.Elem())
	}
	return nil
}

func (d *decoder) mapToStruct(src reflect.Value, dst reflect.Value) error {
	fieldIdx := make(map[string] int)
	for i := 0; i < dst.Type().NumField(); i++ {
		sf := dst.Type().Field(i)
		tag := sf.Tag.Get(d.tag)
		if tag == "" {
			// do by name (only if exported field)
			if sf.Name[0] >= 'A' && sf.Name[0] <= 'Z' {
				fieldIdx[sf.Name] = i
			}
		} else if tag == "-" {
			// skip this field
		} else {
			fieldIdx[tag] = i
		}
	}

	sv := src.MapKeys()
	for i, k := range sv {
		if it, ok := fieldIdx[k.String()]; ok {
			d.pushPath(sv[i].String())
			err := d.decode(src.MapIndex(sv[i]), dst.Field(it))
			if err != nil {
				err = errors.New(d.pathString() + err.Error())
				d.path = nil
				return err
			}
			d.popPath()
		}
	}
	return nil
}

func (d *decoder) sliceCopy(src reflect.Value, dst reflect.Value) error {
	for i := 0; i < src.Len(); i++ {
		if i < dst.Len() {
			d.pushPath(fmt.Sprintf("[%d]", i))
			err := d.decode(src.Index(i), dst.Index(i))
			if err != nil {
				err = errors.New(d.pathString() + err.Error())
				d.path = nil
				return err
			}
			d.popPath()
		}
	}
	return nil
}

func (d *decoder) decodeScalar(src reflect.Value, dst reflect.Value) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	switch dst.Kind() {
	case reflect.Bool:
		dst.SetBool(src.Bool())

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		dst.SetInt(int64(src.Float()))

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		dst.SetUint(uint64(src.Float()))

	case reflect.Float32, reflect.Float64:
		dst.SetFloat(src.Float())

	case reflect.Interface:
		dst.Set(src)

	case reflect.String:
		if src.Kind() != reflect.String {
			return errors.New("not string kind: " + src.Kind().String())
		}
		dst.SetString(src.String())
	}

	return nil
}
<commit_msg>Perform tryCopyIn early<commit_after>// BSD licensed

package interfacetools

import (
	"errors"
	"reflect"
	"bytes"
	"fmt"
)

// Copier is the interface implemented by objects
// that can decode input interfaces themselves.
// The Copier must copy the input data if it wishes
// to retain the data after returning. Unhandled
// input must return an error.
type Copier interface {
	CopyIn(interface{}) error
}

// Performs a deep-copy of source object to the passed in interface.
//
// If the object is a struct, then the copy is attempted based on the tag
// of the json tag of the field; the same rules apply per encoding/json.
// If a field is not available, then a copier skips it.
func CopyOut(src interface{}, out interface{}) (err error) {
	return CopyOutTagged(src, out, "json")
}

func CopyOutTagged(src interface{}, out interface{}, tag string) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	v := reflect.ValueOf(out)
	if v.Kind() != reflect.Ptr {
		return errors.New("output interface must be a pointer")
	}

	dec := newDecoder(tag)
	iv := reflect.ValueOf(src)
	ov := reflect.ValueOf(out)
	return dec.decode(iv, ov)
}

type decoder struct {
	tag  string
	path []string
}

func newDecoder(tag string) *decoder {
	return &decoder{tag, make([]string, 0, 12)}
}

func (d *decoder) pathString() string {
	if len(d.path) == 0 {
		return ""
	}

	var buf bytes.Buffer
	for i := range d.path {
		if i > 0 {
			buf.WriteString(".")
		}
		buf.WriteString(d.path[i])
	}
	buf.WriteString(" ")
	return buf.String()
}

func (d *decoder) pushPath(s string) {
	if d.path != nil {
		d.path = append(d.path, s)
	}
}

func (d *decoder) popPath() string {
	if len(d.path) > 0 {
		s := d.path[len(d.path)-1]
		d.path = d.path[:len(d.path)-1]
		return s
	}
	return ""
}

func (d *decoder) tryCopyIn(sv reflect.Value, v reflect.Value) bool {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
				v = e
				continue
			}
		}
		if v.Kind() != reflect.Ptr {
			break
		}
		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		if v.Type().NumMethod() > 0 {
			if u, ok := v.Interface().(Copier); ok {
				// Can now attempt CopyIn
				if u.CopyIn(sv.Interface()) == nil {
					return true
				}
			}
		}
		v = v.Elem()
	}

	return false
}

func (d *decoder) decode(sv reflect.Value, v reflect.Value) error {
	if v.Kind() == reflect.Ptr && !v.IsNil() {
		v = v.Elem()
	}

	if sv.Kind() == reflect.Ptr {
		sv = sv.Elem()
	}

	if sv.Kind() == reflect.Interface {
		if sv.IsNil() {
			return nil
		}
		sv = sv.Elem()
	}

	if !v.CanSet() {
		return errors.New("cannot set field " + v.String())
	}

	var e reflect.Type
	if v.Kind() == reflect.Ptr {
		e = v.Type().Elem()
	} else {
		e = v.Type()
	}

	switch e.Kind() {
	case reflect.Map:
		if d.tryCopyIn(sv, v) {
			return nil
		}

		if sv.Kind() != reflect.Map {
			return errors.New("src not map")
		}
		t := v.Type()
		if t.Key().Kind() != reflect.String {
			return errors.New("dest<map> does not use string key")
		}
		if v.IsNil() {
			v.Set(reflect.MakeMap(t))
		}

		return d.mapCopy(sv, v)

	case reflect.Struct:
		if d.tryCopyIn(sv, v) {
			return nil
		}

		// Decode map[string] interface{} into struct
		if sv.Kind() != reflect.Map {
			return errors.New("src not map")
		}
		if v.Kind() == reflect.Ptr && v.IsNil() {
			v.Set(reflect.New(e))
		}

		if v.Kind() == reflect.Ptr {
			return d.mapToStruct(sv, v.Elem())
		} else {
			return d.mapToStruct(sv, v)
		}

	case reflect.Slice, reflect.Array:
		if d.tryCopyIn(sv, v) {
			return nil
		}

		if sv.Kind() != reflect.Slice {
			return errors.New("src not slice")
		}

		if v.Kind() == reflect.Slice && v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type(), sv.Len(), sv.Len()))
		}

		return d.sliceCopy(sv, v)
	}

	if v.Kind() == reflect.Ptr {
		nv := reflect.New(e)

		if d.tryCopyIn(sv, nv) {
			return nil
		}

		err := d.decodeScalar(sv, nv)
		if err == nil {
			v.Set(nv)
		}
		return err
	}

	if d.tryCopyIn(sv, v) {
		return nil
	}

	return d.decodeScalar(sv, v)
}

func (d *decoder) mapCopy(src reflect.Value, dst reflect.Value) error {
	sv := src.MapKeys()
	dt := dst.Type().Elem()

	for i := range sv {
		ot := reflect.New(dt)

		if dt.Kind() == reflect.Ptr {
			ot = reflect.New(ot.Type().Elem())
		}

		d.pushPath(sv[i].String())
		err := d.decode(src.MapIndex(sv[i]), ot)
		if err != nil {
			err = errors.New(d.pathString() + err.Error())
			d.path = nil
			return err
		}
		d.popPath()

		dst.SetMapIndex(sv[i], ot.Elem())
	}
	return nil
}

func (d *decoder) mapToStruct(src reflect.Value, dst reflect.Value) error {
	fieldIdx := make(map[string] int)
	for i := 0; i < dst.Type().NumField(); i++ {
		sf := dst.Type().Field(i)
		tag := sf.Tag.Get(d.tag)
		if tag == "" {
			// do by name (only if exported field)
			if sf.Name[0] >= 'A' && sf.Name[0] <= 'Z' {
				fieldIdx[sf.Name] = i
			}
		} else if tag == "-" {
			// skip this field
		} else {
			fieldIdx[tag] = i
		}
	}

	sv := src.MapKeys()
	for i, k := range sv {
		if it, ok := fieldIdx[k.String()]; ok {
			d.pushPath(sv[i].String())
			err := d.decode(src.MapIndex(sv[i]), dst.Field(it))
			if err != nil {
				err = errors.New(d.pathString() + err.Error())
				d.path = nil
				return err
			}
			d.popPath()
		}
	}
	return nil
}

func (d *decoder) sliceCopy(src reflect.Value, dst reflect.Value) error {
	for i := 0; i < src.Len(); i++ {
		if i < dst.Len() {
			d.pushPath(fmt.Sprintf("[%d]", i))
			err := d.decode(src.Index(i), dst.Index(i))
			if err != nil {
				err = errors.New(d.pathString() + err.Error())
				d.path = nil
				return err
			}
			d.popPath()
		}
	}
	return nil
}

func (d *decoder) decodeScalar(src reflect.Value, dst reflect.Value) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()

	switch dst.Kind() {
	case reflect.Bool:
		dst.SetBool(src.Bool())

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		dst.SetInt(int64(src.Float()))

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		dst.SetUint(uint64(src.Float()))

	case reflect.Float32, reflect.Float64:
		dst.SetFloat(src.Float())

	case reflect.Interface:
		dst.Set(src)

	case reflect.String:
		if src.Kind() != reflect.String {
			return errors.New("not string kind: " + src.Kind().String())
		}
		dst.SetString(src.String())
	}

	return nil
}
<|endoftext|>


<commit_before>// +build go1.3

package mpool

import (
	"bytes"
	"sync"
)

var (
	bsb           sync.Pool
	accessLogPool sync.Pool
)

func init() {
	bsb.New = func() interface{} {
		return &bytes.Buffer{}
	}

	accessLogPool.New = func() interface{} {
		return make([]byte, 0, accessLogLineMaxBytes)
	}
}

func BytesBufferGet() *bytes.Buffer {
	return bsb.Get().(*bytes.Buffer)
}

func BytesBufferPut(b *bytes.Buffer) {
	bsb.Put(b)
}

func AccessLogLineBufferGet() []byte {
	return accessLogPool.Get().([]byte)
}

func AccessLogLineBufferPut(b []byte) {
	accessLogPool.Put(b)
}
<commit_msg>reduce the possibility of growing memory<commit_after>// +build go1.3

package mpool

import (
	"bytes"
	"sync"
)

var (
	bsb           sync.Pool
	accessLogPool sync.Pool
)

func init() {
	bsb.New = func() interface{} {
		return bytes.NewBuffer(make([]byte, 100))
	}

	accessLogPool.New = func() interface{} {
		return make([]byte, 0, accessLogLineMaxBytes)
	}
}

func BytesBufferGet() *bytes.Buffer {
	return bsb.Get().(*bytes.Buffer)
}

func BytesBufferPut(b *bytes.Buffer) {
	bsb.Put(b)
}

func AccessLogLineBufferGet() []byte {
	return accessLogPool.Get().([]byte)
}

func AccessLogLineBufferPut(b []byte) {
	accessLogPool.Put(b)
}
<|endoftext|>


<commit_before><commit_msg>comment lint and exported types in iam package<commit_after><|endoftext|>


<commit_before><commit_msg>Use unicode multiplication sign<commit_after><|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/common/handler"
	"socialapi/workers/common/response"
	"socialapi/workers/integration/webhook"
	"socialapi/workers/integration/webhook/services"
	"strconv"

	"labix.org/v2/mgo"

	"github.com/koding/logging"
)

type Handler struct {
	log logging.Logger
	bot *webhook.Bot
	sf  *services.ServiceFactory
}

func NewHandler(l logging.Logger) (*Handler, error) {
	bot, err := webhook.NewBot()
	if err != nil {
		return nil, err
	}

	return &Handler{
		log: l,
		bot: bot,
		sf:  services.NewServiceFactory(),
	}, nil
}

func (h *Handler) Push(u *url.URL, header http.Header, r *WebhookRequest) (int, http.Header, interface{}, error) {
	val := u.Query().Get("token")
	r.Token = val

	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	channelIntegration, err := r.verify()
	if err == webhook.ErrChannelIntegrationNotFound {
		return response.NewAccessDenied(ErrTokenNotValid)
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	r.Message.ChannelIntegrationId = channelIntegration.Id

	if err := h.bot.SendMessage(r.Message); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(nil)
}

func (h *Handler) Prepare(u *url.URL, header http.Header, request services.ServiceInput) (int, http.Header, interface{}, error) {
	r := new(PrepareRequest)
	r.Data = &request

	token := u.Query().Get("token")
	r.Token = token
	name := u.Query().Get("name")
	r.Name = name

	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	_, err := r.verify()
	if err == webhook.ErrIntegrationNotFound {
		return response.NewNotFound()
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	service, err := h.sf.Create(name, r.Data)
	if err != nil {
		return response.NewBadRequest(err)
	}

	errs := service.Validate(r.Data)
	if len(errs) > 0 {
		// TODO we need another bad request method here for showing validation errors
		return response.NewBadRequest(errs[0])
	}

	message := service.PrepareMessage(r.Data)

	endPoint := service.PrepareEndpoint(r.Token)
	pushRequest := make(map[string]string)
	pushRequest["body"] = message

	so := service.Output(r.Data)

	channelId, err := h.fetchChannelId(so)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if channelId != 0 {
		pushRequest["channelId"] = strconv.FormatInt(channelId, 10)
	}

	if err := push(endPoint, pushRequest); err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(nil)
}

func (h *Handler) FetchBotChannel(u *url.URL, header http.Header, r *BotChannelRequest) (int, http.Header, interface{}, error) {
	nick := u.Query().Get("nick")
	r.Username = nick
	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	c, err := h.fetchBotChannel(r)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(map[string]string{"channelId": strconv.FormatInt(c.Id, 10)})
}

func (h *Handler) fetchBotChannel(r *BotChannelRequest) (*models.Channel, error) {
	// check account existence
	acc, err := r.verifyAccount()
	if err != nil {
		return nil, err
	}

	// check group existence
	group, err := r.verifyGroup()
	if err != nil {
		return nil, err
	}

	// prevent sending bot messages when the user is not participant
	// of the given group
	canOpen, err := group.CanOpen(acc.Id)
	if err != nil {
		return nil, err
	}

	if !canOpen {
		return nil, ErrAccountIsNotParticipant
	}

	// now we can fetch the bot channel
	return h.bot.FetchBotChannel(acc, group)
}

func (h *Handler) fetchChannelId(so *services.ServiceOutput) (int64, error) {

	if err := h.prepareUsername(so); err != nil {
		return 0, err
	}

	if so.Username == "" {
		return 0, nil
	}

	br := new(BotChannelRequest)
	br.Username = so.Username
	br.GroupName = so.GroupName
	c, err := h.fetchBotChannel(br)
	if err != nil {
		return 0, err
	}

	return c.Id, nil
}

func (h *Handler) prepareUsername(so *services.ServiceOutput) error {

	if so.Username != "" {
		return nil
	}

	if so.Email == "" {
		return nil
	}

	// TODO instead of fetching directly from mongo
	// we can fetch these via an endpoint
	user, err := modelhelper.FetchUserByEmail(so.Email)
	if err == mgo.ErrNotFound {
		return ErrEmailNotFound
	}

	if err != nil {
		return err
	}

	so.Username = user.Name

	return nil
}

// TODO need to mock the endpoint. up till that time, this push method is
// defined like this
var push = func(endPoint string, pushRequest map[string]string) error {

	// relay the cookie to other endpoint
	request := &handler.Request{
		Type:     "POST",
		Endpoint: endPoint,
		Params:   pushRequest,
	}

	resp, err := handler.MakeRequest(request)
	if err != nil {
		return err
	}
	// Need a better response
	if resp.StatusCode != 200 {
		return fmt.Errorf(resp.Status)
	}

	var cpr models.CheckParticipationResponse
	err = json.NewDecoder(resp.Body).Decode(&cpr)
	resp.Body.Close()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>webhook: return success object as success response<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/common/handler"
	"socialapi/workers/common/response"
	"socialapi/workers/integration/webhook"
	"socialapi/workers/integration/webhook/services"
	"strconv"

	"labix.org/v2/mgo"

	"github.com/koding/logging"
)

type Handler struct {
	log logging.Logger
	bot *webhook.Bot
	sf  *services.ServiceFactory
}

func NewHandler(l logging.Logger) (*Handler, error) {
	bot, err := webhook.NewBot()
	if err != nil {
		return nil, err
	}

	return &Handler{
		log: l,
		bot: bot,
		sf:  services.NewServiceFactory(),
	}, nil
}

func (h *Handler) Push(u *url.URL, header http.Header, r *WebhookRequest) (int, http.Header, interface{}, error) {
	val := u.Query().Get("token")
	r.Token = val

	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	channelIntegration, err := r.verify()
	if err == webhook.ErrChannelIntegrationNotFound {
		return response.NewAccessDenied(ErrTokenNotValid)
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	r.Message.ChannelIntegrationId = channelIntegration.Id

	if err := h.bot.SendMessage(&r.Message); err != nil {
		return response.NewBadRequest(err)
	}
	res := map[string]interface{}{
		"success": true,
	}

	return response.NewOK(res)
}

func (h *Handler) Prepare(u *url.URL, header http.Header, request services.ServiceInput) (int, http.Header, interface{}, error) {
	r := new(PrepareRequest)
	r.Data = &request

	token := u.Query().Get("token")
	r.Token = token
	name := u.Query().Get("name")
	r.Name = name

	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	_, err := r.verify()
	if err == webhook.ErrIntegrationNotFound {
		return response.NewNotFound()
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	service, err := h.sf.Create(name, r.Data)
	if err != nil {
		return response.NewBadRequest(err)
	}

	errs := service.Validate(r.Data)
	if len(errs) > 0 {
		// TODO we need another bad request method here for showing validation errors
		return response.NewBadRequest(errs[0])
	}

	message := service.PrepareMessage(r.Data)

	endPoint := service.PrepareEndpoint(r.Token)
	pushRequest := make(map[string]string)
	pushRequest["body"] = message

	so := service.Output(r.Data)

	channelId, err := h.fetchChannelId(so)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if channelId != 0 {
		pushRequest["channelId"] = strconv.FormatInt(channelId, 10)
	}
	if err := push(endPoint, pushRequest); err != nil {
		return response.NewBadRequest(err)
	}

	res := map[string]interface{}{
		"success": true,
	}

	return response.NewOK(res)
}

func (h *Handler) FetchBotChannel(u *url.URL, header http.Header, r *BotChannelRequest) (int, http.Header, interface{}, error) {
	nick := u.Query().Get("nick")
	r.Username = nick
	if err := r.validate(); err != nil {
		return response.NewBadRequest(err)
	}

	c, err := h.fetchBotChannel(r)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewOK(map[string]string{"channelId": strconv.FormatInt(c.Id, 10)})
}

func (h *Handler) fetchBotChannel(r *BotChannelRequest) (*models.Channel, error) {
	// check account existence
	acc, err := r.verifyAccount()
	if err != nil {
		return nil, err
	}

	// check group existence
	group, err := r.verifyGroup()
	if err != nil {
		return nil, err
	}

	// prevent sending bot messages when the user is not participant
	// of the given group
	canOpen, err := group.CanOpen(acc.Id)
	if err != nil {
		return nil, err
	}

	if !canOpen {
		return nil, ErrAccountIsNotParticipant
	}

	// now we can fetch the bot channel
	return h.bot.FetchBotChannel(acc, group)
}

func (h *Handler) fetchChannelId(so *services.ServiceOutput) (int64, error) {

	if err := h.prepareUsername(so); err != nil {
		return 0, err
	}

	if so.Username == "" {
		return 0, nil
	}

	br := new(BotChannelRequest)
	br.Username = so.Username
	br.GroupName = so.GroupName
	c, err := h.fetchBotChannel(br)
	if err != nil {
		return 0, err
	}

	return c.Id, nil
}

func (h *Handler) prepareUsername(so *services.ServiceOutput) error {

	if so.Username != "" {
		return nil
	}

	if so.Email == "" {
		return nil
	}

	// TODO instead of fetching directly from mongo
	// we can fetch these via an endpoint
	user, err := modelhelper.FetchUserByEmail(so.Email)
	if err == mgo.ErrNotFound {
		return ErrEmailNotFound
	}

	if err != nil {
		return err
	}

	so.Username = user.Name

	return nil
}

// TODO need to mock the endpoint. up till that time, this push method is
// defined like this
var push = func(endPoint string, pushRequest map[string]string) error {

	// relay the cookie to other endpoint
	request := &handler.Request{
		Type:     "POST",
		Endpoint: endPoint,
		Params:   pushRequest,
	}

	resp, err := handler.MakeRequest(request)
	if err != nil {
		return err
	}
	// Need a better response
	if resp.StatusCode != 200 {
		return fmt.Errorf(resp.Status)
	}

	var cpr models.CheckParticipationResponse
	err = json.NewDecoder(resp.Body).Decode(&cpr)
	resp.Body.Close()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>