<commit_before>package html

import (
	"code.google.com/p/go.net/html"
	"errors"
	"io"
	"regexp"
	"unicode"
)

const (
	// We remember a few special node types when descending into their
	// children.
	AncestorArticle = 1 << iota
	AncestorAside
	AncestorBlockquote
	AncestorList
)

var (
	ignorePattern = regexp.MustCompile("(?i)comment|caption|credit|header|foot|blq-dotcom|story-feature|related")
)

type Document struct {
	Title  *Chunk   // the <title>...</title> text
	Chunks []*Chunk // list of all chunks found in this document

	// Unexported fields.
	root *html.Node // the ... part
	head *html.Node // the ... part
	body *html.Node // the ... part

	// State variables used when collectiong chunks.
	ancestors int // bitmask which stores ancestor of the current node

	// Number of non-space characters inside link tags / normal tags
	// per html.ElementNode.
	linkText map[*html.Node]int // length of text inside  tags
	normText map[*html.Node]int // length of text outside  tags
}

func NewDocument(r io.Reader) (*Document, error) {
	doc := new(Document)
	doc.Chunks = make([]*Chunk, 0, 512)
	if err := doc.Parse(r); err != nil {
		return nil, err
	}
	return doc, nil
}

func (doc *Document) Parse(r io.Reader) error {
	root, err := html.Parse(r)
	if err != nil {
		return err
	}
	// Assign the fields root, head and body from the HTML page.
	doc.setNodes(root)

	// Check if ,  and  nodes were found.
	if doc.root == nil || doc.head == nil || doc.body == nil {
		return errors.New("Document missing ,  or .")
	}

	doc.parseHead(doc.head)

	// No title found? The title plays a crucial role in detecting
	// the article content. We need it and every page should contain it.
	// So skip parsing in case we could not find a title.
	if doc.Title == nil {
		return errors.New("Document missing <title>.")
	}
	doc.linkText = make(map[*html.Node]int)
	doc.normText = make(map[*html.Node]int)

	doc.cleanBody(doc.body, 0)
	doc.countText(doc.body, false)
	doc.parseBody(doc.body)

	// Now link the chunks.
	for i := range doc.Chunks {
		if i > 0 {
			doc.Chunks[i].Prev = doc.Chunks[i-1]
		}
		if i < len(doc.Chunks)-1 {
			doc.Chunks[i].Next = doc.Chunks[i+1]
		}
	}
	return nil
}

// Assign the struct fields root, head and body from the HTML tree of node n.
//  doc.root ->
//  doc.head ->
//  doc.body ->
func (doc *Document) setNodes(n *html.Node) {
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		switch c.Data {
		case "html":
			doc.root = c
			doc.setNodes(c)
		case "body":
			doc.body = c
		case "head":
			doc.head = c
		}
	}
}

// parseHead parses the ... part of the HTML page. Right now it
// only detects the <title>...</title>.
func (doc *Document) parseHead(n *html.Node) {
	if n.Type == html.ElementNode && n.Data == "title" {
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Title = chunk
		}
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		doc.parseHead(c)
	}
}

// countText counts the link text and the normal text per html.Node.
// "Link text" is text inside  tags and "normal text" is text inside
// anything but  tags. Of course, counting is done cumulative, so the
// numbers of a parent node include the numbers of it's child nodes.
func (doc *Document) countText(n *html.Node, insideLink bool) (linkText int, normText int) {
	linkText = 0
	normText = 0
	if n.Type == html.ElementNode && n.Data == "a" {
		insideLink = true
	}
	for s := n.FirstChild; s != nil; s = s.NextSibling {
		linkTextChild, normTextChild := doc.countText(s, insideLink)
		linkText += linkTextChild
		normText += normTextChild
	}
	if n.Type == html.TextNode {
		count := 0
		for _, rune := range n.Data {
			if unicode.IsLetter(rune) {
				count += 1
			}
		}
		if insideLink {
			linkText += count
		} else {
			normText += count
		}
	}
	doc.linkText[n] = linkText
	doc.normText[n] = normText
	return
}

// cleanBody removes unwanted HTML elements from the HTML body.
func (doc *Document) cleanBody(n *html.Node, level int) {

	// removeNode returns true if a node should be removed from HTML document.
	removeNode := func(c *html.Node, level int) bool {
		switch c.Data {
		// Elements save to ignore.
		case "address", "audio", "button", "canvas", "caption", "fieldset",
			"figcaption", "figure", "footer", "form", "frame", "header",
			"iframe", "map", "menu", "nav", "noscript", "object", "option",
			"output", "script", "select", "style", "svg", "textarea", "video":
			return true
		// High-level tables might be used to layout the document, so we better
		// not ignore them.
		case "table":
			return level > 5
		}
		return false
	}

	var curr *html.Node = n.FirstChild
	var next *html.Node = nil
	for ; curr != nil; curr = next {
		// We have to remember the next sibling here becase calling RemoveChild
		// sets curr's NextSibling pointer to nil and we would quit the loop
		// prematurely.
		next = curr.NextSibling
		if curr.Type == html.ElementNode {
			if removeNode(curr, level) {
				n.RemoveChild(curr)
			} else {
				doc.cleanBody(curr, level+1)
			}
		}
	}
}

// parseBody parses the ... part of the HTML page. It creates
// Chunks for every html.TextNode found in the body.
func (doc *Document) parseBody(n *html.Node) {
	switch n.Type {
	case html.ElementNode:
		// We ignore the node if it has some nasty classes/ids/itemprobs.
		for _, attr := range n.Attr {
			switch attr.Key {
			case "id", "class", "itemprop":
				if ignorePattern.FindStringIndex(attr.Val) != nil {
					return
				}
			}
		}
		ancestorMask := 0
		switch n.Data {
		// We convert headings and links to text immediately. This is easier
		// and feasible because headings and links don't contain many children.
		// Descending into these children and handling every TextNode separately
		// would make things unnecessary complicated and our results noisy.
		case "h1", "h2", "h3", "h4", "h5", "h6", "a":
			if chunk, err := NewChunk(doc, n); err == nil {
				doc.Chunks = append(doc.Chunks, chunk)
			}
			return
		// Now mask the element type, but only if it isn't already set.
		// If we mask a bit which was already set by one of our callers, we'd also
		// clear it at the end of this function, though it actually should be cleared
		// by the caller.
		case "article":
			ancestorMask = AncestorArticle &^ doc.ancestors
		case "aside":
			ancestorMask = AncestorAside &^ doc.ancestors
		case "blockquote":
			ancestorMask = AncestorBlockquote &^ doc.ancestors
		case "ul", "ol":
			ancestorMask = AncestorList &^ doc.ancestors
		}
		// Add our mask to the ancestor bitmask.
		doc.ancestors |= ancestorMask
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			doc.parseBody(c)
		}
		// Remove our mask from the ancestor bitmask.
		doc.ancestors &^= ancestorMask
	case html.TextNode:
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Chunks = append(doc.Chunks, chunk)
		}
	}
}

type TextStat struct {
	Words     int
	Sentences int
	Count     int
}

// GetClassStats groups the document chunks by their classes (defined by the
// class attribute of HTML nodes) and calculates TextStats for each class.
func (doc *Document) GetClassStats() map[string]*TextStat {
	result := make(map[string]*TextStat)
	for _, chunk := range doc.Chunks {
		for _, class := range chunk.Classes {
			if stat, ok := result[class]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				result[class] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
		}
	}
	return result
}

// GetClusterStats groups the document chunks by common ancestors and
// calculates TextStats for each group of chunks.
func (doc *Document) GetClusterStats() map[*Chunk]*TextStat {
	// Don't ascend further than this constant.
	const maxAncestors = 3

	// Count TextStats for Chunk ancestors.
	ancestorStat := make(map[*html.Node]*TextStat)
	for _, chunk := range doc.Chunks {
		node, count := chunk.Block, 0
		for node != nil && count < maxAncestors {
			if stat, ok := ancestorStat[node]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				ancestorStat[node] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
			node, count = node.Parent, count+1
		}
	}

	// Generate result.
	result := make(map[*Chunk]*TextStat)
	for _, chunk := range doc.Chunks {
		node := chunk.Block
		if node == nil {
			continue
		}
		// Start with the parent's TextStat. Then ascend and check if the
		// current chunk has an ancestor with better stats. Use the best stat
		// as result.
		stat := ancestorStat[node]
		for {
			if node = node.Parent; node == nil {
				break
			}
			if statPrev, ok := ancestorStat[node]; ok {
				if stat.Count < statPrev.Count {
					stat = statPrev
				}
			} else {
				break
			}
		}
		result[chunk] = stat
	}
	return result
}
<commit_msg>don't ignore header classes, ignore description classes<commit_after>package html

import (
	"code.google.com/p/go.net/html"
	"errors"
	"io"
	"regexp"
	"unicode"
)

const (
	// We remember a few special node types when descending into their
	// children.
	AncestorArticle = 1 << iota
	AncestorAside
	AncestorBlockquote
	AncestorList
)

var (
	ignorePattern = regexp.MustCompile("(?i)comment|caption|description|credit|foot|blq-dotcom|story-feature|related")
)

type Document struct {
	Title  *Chunk   // the <title>...</title> text
	Chunks []*Chunk // list of all chunks found in this document

	// Unexported fields.
	root *html.Node // the ... part
	head *html.Node // the ... part
	body *html.Node // the ... part

	// State variables used when collectiong chunks.
	ancestors int // bitmask which stores ancestor of the current node

	// Number of non-space characters inside link tags / normal tags
	// per html.ElementNode.
	linkText map[*html.Node]int // length of text inside  tags
	normText map[*html.Node]int // length of text outside  tags
}

func NewDocument(r io.Reader) (*Document, error) {
	doc := new(Document)
	doc.Chunks = make([]*Chunk, 0, 512)
	if err := doc.Parse(r); err != nil {
		return nil, err
	}
	return doc, nil
}

func (doc *Document) Parse(r io.Reader) error {
	root, err := html.Parse(r)
	if err != nil {
		return err
	}
	// Assign the fields root, head and body from the HTML page.
	doc.setNodes(root)

	// Check if ,  and  nodes were found.
	if doc.root == nil || doc.head == nil || doc.body == nil {
		return errors.New("Document missing ,  or .")
	}

	doc.parseHead(doc.head)

	// No title found? The title plays a crucial role in detecting
	// the article content. We need it and every page should contain it.
	// So skip parsing in case we could not find a title.
	if doc.Title == nil {
		return errors.New("Document missing <title>.")
	}
	doc.linkText = make(map[*html.Node]int)
	doc.normText = make(map[*html.Node]int)

	doc.cleanBody(doc.body, 0)
	doc.countText(doc.body, false)
	doc.parseBody(doc.body)

	// Now link the chunks.
	for i := range doc.Chunks {
		if i > 0 {
			doc.Chunks[i].Prev = doc.Chunks[i-1]
		}
		if i < len(doc.Chunks)-1 {
			doc.Chunks[i].Next = doc.Chunks[i+1]
		}
	}
	return nil
}

// Assign the struct fields root, head and body from the HTML tree of node n.
//  doc.root ->
//  doc.head ->
//  doc.body ->
func (doc *Document) setNodes(n *html.Node) {
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		switch c.Data {
		case "html":
			doc.root = c
			doc.setNodes(c)
		case "body":
			doc.body = c
		case "head":
			doc.head = c
		}
	}
}

// parseHead parses the ... part of the HTML page. Right now it
// only detects the <title>...</title>.
func (doc *Document) parseHead(n *html.Node) {
	if n.Type == html.ElementNode && n.Data == "title" {
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Title = chunk
		}
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		doc.parseHead(c)
	}
}

// countText counts the link text and the normal text per html.Node.
// "Link text" is text inside  tags and "normal text" is text inside
// anything but  tags. Of course, counting is done cumulative, so the
// numbers of a parent node include the numbers of it's child nodes.
func (doc *Document) countText(n *html.Node, insideLink bool) (linkText int, normText int) {
	linkText = 0
	normText = 0
	if n.Type == html.ElementNode && n.Data == "a" {
		insideLink = true
	}
	for s := n.FirstChild; s != nil; s = s.NextSibling {
		linkTextChild, normTextChild := doc.countText(s, insideLink)
		linkText += linkTextChild
		normText += normTextChild
	}
	if n.Type == html.TextNode {
		count := 0
		for _, rune := range n.Data {
			if unicode.IsLetter(rune) {
				count += 1
			}
		}
		if insideLink {
			linkText += count
		} else {
			normText += count
		}
	}
	doc.linkText[n] = linkText
	doc.normText[n] = normText
	return
}

// cleanBody removes unwanted HTML elements from the HTML body.
func (doc *Document) cleanBody(n *html.Node, level int) {

	// removeNode returns true if a node should be removed from HTML document.
	removeNode := func(c *html.Node, level int) bool {
		switch c.Data {
		// Elements save to ignore.
		case "address", "audio", "button", "canvas", "caption", "fieldset",
			"figcaption", "figure", "footer", "form", "frame", "iframe",
			"map", "menu", "nav", "noscript", "object", "option", "output",
			"script", "select", "style", "svg", "textarea", "video":
			return true
		// High-level tables might be used to layout the document, so we better
		// not ignore them.
		case "table":
			return level > 5
		}
		return false
	}

	var curr *html.Node = n.FirstChild
	var next *html.Node = nil
	for ; curr != nil; curr = next {
		// We have to remember the next sibling here becase calling RemoveChild
		// sets curr's NextSibling pointer to nil and we would quit the loop
		// prematurely.
		next = curr.NextSibling
		if curr.Type == html.ElementNode {
			if removeNode(curr, level) {
				n.RemoveChild(curr)
			} else {
				doc.cleanBody(curr, level+1)
			}
		}
	}
}

// parseBody parses the ... part of the HTML page. It creates
// Chunks for every html.TextNode found in the body.
func (doc *Document) parseBody(n *html.Node) {
	switch n.Type {
	case html.ElementNode:
		// We ignore the node if it has some nasty classes/ids/itemprobs.
		for _, attr := range n.Attr {
			switch attr.Key {
			case "id", "class", "itemprop":
				if ignorePattern.FindStringIndex(attr.Val) != nil {
					return
				}
			}
		}
		ancestorMask := 0
		switch n.Data {
		// We convert headings and links to text immediately. This is easier
		// and feasible because headings and links don't contain many children.
		// Descending into these children and handling every TextNode separately
		// would make things unnecessary complicated and our results noisy.
		case "h1", "h2", "h3", "h4", "h5", "h6", "a":
			if chunk, err := NewChunk(doc, n); err == nil {
				doc.Chunks = append(doc.Chunks, chunk)
			}
			return
		// Now mask the element type, but only if it isn't already set.
		// If we mask a bit which was already set by one of our callers, we'd also
		// clear it at the end of this function, though it actually should be cleared
		// by the caller.
		case "article":
			ancestorMask = AncestorArticle &^ doc.ancestors
		case "aside":
			ancestorMask = AncestorAside &^ doc.ancestors
		case "blockquote":
			ancestorMask = AncestorBlockquote &^ doc.ancestors
		case "ul", "ol":
			ancestorMask = AncestorList &^ doc.ancestors
		}
		// Add our mask to the ancestor bitmask.
		doc.ancestors |= ancestorMask
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			doc.parseBody(c)
		}
		// Remove our mask from the ancestor bitmask.
		doc.ancestors &^= ancestorMask
	case html.TextNode:
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Chunks = append(doc.Chunks, chunk)
		}
	}
}

type TextStat struct {
	Words     int
	Sentences int
	Count     int
}

// GetClassStats groups the document chunks by their classes (defined by the
// class attribute of HTML nodes) and calculates TextStats for each class.
func (doc *Document) GetClassStats() map[string]*TextStat {
	result := make(map[string]*TextStat)
	for _, chunk := range doc.Chunks {
		for _, class := range chunk.Classes {
			if stat, ok := result[class]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				result[class] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
		}
	}
	return result
}

// GetClusterStats groups the document chunks by common ancestors and
// calculates TextStats for each group of chunks.
func (doc *Document) GetClusterStats() map[*Chunk]*TextStat {
	// Don't ascend further than this constant.
	const maxAncestors = 3

	// Count TextStats for Chunk ancestors.
	ancestorStat := make(map[*html.Node]*TextStat)
	for _, chunk := range doc.Chunks {
		node, count := chunk.Block, 0
		for node != nil && count < maxAncestors {
			if stat, ok := ancestorStat[node]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				ancestorStat[node] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
			node, count = node.Parent, count+1
		}
	}

	// Generate result.
	result := make(map[*Chunk]*TextStat)
	for _, chunk := range doc.Chunks {
		node := chunk.Block
		if node == nil {
			continue
		}
		// Start with the parent's TextStat. Then ascend and check if the
		// current chunk has an ancestor with better stats. Use the best stat
		// as result.
		stat := ancestorStat[node]
		for {
			if node = node.Parent; node == nil {
				break
			}
			if statPrev, ok := ancestorStat[node]; ok {
				if stat.Count < statPrev.Count {
					stat = statPrev
				}
			} else {
				break
			}
		}
		result[chunk] = stat
	}
	return result
}
<|endoftext|>


<commit_before>package web

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

	"github.com/gocraft/web"
	"github.com/varunamachi/orek/data"
)

type Context struct {
	SessionUser  data.User
	CreationTime time.Duration
}

func checkSession(context *Context) bool {
	return true
}

func (c *Context) SessionChecker(rw web.ResponseWriter,
	req *web.Request,
	next web.NextMiddlewareFunc) {
	//get the session ID
	//see if it is still valid
	//put the user and session objects into the context object
	next(rw, req)
}

func (c *Context) Login(resp web.ResponseWriter, req *web.Request) {
	//Get the user name and password from the request
	//Authenticate the user and create the user object, put the user into
	// context
	//Check if the current session already registered to some other login
	//if so expire this session
	//Create a new session in the session table
	//	userName := req.FormValue("userName")
	//	password := req.FormValue("password")
	//	sessionId := req.FormValue("sessionId")
	//	data.DataSource().GetUser("varun").FirstName

	//	data.DataSource().GetUser(
}

func (c *Context) Logout(resp web.ResponseWriter, req *web.Request) {
	//resp.Write
}

func (c *Context) GetAllUsers(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}
	users, err := data.DataSource().GetAllUsers()
	if err == nil {
		marshalled, err := json.Marshal(users)
		if err == nil {
			fmt.Fprintf(resp, string(marshalled))
		} else {
			fmt.Fprintf(resp, "!Error:MarshalError")
		}
	} else {
		fmt.Fprintf(resp, "!Error:DataSourceError")
	}
}

func (c *Context) GetUser(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}
	userName := req.FormValue("userName")
	user, err := data.DataSource().GetUser(userName)
	if err == nil {
		mrsh, err := json.Marshal(user)
		if err == nil {
			fmt.Fprintf(resp, string(mrsh))
		} else {
			fmt.Fprintf(resp, "!Error:Marshal Error")
		}
	} else {
		fmt.Fprintf(resp, "!Error:DataSource Error")
	}
}

func (c *Context) CreateUser(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) DeleteUser(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}
}

func (c *Context) GetAllSources(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetSource(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetSourceWithId(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) CreateOrUpdateSource(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) DeleteSource(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetAllVariables(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetVariable(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetVariableWithId(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) CreateOrUpdateVariable(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) DeleteVariable(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetAllUserGroups(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetUserGroup(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) CreateOrUpdateUserGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) DeleteUserGroup(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetAllVariableGroups(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetVariableGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetVariableGroupWithId(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) CreateOrUpdateVariableGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) DeleteVariableGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) AddUserToGroup(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) RemoveUserFromGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetUsersInGroup(resp web.ResponseWriter, req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetGroupsForUser(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) AddVariableToGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) RemoveVariableFromGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetVariablesInGroup(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetGroupsForVariable(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) AddVariableValue(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) ClearValuesForVariable(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func (c *Context) GetValuesForVariable(resp web.ResponseWriter,
	req *web.Request) {
	if !checkSession(c) {
		fmt.Fprintf(resp, "!Error:Session Error")
		return
	}

}

func Setup() error {

	return nil
}
<commit_msg>Removed unnessary check for session<commit_after>package web

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

	"github.com/gocraft/web"
	"github.com/varunamachi/orek/data"
)

type Context struct {
	SessionUser  data.User
	CreationTime time.Duration
}

func checkSession(context *Context) bool {
	return true
}

func (c *Context) SessionChecker(rw web.ResponseWriter,
	req *web.Request,
	next web.NextMiddlewareFunc) {
	//get the session ID
	//see if it is still valid
	//put the user and session objects into the context object
	next(rw, req)
}

func (c *Context) Login(resp web.ResponseWriter, req *web.Request) {
	//Get the user name and password from the request
	//Authenticate the user and create the user object, put the user into
	// context
	//Check if the current session already registered to some other login
	//if so expire this session
	//Create a new session in the session table
	//	userName := req.FormValue("userName")
	//	password := req.FormValue("password")
	//	sessionId := req.FormValue("sessionId")
	//	data.DataSource().GetUser("varun").FirstName

	//	data.DataSource().GetUser(
}

func (c *Context) Logout(resp web.ResponseWriter, req *web.Request) {
	//resp.Write
}

func (c *Context) GetAllUsers(resp web.ResponseWriter, req *web.Request) {
	users, err := data.DataSource().GetAllUsers()
	if err == nil {
		marshalled, err := json.Marshal(users)
		if err == nil {
			fmt.Fprintf(resp, string(marshalled))
		} else {
			fmt.Fprintf(resp, "!Error:MarshalError")
		}
	} else {
		fmt.Fprintf(resp, "!Error:DataSourceError")
	}
}

func (c *Context) GetUser(resp web.ResponseWriter, req *web.Request) {
	userName := req.PathParams["userName"]
	user, err := data.DataSource().GetUser(userName)
	if err == nil {
		mrsh, err := json.Marshal(user)
		if err == nil {
			fmt.Fprintf(resp, string(mrsh))
		} else {
			fmt.Fprintf(resp, "!Error:Marshal Error")
		}
	} else {
		fmt.Fprintf(resp, "!Error:DataSource Error")
	}
}

func (c *Context) CreateUser(resp web.ResponseWriter, req *web.Request) {
	//jsonValue := req.FormValue("userDetail")
	//user := json.Unmarshal(
	//err := data.DataSource().CreateOrUpdateUser(user)

}

func (c *Context) DeleteUser(resp web.ResponseWriter, req *web.Request) {
}

func (c *Context) GetAllSources(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetSource(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetSourceWithId(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) CreateOrUpdateSource(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) DeleteSource(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetAllVariables(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetVariable(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetVariableWithId(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) CreateOrUpdateVariable(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) DeleteVariable(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetAllUserGroups(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetUserGroup(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) CreateOrUpdateUserGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) DeleteUserGroup(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetAllVariableGroups(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetVariableGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetVariableGroupWithId(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) CreateOrUpdateVariableGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) DeleteVariableGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) AddUserToGroup(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) RemoveUserFromGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetUsersInGroup(resp web.ResponseWriter, req *web.Request) {

}

func (c *Context) GetGroupsForUser(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) AddVariableToGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) RemoveVariableFromGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetVariablesInGroup(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetGroupsForVariable(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) AddVariableValue(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) ClearValuesForVariable(resp web.ResponseWriter,
	req *web.Request) {

}

func (c *Context) GetValuesForVariable(resp web.ResponseWriter,
	req *web.Request) {

}

func Setup() error {

	return nil
}
<|endoftext|>


<commit_before>package core

import (
	"github.com/aws/aws-sdk-go/service/rds"
)

// Returns all DB instances based on the input given
func (c *Connector) GetDBInstances(input *rds.DescribeDBInstancesInput) ([]*rds.DescribeDBInstancesOutput, Errs) {
	var errs Errs
	var instances []*rds.DescribeDBInstancesOutput

	for _, svc := range c.svcs {
		if svc.rds == nil {
			svc.rds = rds.New(svc.session)
		}
		elb, err := svc.rds.DescribeDBInstances(input)
		if err != nil {
			errs = append(errs, NewAPIError(svc.region, rds.ServiceName, err))
		} else {
			instances = append(instances, elb)
		}
	}
	return instances, errs
}

// Returns a list of tags from an ARN, extra filters for tags can also be provided
// For more information, please see: https://docs.aws.amazon.com/sdk-for-go/api/service/rds/#Filter
func (c *Connector) GetDBInstancesTags(input *rds.ListTagsForResourceInput) ([]*rds.ListTagsForResourceOutput, Errs) {
	var errs Errs
	var rdsTags []*rds.ListTagsForResourceOutput

	for _, svc := range c.svcs {
		if svc.rds == nil {
			svc.rds = rds.New(svc.session)
		}
		rdsTag, err := svc.rds.ListTagsForResource(input)
		if err != nil {
			errs = append(errs, NewAPIError(svc.region, rds.ServiceName, err))
		} else {
			rdsTags = append(rdsTags, rdsTag)
		}
	}
	return rdsTags, errs
}
<commit_msg>rds: fix wrong variable names in AWS calls<commit_after>package core

import (
	"github.com/aws/aws-sdk-go/service/rds"
)

// Returns all DB instances based on the input given
func (c *Connector) GetDBInstances(input *rds.DescribeDBInstancesInput) ([]*rds.DescribeDBInstancesOutput, Errs) {
	var errs Errs
	var instances []*rds.DescribeDBInstancesOutput

	for _, svc := range c.svcs {
		if svc.rds == nil {
			svc.rds = rds.New(svc.session)
		}
		instance, err := svc.rds.DescribeDBInstances(input)
		if err != nil {
			errs = append(errs, NewAPIError(svc.region, rds.ServiceName, err))
		} else {
			instances = append(instances, instance)
		}
	}
	return instances, errs
}

// Returns a list of tags from an ARN, extra filters for tags can also be provided
// For more information, please see: https://docs.aws.amazon.com/sdk-for-go/api/service/rds/#Filter
func (c *Connector) GetDBInstancesTags(input *rds.ListTagsForResourceInput) ([]*rds.ListTagsForResourceOutput, Errs) {
	var errs Errs
	var rdsTags []*rds.ListTagsForResourceOutput

	for _, svc := range c.svcs {
		if svc.rds == nil {
			svc.rds = rds.New(svc.session)
		}
		rdsTag, err := svc.rds.ListTagsForResource(input)
		if err != nil {
			errs = append(errs, NewAPIError(svc.region, rds.ServiceName, err))
		} else {
			rdsTags = append(rdsTags, rdsTag)
		}
	}
	return rdsTags, errs
}
<|endoftext|>


<commit_before>package core

import (
	"github.com/bulletind/khabar/db"
	"github.com/bulletind/khabar/dbapi/pending"
	"github.com/bulletind/khabar/dbapi/saved_item"
	"github.com/bulletind/khabar/dbapi/sent"
)

func webHandler(item *pending.PendingItem, text string,
	settings map[string]interface{}) {

	sent_item := db.SentItem{
		CreatedBy:      item.CreatedBy,
		AppName:        item.AppName,
		Organization:   item.Organization,
		User:           item.User,
		IsRead:         false,
		Topic:          item.Topic,
		DestinationUri: item.DestinationUri,
		Text:           text,
		Context:        item.Context,
		Entity:         item.Entity,
	}

	sent_item.PrepareSave()

	sent.Insert(&sent_item)

	saved_item.Insert(db.SavedWebCollection, &db.SavedItem{Data: sent_item})
}
<commit_msg>Do not save saved_item twice<commit_after>package core

import (
	"github.com/bulletind/khabar/db"
	"github.com/bulletind/khabar/dbapi/pending"
	"github.com/bulletind/khabar/dbapi/sent"
)

func webHandler(item *pending.PendingItem, text string,
	settings map[string]interface{}) {

	sent_item := db.SentItem{
		CreatedBy:      item.CreatedBy,
		AppName:        item.AppName,
		Organization:   item.Organization,
		User:           item.User,
		IsRead:         false,
		Topic:          item.Topic,
		DestinationUri: item.DestinationUri,
		Text:           text,
		Context:        item.Context,
		Entity:         item.Entity,
	}

	sent_item.PrepareSave()
	sent.Insert(&sent_item)
}
<|endoftext|>


<commit_before>package web

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

	log "github.com/golang/glog"
	"github.com/gorilla/mux"
	"github.com/micro/cli"
	"github.com/micro/go-micro/cmd"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/selector"
	"github.com/micro/micro/internal/handler"
	"github.com/serenize/snaker"
)

var (
	re        = regexp.MustCompile("^[a-zA-Z0-9]+$")
	Address   = ":8082"
	Namespace = "go.micro.web"
)

type server struct {
	*mux.Router
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if origin := r.Header.Get("Origin"); origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		return
	}

	s.Router.ServeHTTP(w, r)
}

func (s *server) proxy() http.Handler {
	sel := selector.NewSelector(
		selector.Registry((*cmd.DefaultOptions().Registry)),
	)

	director := func(r *http.Request) {
		parts := strings.Split(r.URL.Path, "/")
		if len(parts) < 2 {
			return
		}
		if !re.MatchString(parts[1]) {
			return
		}
		next, err := sel.Select(Namespace + "." + parts[1])
		if err != nil {
			return
		}
		r.URL.Scheme = "http"
		s, err := next()
		if err != nil {
			return
		}
		r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port)
		r.URL.Path = "/" + strings.Join(parts[2:], "/")
	}
	return &httputil.ReverseProxy{
		Director: director,
	}
}

func format(v *registry.Value) string {
	if v == nil || len(v.Values) == 0 {
		return "{}"
	}
	var f []string
	for _, k := range v.Values {
		f = append(f, formatEndpoint(k, 0))
	}
	return fmt.Sprintf("{\n%s}", strings.Join(f, ""))
}

func formatEndpoint(v *registry.Value, r int) string {
	// default format is tabbed plus the value plus new line
	fparts := []string{"", "%s %s", "\n"}
	for i := 0; i < r+1; i++ {
		fparts[0] += "\t"
	}
	// its just a primitive of sorts so return
	if len(v.Values) == 0 {
		return fmt.Sprintf(strings.Join(fparts, ""), snaker.CamelToSnake(v.Name), v.Type)
	}

	// this thing has more things, it's complex
	fparts[1] += " {"

	vals := []interface{}{snaker.CamelToSnake(v.Name), v.Type}

	for _, val := range v.Values {
		fparts = append(fparts, "%s")
		vals = append(vals, formatEndpoint(val, r+1))
	}

	// at the end
	l := len(fparts) - 1
	for i := 0; i < r+1; i++ {
		fparts[l] += "\t"
	}
	fparts = append(fparts, "}\n")

	return fmt.Sprintf(strings.Join(fparts, ""), vals...)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	services, err := (*cmd.DefaultOptions().Registry).ListServices()
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}

	var webServices []string
	for _, s := range services {
		if strings.Index(s.Name, Namespace) == 0 {
			webServices = append(webServices, strings.Replace(s.Name, Namespace+".", "", 1))
		}
	}

	type templateData struct {
		HasWebServices bool
		WebServices    []string
	}

	data := templateData{len(webServices) > 0, webServices}
	render(w, r, indexTemplate, data)
}

func registryHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	svc := r.Form.Get("service")

	if len(svc) > 0 {
		s, err := (*cmd.DefaultOptions().Registry).GetService(svc)
		if err != nil {
			http.Error(w, "Error occurred:"+err.Error(), 500)
			return
		}

		if r.Header.Get("Content-Type") == "application/json" {
			b, err := json.Marshal(map[string]interface{}{
				"services": s,
			})
			if err != nil {
				http.Error(w, "Error occurred:"+err.Error(), 500)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(b)
			return
		}

		render(w, r, serviceTemplate, s)
		return
	}

	services, err := (*cmd.DefaultOptions().Registry).ListServices()
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}

	if r.Header.Get("Content-Type") == "application/json" {
		b, err := json.Marshal(map[string]interface{}{
			"services": services,
		})
		if err != nil {
			http.Error(w, "Error occurred:"+err.Error(), 500)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(b)
		return
	}

	render(w, r, registryTemplate, services)
}

func queryHandler(w http.ResponseWriter, r *http.Request) {
	render(w, r, queryTemplate, nil)
}

func render(w http.ResponseWriter, r *http.Request, tmpl string, data interface{}) {
	t, err := template.New("template").Funcs(template.FuncMap{
		"format": format,
	}).Parse(layoutTemplate)
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}
	t, err = t.Parse(tmpl)
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}
	if err := t.ExecuteTemplate(w, "layout", data); err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
	}
}

func run() {
	r := mux.NewRouter()
	s := &server{r}
	s.HandleFunc("/registry", registryHandler)
	s.HandleFunc("/rpc", handler.RPC)
	s.HandleFunc("/query", queryHandler)
	s.PathPrefix("/{service:[a-zA-Z0-9]+}").Handler(s.proxy())
	s.HandleFunc("/", indexHandler)

	log.Infof("Listening on %s", Address)

	if err := http.ListenAndServe(Address, s); err != nil {
		log.Fatal(err)
	}
}

func Commands() []cli.Command {
	return []cli.Command{
		{
			Name:  "web",
			Usage: "Run the micro web app",
			Action: func(c *cli.Context) {
				run()
			},
		},
	}
}
<commit_msg>Add X-Micro-Web-Base-Path header for proxying<commit_after>package web

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

	log "github.com/golang/glog"
	"github.com/gorilla/mux"
	"github.com/micro/cli"
	"github.com/micro/go-micro/cmd"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/selector"
	"github.com/micro/micro/internal/handler"
	"github.com/serenize/snaker"
)

var (
	re = regexp.MustCompile("^[a-zA-Z0-9]+$")
	// Default address to bind to
	Address = ":8082"
	// The namespace to serve
	// Example:
	// Namespace + /[Service]/foo/bar
	// Host: Namespace.Service Endpoint: /foo/bar
	Namespace = "go.micro.web"
	// Base path sent to web service.
	// This is stripped from the request path
	// Allows the web service to define absolute paths
	BasePathHeader = "X-Micro-Web-Base-Path"
)

type server struct {
	*mux.Router
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if origin := r.Header.Get("Origin"); origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		return
	}

	s.Router.ServeHTTP(w, r)
}

func (s *server) proxy() http.Handler {
	sel := selector.NewSelector(
		selector.Registry((*cmd.DefaultOptions().Registry)),
	)

	director := func(r *http.Request) {
		parts := strings.Split(r.URL.Path, "/")
		if len(parts) < 2 {
			return
		}
		if !re.MatchString(parts[1]) {
			return
		}
		next, err := sel.Select(Namespace + "." + parts[1])
		if err != nil {
			return
		}
		r.URL.Scheme = "http"
		s, err := next()
		if err != nil {
			return
		}

		//
		r.Header.Set(BasePathHeader, "/"+parts[1])
		r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port)
		r.URL.Path = "/" + strings.Join(parts[2:], "/")
	}
	return &httputil.ReverseProxy{
		Director: director,
	}
}

func format(v *registry.Value) string {
	if v == nil || len(v.Values) == 0 {
		return "{}"
	}
	var f []string
	for _, k := range v.Values {
		f = append(f, formatEndpoint(k, 0))
	}
	return fmt.Sprintf("{\n%s}", strings.Join(f, ""))
}

func formatEndpoint(v *registry.Value, r int) string {
	// default format is tabbed plus the value plus new line
	fparts := []string{"", "%s %s", "\n"}
	for i := 0; i < r+1; i++ {
		fparts[0] += "\t"
	}
	// its just a primitive of sorts so return
	if len(v.Values) == 0 {
		return fmt.Sprintf(strings.Join(fparts, ""), snaker.CamelToSnake(v.Name), v.Type)
	}

	// this thing has more things, it's complex
	fparts[1] += " {"

	vals := []interface{}{snaker.CamelToSnake(v.Name), v.Type}

	for _, val := range v.Values {
		fparts = append(fparts, "%s")
		vals = append(vals, formatEndpoint(val, r+1))
	}

	// at the end
	l := len(fparts) - 1
	for i := 0; i < r+1; i++ {
		fparts[l] += "\t"
	}
	fparts = append(fparts, "}\n")

	return fmt.Sprintf(strings.Join(fparts, ""), vals...)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	services, err := (*cmd.DefaultOptions().Registry).ListServices()
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}

	var webServices []string
	for _, s := range services {
		if strings.Index(s.Name, Namespace) == 0 {
			webServices = append(webServices, strings.Replace(s.Name, Namespace+".", "", 1))
		}
	}

	type templateData struct {
		HasWebServices bool
		WebServices    []string
	}

	data := templateData{len(webServices) > 0, webServices}
	render(w, r, indexTemplate, data)
}

func registryHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	svc := r.Form.Get("service")

	if len(svc) > 0 {
		s, err := (*cmd.DefaultOptions().Registry).GetService(svc)
		if err != nil {
			http.Error(w, "Error occurred:"+err.Error(), 500)
			return
		}

		if r.Header.Get("Content-Type") == "application/json" {
			b, err := json.Marshal(map[string]interface{}{
				"services": s,
			})
			if err != nil {
				http.Error(w, "Error occurred:"+err.Error(), 500)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(b)
			return
		}

		render(w, r, serviceTemplate, s)
		return
	}

	services, err := (*cmd.DefaultOptions().Registry).ListServices()
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}

	if r.Header.Get("Content-Type") == "application/json" {
		b, err := json.Marshal(map[string]interface{}{
			"services": services,
		})
		if err != nil {
			http.Error(w, "Error occurred:"+err.Error(), 500)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(b)
		return
	}

	render(w, r, registryTemplate, services)
}

func queryHandler(w http.ResponseWriter, r *http.Request) {
	render(w, r, queryTemplate, nil)
}

func render(w http.ResponseWriter, r *http.Request, tmpl string, data interface{}) {
	t, err := template.New("template").Funcs(template.FuncMap{
		"format": format,
	}).Parse(layoutTemplate)
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}
	t, err = t.Parse(tmpl)
	if err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
		return
	}
	if err := t.ExecuteTemplate(w, "layout", data); err != nil {
		http.Error(w, "Error occurred:"+err.Error(), 500)
	}
}

func run() {
	r := mux.NewRouter()
	s := &server{r}
	s.HandleFunc("/registry", registryHandler)
	s.HandleFunc("/rpc", handler.RPC)
	s.HandleFunc("/query", queryHandler)
	s.PathPrefix("/{service:[a-zA-Z0-9]+}").Handler(s.proxy())
	s.HandleFunc("/", indexHandler)

	log.Infof("Listening on %s", Address)

	if err := http.ListenAndServe(Address, s); err != nil {
		log.Fatal(err)
	}
}

func Commands() []cli.Command {
	return []cli.Command{
		{
			Name:  "web",
			Usage: "Run the micro web app",
			Action: func(c *cli.Context) {
				run()
			},
		},
	}
}
<|endoftext|>


<commit_before>package bamstats

import (
	log "github.com/Sirupsen/logrus"
	"github.com/biogo/hts/bam"
	"github.com/biogo/hts/sam"
	"github.com/brentp/bix"
	"os"
)

type ElementStats struct {
	ExonIntron int `json:"exonic_intronic"`
	Intron     int `json:"intron"`
	Exon       int `json:"exon"`
	Intergenic int `json:"intergenic"`
	Total      int `json:"total"`
}

type ReadStats struct {
	Total      ElementStats `json:"Total reads"`
	Continuous ElementStats `json:"Continuous read"`
	Split      ElementStats `json:"Split reads"`
}

func updateCount(r *sam.Record, elems map[string]uint8, st *ElementStats) {
	exons, hasExon := elems["exon"]
	introns, hasIntron := elems["intron"]
	st.Total++
	if _, isIntergenic := elems["intergenic"]; isIntergenic {
		st.Intergenic++
		return
	}
	if hasExon && !hasIntron && exons > 0 {
		st.Exon++
		return
	}
	if hasIntron && !hasExon && introns > 0 {
		st.Intron++
		return
	}
	st.ExonIntron++
}

func Coverage(bamFile string, annotation string, cpu int) ReadStats {
	stats := ReadStats{}
	f, err := os.Open(bamFile)
	defer f.Close()
	check(err)
	anno, err := bix.New(annotation)
	check(err)
	br, err := bam.NewReader(f, cpu)
	check(err)
	for {
		record, err := br.Read()
		if err != nil {
			break
		}
		if !isPrimary(record) {
			continue
		}
		elements := map[string]uint8{}
		log.Debug(record.Name)
		for _, mappingPosition := range getBlocks(record) {
			log.Debug(mappingPosition)
			eBuf, err := anno.Query(mappingPosition)
			check(err)
			getElements(mappingPosition, eBuf, elements)
		}
		stats.Total.Total++
		if isSplit(record) {
			updateCount(record, elements, &stats.Split)
		} else {
			updateCount(record, elements, &stats.Continuous)
		}
	}
	return stats
}
<commit_msg>Add stats methods and parallel coverage implementation<commit_after>package bamstats

import (
	log "github.com/Sirupsen/logrus"
	"github.com/biogo/hts/bam"
	"github.com/biogo/hts/sam"
	"github.com/brentp/bix"
	"os"
  "sync"
)

var wg sync.WaitGroup

type ElementStats struct {
	ExonIntron int `json:"exonic_intronic"`
	Intron     int `json:"intron"`
	Exon       int `json:"exon"`
	Intergenic int `json:"intergenic"`
	Total      int `json:"total"`
}

type ReadStats struct {
	Total      ElementStats `json:"Total reads"`
	Continuous ElementStats `json:"Continuous read"`
	Split      ElementStats `json:"Split reads"`
}

func (s *ReadStats) Update(other ReadStats) {
  s.Continuous.Update(other.Continuous)
  s.Split.Update(other.Split)
  s.UpdateTotal(other)
}

func (s *ReadStats) UpdateTotal(other ReadStats) {
  s.Total.Update(other.Continuous)
  s.Total.Update(other.Split)
}

func (s *ReadStats) Merge(others chan ReadStats) {
  for other := range others {
    s.Update(other)
  }
}

func (s *ElementStats) Update(other ElementStats) {
  s.ExonIntron += other.ExonIntron
  s.Exon += other.Exon
  s.Intron += other.Intron
  s.Intergenic += other.Intergenic
  s.Total += other.Total
}

func updateCount(r *sam.Record, elems map[string]uint8, st *ElementStats) {
	exons, hasExon := elems["exon"]
	introns, hasIntron := elems["intron"]
	st.Total++
	if _, isIntergenic := elems["intergenic"]; isIntergenic {
		st.Intergenic++
		return
	}
	if hasExon && !hasIntron && exons > 0 {
		st.Exon++
		return
	}
	if hasIntron && !hasExon && introns > 0 {
		st.Intron++
		return
	}
	st.ExonIntron++
}

func worker(in chan *sam.Record, out chan ReadStats, anno *bix.Bix) {
  defer wg.Done()
  stats := ReadStats{}
  for record := range in {
    elements := map[string]uint8{}
		log.Debug(record.Name)
		for _, mappingPosition := range getBlocks(record) {
			log.Debug(mappingPosition)
			eBuf, err := anno.Query(mappingPosition)
			check(err)
			getElements(mappingPosition, eBuf, elements)
		}
		if isSplit(record) {
			updateCount(record, elements, &stats.Split)
		} else {
			updateCount(record, elements, &stats.Continuous)
		}
	}
  out <- stats
}

func Coverage(bamFile string, annotation string, cpu int) ReadStats {
	f, err := os.Open(bamFile)
	defer f.Close()
	check(err)
	anno, err := bix.New(annotation, cpu)
	check(err)
	br, err := bam.NewReader(f, cpu)
	check(err)
  input := make([]chan *sam.Record, cpu)
  stats := make(chan ReadStats, cpu)
  for i := 0; i < cpu; i++ {
    wg.Add(1)
    input[i] = make(chan *sam.Record)
    go worker(input[i], stats, anno)
  }
  c := 0
	for {
    record, err := br.Read()
		if err != nil {
			break
		}
		if !isPrimary(record) {
			continue
		}
    input[c] <- record
    c = (c+1)%cpu
  }
  for i := 0; i < cpu; i++ {
    close(input[i])
  }
  wg.Wait()
  close(stats)
  st := ReadStats{}
  st.Merge(stats)
  return st
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"

	"github.com/gorilla/mux"
)

// ImplementsServer verifies that a given `*mux.Router` has handlers for
// all routes specified in `NewAPIRouter()`.
//
// We can't easily check whether a router implements the `api.Server`
// interface, as would be desired, so we rely on the knowledge that
// `*client.Client` implements `api.Server` while also depending on
// route name strings defined in this package.
//
// Returns an error if router doesn't fully implement `NewAPIRouter()`,
// nil otherwise.
func ImplementsServer(router *mux.Router) error {
	apiRouter := NewAPIRouter()
	return apiRouter.Walk(makeWalkFunc(router))
}

// makeWalkFunc creates a function which verifies that the route passed
// to it both exists in the router under test and has a handler attached.
func makeWalkFunc(router *mux.Router) mux.WalkFunc {
	return mux.WalkFunc(func(r *mux.Route, _ *mux.Router, _ []*mux.Route) error {
		// Does a route with this name exist in router?
		route := router.Get(r.GetName())
		if route == nil {
			return fmt.Errorf("no route by name %q in router", r.GetName())
		}
		// Goes the route have a handler?
		handler := route.GetHandler()
		if handler == nil {
			return fmt.Errorf("no handler for route %q in router", r.GetName())
		}
		return nil
	})
}
<commit_msg>Change goes to does<commit_after>package http

import (
	"fmt"

	"github.com/gorilla/mux"
)

// ImplementsServer verifies that a given `*mux.Router` has handlers for
// all routes specified in `NewAPIRouter()`.
//
// We can't easily check whether a router implements the `api.Server`
// interface, as would be desired, so we rely on the knowledge that
// `*client.Client` implements `api.Server` while also depending on
// route name strings defined in this package.
//
// Returns an error if router doesn't fully implement `NewAPIRouter()`,
// nil otherwise.
func ImplementsServer(router *mux.Router) error {
	apiRouter := NewAPIRouter()
	return apiRouter.Walk(makeWalkFunc(router))
}

// makeWalkFunc creates a function which verifies that the route passed
// to it both exists in the router under test and has a handler attached.
func makeWalkFunc(router *mux.Router) mux.WalkFunc {
	return mux.WalkFunc(func(r *mux.Route, _ *mux.Router, _ []*mux.Route) error {
		// Does a route with this name exist in router?
		route := router.Get(r.GetName())
		if route == nil {
			return fmt.Errorf("no route by name %q in router", r.GetName())
		}
		// Does the route have a handler?
		handler := route.GetHandler()
		if handler == nil {
			return fmt.Errorf("no handler for route %q in router", r.GetName())
		}
		return nil
	})
}
<|endoftext|>


<commit_before>package braintree

import (
	"time"
)

//Kind of webhooks.
const (
	WebhookAccountUpdaterDailyReport = "account_updater_daily_report"

	WebhookCheck = "check"

	WebhookDisbursement          = "disbursement"
	WebhookDisbursementException = "disbursement_exception"

	WebhookDisputeLost   = "dispute_lost"
	WebhookDisputeOpened = "dispute_opened"
	WebhookDisputeWon    = "dispute_won"

	WebhookSubscriptionCanceled              = "subscription_canceled"
	WebhookSubscriptionChargedSuccessfully   = "subscription_charged_successfully"
	WebhookSubscriptionChargedUnsuccessfully = "subscription_charged_unsuccessfully"
	WebhookSubscriptionExpired               = "subscription_expired"
	WebhookSubscriptionTrialEnded            = "subscription_trial_ended"
	WebhookSubscriptionWentActive            = "subscription_went_active"
	WebhookSubscriptionWentPastDue           = "subscription_went_past_due"

	WebhookSubMerchantAccountApproved = "sub_merchant_account_approved"
	WebhookSubMerchantAccountDeclined = "sub_merchant_account_declined"

	WebhookPartnerMerchantAccountConnected    = "partner_merchant_account_connected"
	WebhookPartnerMerchantAccountDisconnected = "partner_merchant_account_disconnected"
	WebhookPartnerMerchantAccountDeclined     = "partner_merchant_account_declined"

	WebhookTransactionSettled            = "transaction_settled"
	WebhookTransactionSettlementDeclined = "transaction_settlement_declined"
	WebhookTransactionDispursed          = "transaction_dispursed"
)

// WebhookNotification is an automated notifications from braintree via webhook.
type WebhookNotification struct {
	Kind      string          `xml:"kind"`
	Subject   *WebhookSubject `xml:"subject"`
	Timestamp time.Time       `xml:"timestamp"`
}

// WebhookSubject will be implemented later.
type WebhookSubject interface {
	privateWebhook()
}
<commit_msg>add  minimal support for webhooks for subscriptions, transactions<commit_after>package braintree

import (
	"time"
)

//Kind of webhooks.
const (
	WebhookAccountUpdaterDailyReport = "account_updater_daily_report"

	WebhookCheck = "check"

	WebhookDisbursement          = "disbursement"
	WebhookDisbursementException = "disbursement_exception"

	WebhookDisputeLost   = "dispute_lost"
	WebhookDisputeOpened = "dispute_opened"
	WebhookDisputeWon    = "dispute_won"

	WebhookSubscriptionCanceled              = "subscription_canceled"
	WebhookSubscriptionChargedSuccessfully   = "subscription_charged_successfully"
	WebhookSubscriptionChargedUnsuccessfully = "subscription_charged_unsuccessfully"
	WebhookSubscriptionExpired               = "subscription_expired"
	WebhookSubscriptionTrialEnded            = "subscription_trial_ended"
	WebhookSubscriptionWentActive            = "subscription_went_active"
	WebhookSubscriptionWentPastDue           = "subscription_went_past_due"

	WebhookSubMerchantAccountApproved = "sub_merchant_account_approved"
	WebhookSubMerchantAccountDeclined = "sub_merchant_account_declined"

	WebhookPartnerMerchantAccountConnected    = "partner_merchant_account_connected"
	WebhookPartnerMerchantAccountDisconnected = "partner_merchant_account_disconnected"
	WebhookPartnerMerchantAccountDeclined     = "partner_merchant_account_declined"

	WebhookTransactionSettled            = "transaction_settled"
	WebhookTransactionSettlementDeclined = "transaction_settlement_declined"
	WebhookTransactionDispursed          = "transaction_dispursed"
)

// WebhookNotification is an automated notifications from braintree via webhook.
type WebhookNotification struct {
	Kind      string         `xml:"kind"`
	Subject   WebhookSubject `xml:"subject"`
	Timestamp time.Time      `xml:"timestamp"`
}

// WebhookSubject might change in the future.
// Handles only Subscriptions and Transactions for now.
type WebhookSubject struct {
	Subscription *Subscription `xml:"subscription"`
	Transaction  *Transaction  `xml:"transaction"`
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"

	"github.com/adnanh/webhook/helpers"
	"github.com/adnanh/webhook/hook"

	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
)

const (
	version = "2.0.0"
)

var (
	ip            = flag.String("ip", "", "ip the webhook should serve hooks on")
	port          = flag.Int("port", 9000, "port the webhook should serve hooks on")
	verbose       = flag.Bool("verbose", false, "show verbose output")
	hooksFilePath = flag.String("hooks", "hooks.json", "path to the json file containing defined hooks the webhook should serve")

	hooks hook.Hooks
)

func init() {
	hooks = hook.Hooks{}

	flag.Parse()

	log.SetPrefix("[webhook] ")
	log.SetFlags(log.Ldate | log.Ltime)

	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	log.Println("version " + version + " starting")

	// load and parse hooks
	log.Printf("attempting to load hooks from %s\n", *hooksFilePath)

	err := hooks.LoadFromFile(*hooksFilePath)

	if err != nil {
		log.Printf("couldn't load hooks from file! %+v\n", err)
	} else {
		log.Printf("loaded %d hook(s) from file\n", len(hooks))

		for _, hook := range hooks {
			log.Printf("\t> %s\n", hook.ID)
		}
	}
	// set up file watcher
	//log.Printf("setting up file watcher for %s\n", *hooksFilePath)
}

func main() {
	l := log.New(os.Stdout, "[webhook] ", log.Ldate|log.Ltime)

	negroniLogger := &negroni.Logger{l}

	negroniRecovery := &negroni.Recovery{
		Logger:     l,
		PrintStack: true,
		StackAll:   false,
		StackSize:  1024 * 8,
	}

	n := negroni.New(negroniRecovery, negroniLogger)

	router := mux.NewRouter()
	router.HandleFunc("/hooks/{id}", hookHandler)

	n.UseHandler(router)

	log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))

	log.Printf("listening on %s:%d", *ip, *port)
}

func hookHandler(w http.ResponseWriter, r *http.Request) {
	id := mux.Vars(r)["id"]

	hook := hooks.Match(id)

	if hook != nil {
		log.Printf("%s got matched\n", id)

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Printf("error reading the request body. %+v\n", err)
		}

		// parse headers
		headers := helpers.ValuesToMap(r.Header)

		// parse query variables
		query := helpers.ValuesToMap(r.URL.Query())

		// parse body
		var payload map[string]interface{}

		contentType := r.Header.Get("Content-Type")

		if contentType == "application/json" {
			decoder := json.NewDecoder(strings.NewReader(string(body)))
			decoder.UseNumber()

			err := decoder.Decode(&payload)

			if err != nil {
				log.Printf("error parsing JSON payload %+v\n", err)
			}
		} else if contentType == "application/x-www-form-urlencoded" {
			fd, err := url.ParseQuery(string(body))
			if err != nil {
				log.Printf("error parsing form payload %+v\n", err)
			} else {
				payload = helpers.ValuesToMap(fd)
			}
		}

		// handle hook
		go handleHook(hook, &headers, &query, &payload, &body)

		// say thanks
		fmt.Fprintf(w, "Thanks.")
	} else {
		fmt.Fprintf(w, "Hook not found.")
	}
}

func handleHook(hook *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) {
	if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(headers, query, payload, body) {
		log.Printf("%s hook triggered successfully\n", hook.ID)

		cmd := exec.Command(hook.ExecuteCommand)
		cmd.Args = hook.ExtractCommandArguments(headers, query, payload)
		cmd.Dir = hook.CommandWorkingDirectory

		log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir)

		out, err := cmd.Output()

		log.Printf("stdout: %s\n", out)

		if err != nil {
			log.Printf("stderr: %+v\n", err)
		}
		log.Printf("finished handling %s\n", hook.ID)
	} else {
		log.Printf("%s hook did not get triggered\n", hook.ID)
	}
}
<commit_msg>added ability to hot reload the hooks file<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"

	"github.com/adnanh/webhook/helpers"
	"github.com/adnanh/webhook/hook"

	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"

	fsnotify "gopkg.in/fsnotify.v1"
)

const (
	version = "2.0.0"
)

var (
	ip            = flag.String("ip", "", "ip the webhook should serve hooks on")
	port          = flag.Int("port", 9000, "port the webhook should serve hooks on")
	verbose       = flag.Bool("verbose", false, "show verbose output")
	hotReload     = flag.Bool("hotreload", false, "watch hooks file for changes and reload them automatically")
	hooksFilePath = flag.String("hooks", "hooks.json", "path to the json file containing defined hooks the webhook should serve")

	watcher *fsnotify.Watcher

	hooks hook.Hooks
)

func init() {
	hooks = hook.Hooks{}

	flag.Parse()

	log.SetPrefix("[webhook] ")
	log.SetFlags(log.Ldate | log.Ltime)

	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	log.Println("version " + version + " starting")

	// load and parse hooks
	log.Printf("attempting to load hooks from %s\n", *hooksFilePath)

	err := hooks.LoadFromFile(*hooksFilePath)

	if err != nil {
		log.Printf("couldn't load hooks from file! %+v\n", err)
	} else {
		log.Printf("loaded %d hook(s) from file\n", len(hooks))

		for _, hook := range hooks {
			log.Printf("\t> %s\n", hook.ID)
		}
	}
}

func main() {
	if *hotReload {
		// set up file watcher
		log.Printf("setting up file watcher for %s\n", *hooksFilePath)

		var err error

		watcher, err = fsnotify.NewWatcher()
		if err != nil {
			log.Fatal("error creating file watcher instance", err)
		}

		defer watcher.Close()

		go watchForFileChange()

		err = watcher.Add(*hooksFilePath)
		if err != nil {
			log.Fatal("error adding hooks file to the watcher", err)
		}
	}

	l := log.New(os.Stdout, "[webhook] ", log.Ldate|log.Ltime)

	negroniLogger := &negroni.Logger{l}

	negroniRecovery := &negroni.Recovery{
		Logger:     l,
		PrintStack: true,
		StackAll:   false,
		StackSize:  1024 * 8,
	}

	n := negroni.New(negroniRecovery, negroniLogger)

	router := mux.NewRouter()
	router.HandleFunc("/hooks/{id}", hookHandler)

	n.UseHandler(router)

	log.Printf("listening on %s:%d", *ip, *port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))
}

func hookHandler(w http.ResponseWriter, r *http.Request) {
	id := mux.Vars(r)["id"]

	hook := hooks.Match(id)

	if hook != nil {
		log.Printf("%s got matched\n", id)

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Printf("error reading the request body. %+v\n", err)
		}

		// parse headers
		headers := helpers.ValuesToMap(r.Header)

		// parse query variables
		query := helpers.ValuesToMap(r.URL.Query())

		// parse body
		var payload map[string]interface{}

		contentType := r.Header.Get("Content-Type")

		if contentType == "application/json" {
			decoder := json.NewDecoder(strings.NewReader(string(body)))
			decoder.UseNumber()

			err := decoder.Decode(&payload)

			if err != nil {
				log.Printf("error parsing JSON payload %+v\n", err)
			}
		} else if contentType == "application/x-www-form-urlencoded" {
			fd, err := url.ParseQuery(string(body))
			if err != nil {
				log.Printf("error parsing form payload %+v\n", err)
			} else {
				payload = helpers.ValuesToMap(fd)
			}
		}

		// handle hook
		go handleHook(hook, &headers, &query, &payload, &body)

		// say thanks
		fmt.Fprintf(w, "Thanks.")
	} else {
		fmt.Fprintf(w, "Hook not found.")
	}
}

func handleHook(hook *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) {
	if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(headers, query, payload, body) {
		log.Printf("%s hook triggered successfully\n", hook.ID)

		cmd := exec.Command(hook.ExecuteCommand)
		cmd.Args = hook.ExtractCommandArguments(headers, query, payload)
		cmd.Dir = hook.CommandWorkingDirectory

		log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir)

		out, err := cmd.Output()

		log.Printf("stdout: %s\n", out)

		if err != nil {
			log.Printf("stderr: %+v\n", err)
		}
		log.Printf("finished handling %s\n", hook.ID)
	} else {
		log.Printf("%s hook did not get triggered\n", hook.ID)
	}
}

func watchForFileChange() {
	for {
		select {
		case event := <-(*watcher).Events:
			if event.Op&fsnotify.Write == fsnotify.Write {
				log.Println("hooks file modified")

				newHooks := hook.Hooks{}

				// parse and swap
				log.Printf("attempting to reload hooks from %s\n", *hooksFilePath)

				err := newHooks.LoadFromFile(*hooksFilePath)

				if err != nil {
					log.Printf("couldn't load hooks from file! %+v\n", err)
				} else {
					log.Printf("loaded %d hook(s) from file\n", len(hooks))

					for _, hook := range hooks {
						log.Printf("\t> %s\n", hook.ID)
					}

					hooks = newHooks
				}
			}
		case err := <-(*watcher).Errors:
			log.Println("watcher error:", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	_ "github.com/mattn/go-sqlite3"
	"github.com/spf13/cobra"
)

func newCreateCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var password string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "create",
		Short: "creates a new password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("insert into passwords (machine, service, user, password, type) values(?, ?, ?, ?, ?)")
			if err != nil {
				return fmt.Errorf("db.Prepare() failed: %s", err)
			}

			_, err = query.Exec(machine, service, user, password, passwordType)
			if err != nil {
				return fmt.Errorf("query.Exec() failed: %s", err)
			}

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&password, "password", "p", "", "password (required)")
	cmd.MarkFlagRequired("password")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newUpdateCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var password string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "update",
		Short: "updates an existing password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("update passwords set password=? where machine=? and service=? and user=? and type=?")
			if err != nil {
				return fmt.Errorf("db.Prepare(update) failed: %s", err)
			}

			_, err = query.Exec(password, machine, service, user, passwordType)

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&password, "password", "p", "", "new password (required)")
	cmd.MarkFlagRequired("password")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newDeleteCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "delete",
		Short: "deletes an existing password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("delete from passwords where machine=? and service=? and user=? and type=?")
			if err != nil {
				return fmt.Errorf("db.Prepare(delete) failed: %s", err)
			}

			_, err = query.Exec(machine, service, user, passwordType)

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newReadCommand(db *sql.DB) *cobra.Command {
	var machineFlag string
	var serviceFlag string
	var userFlag string
	var typeFlag string
	var cmd = &cobra.Command{
		Use:   "search",
		Short: "searches passwords",
		RunE: func(cmd *cobra.Command, args []string) error {
			rows, err := db.Query("select machine, service, user, password, type from passwords")
			if err != nil {
				return fmt.Errorf("db.Query(insert) failed: %s", err)
			}

			defer rows.Close()
			for rows.Next() {
				var machine string
				var service string
				var user string
				var password string
				var passwordType string
				err = rows.Scan(&machine, &service, &user, &password, &passwordType)
				if err != nil {
					return fmt.Errorf("rows.Scan() failed: %s", err)
				}

				if len(machineFlag) > 0 && machine != machineFlag {
					continue
				}

				if len(serviceFlag) > 0 && service != serviceFlag {
					continue
				}

				if len(userFlag) > 0 && user != userFlag {
					continue
				}

				fmt.Printf("%s %s@%s %s\n", service, user, machine, password)
			}

			return nil
		},
	}
	cmd.Flags().StringVarP(&machineFlag, "machine", "m", "", "machine (required)")
	cmd.Flags().StringVarP(&serviceFlag, "service", "s", "", "service (required)")
	cmd.Flags().StringVarP(&userFlag, "user", "u", "", "user (required)")
	cmd.Flags().StringVarP(&typeFlag, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newRootCommand(db *sql.DB) *cobra.Command {
	var cmd = &cobra.Command{
		Use:   "cpm",
		Short: "cpm is a console password manager",
	}
	cmd.AddCommand(newCreateCommand(db))
	cmd.AddCommand(newReadCommand(db))
	cmd.AddCommand(newUpdateCommand(db))
	cmd.AddCommand(newDeleteCommand(db))

	return cmd
}

func getCommands() []string {
	return []string{"create", "read", "update", "delete"}
}

// CpmDatabase is an opened tempfile, containing an sqlite database.
type CpmDatabase struct {
	File     *os.File
	Database *sql.DB
}

func pathExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func openDatabase() (*CpmDatabase, error) {
	var db CpmDatabase
	var err error
	db.File, err = ioutil.TempFile("", "cpm")
	if err != nil {
		return nil, fmt.Errorf("ioutil.TempFile() failed: %s", err)
	}

	if pathExists("./cpmdb") {
		os.Remove(db.File.Name())
		cmd := exec.Command("gpg", "--decrypt", "-a", "-o", db.File.Name(), "./cpmdb")
		err := cmd.Start()
		if err != nil {
			return nil, fmt.Errorf("cmd.Start() failed: %s", err)
		}
		err = cmd.Wait()
		if err != nil {
			return nil, fmt.Errorf("cmd.Wait() failed: %s", err)
		}
	}

	db.Database, err = sql.Open("sqlite3", db.File.Name())
	if err != nil {
		return nil, fmt.Errorf("sql.Open() failed: %s", err)
	}

	query, err := db.Database.Prepare(`create table if not exists passwords (
		id integer primary key,
		machine text not null,
		service text not null,
		user text not null,
		password text not null,
		type text not null
	)`)
	if err != nil {
		return nil, err
	}
	query.Exec()

	return &db, nil
}

func closeDatabase(db *CpmDatabase) {
	db.Database.Close()

	os.Remove("./cpmdb")
	// TODO harcoded uid
	cmd := exec.Command("gpg", "--encrypt", "--sign", "-a", "-r", "03915096", "-o", "./cpmdb", db.File.Name())
	err := cmd.Start()
	if err != nil {
		log.Fatalf("cmd.Start(gpg encrypt) failed: %s", err)
	}
	err = cmd.Wait()
	if err != nil {
		log.Fatalf("cmd.Wait(gpg encrypt) failed: %s", err)
	}

	os.Remove(db.File.Name())
}

func main() {
	db, err := openDatabase()
	if err != nil {
		log.Fatalf("openDatabase() failed: %s", err)
	}
	defer closeDatabase(db)

	var commandFound bool
	commands := getCommands()
	for _, a := range commands {
		for _, b := range os.Args[1:] {
			if a == b {
				commandFound = true
				break
			}
		}
	}
	var cmd = newRootCommand(db.Database)
	if !commandFound {
		// Default to the search subcommand.
		args := append([]string{"search"}, os.Args[1:]...)
		cmd.SetArgs(args)
	}

	err = cmd.Execute()
	if err != nil {
		log.Fatalf("rootCmd.Execute() failed: %s", err)
	}
}
<commit_msg>cpm: show password type in search output<commit_after>package main

import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	_ "github.com/mattn/go-sqlite3"
	"github.com/spf13/cobra"
)

func newCreateCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var password string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "create",
		Short: "creates a new password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("insert into passwords (machine, service, user, password, type) values(?, ?, ?, ?, ?)")
			if err != nil {
				return fmt.Errorf("db.Prepare() failed: %s", err)
			}

			_, err = query.Exec(machine, service, user, password, passwordType)
			if err != nil {
				return fmt.Errorf("query.Exec() failed: %s", err)
			}

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&password, "password", "p", "", "password (required)")
	cmd.MarkFlagRequired("password")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newUpdateCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var password string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "update",
		Short: "updates an existing password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("update passwords set password=? where machine=? and service=? and user=? and type=?")
			if err != nil {
				return fmt.Errorf("db.Prepare(update) failed: %s", err)
			}

			_, err = query.Exec(password, machine, service, user, passwordType)

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&password, "password", "p", "", "new password (required)")
	cmd.MarkFlagRequired("password")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newDeleteCommand(db *sql.DB) *cobra.Command {
	var machine string
	var service string
	var user string
	var passwordType string
	var cmd = &cobra.Command{
		Use:   "delete",
		Short: "deletes an existing password",
		RunE: func(cmd *cobra.Command, args []string) error {
			query, err := db.Prepare("delete from passwords where machine=? and service=? and user=? and type=?")
			if err != nil {
				return fmt.Errorf("db.Prepare(delete) failed: %s", err)
			}

			_, err = query.Exec(machine, service, user, passwordType)

			return nil
		},
	}
	cmd.Flags().StringVarP(&machine, "machine", "m", "", "machine (required)")
	cmd.MarkFlagRequired("machine")
	cmd.Flags().StringVarP(&service, "service", "s", "", "service (required)")
	cmd.MarkFlagRequired("service")
	cmd.Flags().StringVarP(&user, "user", "u", "", "user (required)")
	cmd.MarkFlagRequired("user")
	cmd.Flags().StringVarP(&passwordType, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newReadCommand(db *sql.DB) *cobra.Command {
	var machineFlag string
	var serviceFlag string
	var userFlag string
	var typeFlag string
	var cmd = &cobra.Command{
		Use:   "search",
		Short: "searches passwords",
		RunE: func(cmd *cobra.Command, args []string) error {
			rows, err := db.Query("select machine, service, user, password, type from passwords")
			if err != nil {
				return fmt.Errorf("db.Query(insert) failed: %s", err)
			}

			defer rows.Close()
			for rows.Next() {
				var machine string
				var service string
				var user string
				var password string
				var passwordType string
				err = rows.Scan(&machine, &service, &user, &password, &passwordType)
				if err != nil {
					return fmt.Errorf("rows.Scan() failed: %s", err)
				}

				if len(machineFlag) > 0 && machine != machineFlag {
					continue
				}

				if len(serviceFlag) > 0 && service != serviceFlag {
					continue
				}

				if len(userFlag) > 0 && user != userFlag {
					continue
				}

				fmt.Printf("machine: %s service: %s user: %s password: %s, password type: %s\n", machine, service, user, password, passwordType)
			}

			return nil
		},
	}
	cmd.Flags().StringVarP(&machineFlag, "machine", "m", "", "machine (required)")
	cmd.Flags().StringVarP(&serviceFlag, "service", "s", "", "service (required)")
	cmd.Flags().StringVarP(&userFlag, "user", "u", "", "user (required)")
	cmd.Flags().StringVarP(&typeFlag, "type", "t", "plain", "password type ('plain' or 'totp', default: plain)")

	return cmd
}

func newRootCommand(db *sql.DB) *cobra.Command {
	var cmd = &cobra.Command{
		Use:   "cpm",
		Short: "cpm is a console password manager",
	}
	cmd.AddCommand(newCreateCommand(db))
	cmd.AddCommand(newReadCommand(db))
	cmd.AddCommand(newUpdateCommand(db))
	cmd.AddCommand(newDeleteCommand(db))

	return cmd
}

func getCommands() []string {
	return []string{"create", "read", "update", "delete"}
}

// CpmDatabase is an opened tempfile, containing an sqlite database.
type CpmDatabase struct {
	File     *os.File
	Database *sql.DB
}

func pathExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func openDatabase() (*CpmDatabase, error) {
	var db CpmDatabase
	var err error
	db.File, err = ioutil.TempFile("", "cpm")
	if err != nil {
		return nil, fmt.Errorf("ioutil.TempFile() failed: %s", err)
	}

	if pathExists("./cpmdb") {
		os.Remove(db.File.Name())
		cmd := exec.Command("gpg", "--decrypt", "-a", "-o", db.File.Name(), "./cpmdb")
		err := cmd.Start()
		if err != nil {
			return nil, fmt.Errorf("cmd.Start() failed: %s", err)
		}
		err = cmd.Wait()
		if err != nil {
			return nil, fmt.Errorf("cmd.Wait() failed: %s", err)
		}
	}

	db.Database, err = sql.Open("sqlite3", db.File.Name())
	if err != nil {
		return nil, fmt.Errorf("sql.Open() failed: %s", err)
	}

	query, err := db.Database.Prepare(`create table if not exists passwords (
		id integer primary key,
		machine text not null,
		service text not null,
		user text not null,
		password text not null,
		type text not null
	)`)
	if err != nil {
		return nil, err
	}
	query.Exec()

	return &db, nil
}

func closeDatabase(db *CpmDatabase) {
	db.Database.Close()

	os.Remove("./cpmdb")
	// TODO harcoded uid
	cmd := exec.Command("gpg", "--encrypt", "--sign", "-a", "-r", "03915096", "-o", "./cpmdb", db.File.Name())
	err := cmd.Start()
	if err != nil {
		log.Fatalf("cmd.Start(gpg encrypt) failed: %s", err)
	}
	err = cmd.Wait()
	if err != nil {
		log.Fatalf("cmd.Wait(gpg encrypt) failed: %s", err)
	}

	os.Remove(db.File.Name())
}

func main() {
	db, err := openDatabase()
	if err != nil {
		log.Fatalf("openDatabase() failed: %s", err)
	}
	defer closeDatabase(db)

	var commandFound bool
	commands := getCommands()
	for _, a := range commands {
		for _, b := range os.Args[1:] {
			if a == b {
				commandFound = true
				break
			}
		}
	}
	var cmd = newRootCommand(db.Database)
	if !commandFound {
		// Default to the search subcommand.
		args := append([]string{"search"}, os.Args[1:]...)
		cmd.SetArgs(args)
	}

	err = cmd.Execute()
	if err != nil {
		log.Fatalf("rootCmd.Execute() failed: %s", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"code.google.com/p/goplan9/plan9"
	"code.google.com/p/goplan9/plan9/client"
)

type window struct {
	Id    string
	Props string
	Tags  []string
}

func (win window) String() string {
	return win.Id + " " + win.Props + " " + strings.Join(win.Tags, "+")
}

type wmii struct {
	conn *client.Conn
	fsys *client.Fsys
}

func newWmii() (*wmii, error) {
	conn, err := client.DialService("wmii")
	if err != nil {
		return nil, err
	}

	fsys, err := conn.Attach(nil, "", "")
	if err != nil {
		conn.Close()
		return nil, err
	}

	return &wmii{conn: conn, fsys: fsys}, nil
}

func (wm *wmii) Close() error {
	return wm.conn.Close()
}

func (wm *wmii) Windows() ([]window, error) {
	dirname := "/client"
	dirs, err := wm.readDir(dirname)
	if err != nil {
		return nil, err
	}

	wins := make([]window, 0, len(dirs))
	for _, dir := range dirs {
		if dir.Name == "sel" {
			continue
		}
		fname := fmt.Sprintf("/client/%s/props", dir.Name)
		props, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		fname = fmt.Sprintf("/client/%s/tags", dir.Name)
		tagstr, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		tags := []string{}
		for _, tag := range strings.Split(string(tagstr), "+") {
			if tag != "" {
				tags = append(tags, tag)
			}
		}

		wins = append(wins, window{Id: dir.Name, Props: string(props), Tags: tags})
	}

	return wins, nil
}

func (wm *wmii) SelectWindow(id string) error {
	return wm.writeFile("/tag/sel/ctl", []byte(fmt.Sprintf("select client %s\n", id)))
}

func (wm *wmii) View(tag string) error {
	return wm.writeFile("/ctl", []byte(fmt.Sprintf("view %s\n", tag)))
}

func (wm *wmii) CurrentTag() (string, error) {
	buf, err := wm.readFile("/ctl")
	if err != nil {
		return "", err
	}

	sc := bufio.NewScanner(bytes.NewReader(buf))
	for sc.Scan() {
		line := sc.Text()
		if strings.HasPrefix(line, "view ") {
			return strings.TrimSpace(line[5:]), nil
		}
	}

	return "", sc.Err()
}

func (wm *wmii) readDir(name string) ([]*plan9.Dir, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return fid.Dirreadall()
}

func (wm *wmii) readFile(name string) ([]byte, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return ioutil.ReadAll(fid)
}

func (wm *wmii) writeFile(name string, data []byte) error {
	fid, err := wm.fsys.Open(name, plan9.OWRITE)
	if err != nil {
		return err
	}
	_, err = fid.Write(data)
	fid.Close()
	return err
}

func selectWindow(windows []window) (int, error) {

	items := make([]string, len(windows))
	for i := range items {
		items[i] = fmt.Sprintf("<%d> [%s] %s", i, strings.Join(windows[i].Tags, "+"), windows[i].Props)
	}

	dmenu := exec.Command("dmenu", "-l", "7", "-i", "-b")

	in, err := dmenu.StdinPipe()
	if err != nil {
		return -1, err
	}

	go func() {
		for _, item := range items {
			fmt.Fprintln(in, item)
		}
		in.Close()
	}()

	out, err := dmenu.Output()
	if err != nil {
		return -1, err
	}

	if len(out) > 0 {
		sel := string(out[:len(out)-1])
		for i, item := range items {
			if item == sel {
				return i, nil
			}
		}
	}

	return -1, nil
}

func main() {
	wm, err := newWmii()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer wm.Close()

	windows, err := wm.Windows()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	sel, err := selectWindow(windows)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if sel < 0 {
		return
	}

	win := windows[sel]

	if len(win.Tags) == 0 {
		fmt.Fprintf(os.Stderr, "selected window has no tags\n")
		return
	}

	ctag, _ := wm.CurrentTag()
	ntag := win.Tags[0]

	for _, tag := range win.Tags {
		if tag == ctag {
			ntag = tag
		}
	}

	if ntag != ctag {
		if err := wm.View(ntag); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	if err := wm.SelectWindow(win.Id); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>add wm.AddTag()<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"code.google.com/p/goplan9/plan9"
	"code.google.com/p/goplan9/plan9/client"
)

type window struct {
	Id    string
	Props string
	Tags  []string
}

func (win window) String() string {
	return win.Id + " " + win.Props + " " + strings.Join(win.Tags, "+")
}

type wmii struct {
	conn *client.Conn
	fsys *client.Fsys
}

func newWmii() (*wmii, error) {
	conn, err := client.DialService("wmii")
	if err != nil {
		return nil, err
	}

	fsys, err := conn.Attach(nil, "", "")
	if err != nil {
		conn.Close()
		return nil, err
	}

	return &wmii{conn: conn, fsys: fsys}, nil
}

func (wm *wmii) Close() error {
	return wm.conn.Close()
}

func (wm *wmii) Windows() ([]window, error) {
	dirname := "/client"
	dirs, err := wm.readDir(dirname)
	if err != nil {
		return nil, err
	}

	wins := make([]window, 0, len(dirs))
	for _, dir := range dirs {
		if dir.Name == "sel" {
			continue
		}
		fname := fmt.Sprintf("/client/%s/props", dir.Name)
		props, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		fname = fmt.Sprintf("/client/%s/tags", dir.Name)
		tagstr, err := wm.readFile(fname)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wmiinav: read %s: %s", fname, err)
		}
		tags := []string{}
		for _, tag := range strings.Split(string(tagstr), "+") {
			if tag != "" {
				tags = append(tags, tag)
			}
		}

		wins = append(wins, window{Id: dir.Name, Props: string(props), Tags: tags})
	}

	return wins, nil
}

func (wm *wmii) SelectWindow(id string) error {
	return wm.writeFile("/tag/sel/ctl", []byte(fmt.Sprintf("select client %s\n", id)))
}

func (wm *wmii) View(tag string) error {
	return wm.writeFile("/ctl", []byte(fmt.Sprintf("view %s\n", tag)))
}

func (wm *wmii) CurrentTag() (string, error) {
	buf, err := wm.readFile("/ctl")
	if err != nil {
		return "", err
	}

	sc := bufio.NewScanner(bytes.NewReader(buf))
	for sc.Scan() {
		line := sc.Text()
		if strings.HasPrefix(line, "view ") {
			return strings.TrimSpace(line[5:]), nil
		}
	}

	return "", sc.Err()
}

func (wm *wmii) AddTag(win *window, tag string) error {
	win.Tags = append(win.Tags, tag)
	return wm.writeFile(fmt.Sprintf("/client/%s/tags", win.Id), []byte("+" + tag))
}

func (wm *wmii) readDir(name string) ([]*plan9.Dir, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return fid.Dirreadall()
}

func (wm *wmii) readFile(name string) ([]byte, error) {
	fid, err := wm.fsys.Open(name, plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()
	return ioutil.ReadAll(fid)
}

func (wm *wmii) writeFile(name string, data []byte) error {
	fid, err := wm.fsys.Open(name, plan9.OWRITE)
	if err != nil {
		return err
	}
	_, err = fid.Write(data)
	fid.Close()
	return err
}

func selectWindow(windows []window) (int, error) {

	items := make([]string, len(windows))
	for i := range items {
		items[i] = fmt.Sprintf("<%d> [%s] %s", i, strings.Join(windows[i].Tags, "+"), windows[i].Props)
	}

	dmenu := exec.Command("dmenu", "-l", "7", "-i", "-b")

	in, err := dmenu.StdinPipe()
	if err != nil {
		return -1, err
	}

	go func() {
		for _, item := range items {
			fmt.Fprintln(in, item)
		}
		in.Close()
	}()

	out, err := dmenu.Output()
	if err != nil {
		return -1, err
	}

	if len(out) > 0 {
		sel := string(out[:len(out)-1])
		for i, item := range items {
			if item == sel {
				return i, nil
			}
		}
	}

	return -1, nil
}

func main() {
	wm, err := newWmii()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer wm.Close()

	windows, err := wm.Windows()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	sel, err := selectWindow(windows)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if sel < 0 {
		return
	}

	win := windows[sel]

	if len(win.Tags) == 0 {
		fmt.Fprintf(os.Stderr, "selected window has no tags\n")
		return
	}

	ctag, _ := wm.CurrentTag()
	ntag := win.Tags[0]

	for _, tag := range win.Tags {
		if tag == ctag {
			ntag = tag
		}
	}

	if ntag != ctag {
		if err := wm.View(ntag); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	if err := wm.SelectWindow(win.Id); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/x509"
	"io/ioutil"
	"math/big"
	"testing"
)

func TestGetDistributionPoint(t *testing.T) {
	cert, _ := readCertificate("./testdata/certificate.pem")
	server, _ := getCRLDistributionPoint(cert)

	expected := "http://crl3.digicert.com/ssca-sha2-g3.crl"

	if server != expected {
		t.Errorf("expected %q, got %q", expected, server)
	}
}

func TestGetDestributionPointFromCertWithoutCRL(t *testing.T) {
	cert, _ := readCertificate("./testdata/cloudflare_origin_ca_rsa_root.crt")
	server, _ := getCRLDistributionPoint(cert)

	expected := ""

	if server != expected {
		t.Errorf("expected %q, got %q", expected, server)
	}
}

func TestFindCert(t *testing.T) {
	// NOTE: DigiCert SHA2 Extended Validation Server CA CRL
	crl, _ := ioutil.ReadFile("./testdata/sha2-ev-server-g2.crl")
	resp, err := x509.ParseCRL(crl)
	if err != nil {
		t.Fatal(err)
	}

	// Serial belongs to https://censys.io/certificates/39e31c9f5913e4ed68c9582de80c8be4689608f622075d0c81b6fe52dfe2db82
	s := new(big.Int)
	s.SetString("17015245701990644280577643802745589798", 10)

	test := FindCert(s, resp)

	if test == nil {
		t.Errorf("expected to find revoked certificate with serial number %q", s.String())
	}
}

func TestFindNonExistingRevokedCert(t *testing.T) {
	// NOTE: DigiCert SHA2 Extended Validation Server CA CRL
	crl, _ := ioutil.ReadFile("./testdata/sha2-ev-server-g2.crl")
	resp, err := x509.ParseCRL(crl)
	if err != nil {
		t.Fatal(err)
	}

	test := FindCert(big.NewInt(0), resp)

	if test != nil {
		t.Error("did not expect to find a revoked certificate")
	}
}

func TestGetCRLResponse(t *testing.T) {
	client = &MockHttpClient{}
	cert, err := readCertificate("./testdata/cisco_revoked.pem")

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

	st, err := GetCRLResponse(client, cert)

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

	if st.Status != "Revoked" {
		t.Fatal("err")
	}
}

func TestGetCRLResponseNotRevoked(t *testing.T) {
	client = &MockHttpClient{}
	cert, err := readCertificate("./testdata/twitter.pem")

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

	st, err := GetCRLResponse(client, cert)

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

	if st.Status != "Good" {
		t.Fatal("err")
	}
}
<commit_msg>Updated error messages in test case.<commit_after>package main

import (
	"crypto/x509"
	"io/ioutil"
	"math/big"
	"testing"
)

func TestGetDistributionPoint(t *testing.T) {
	cert, _ := readCertificate("./testdata/certificate.pem")
	server, _ := getCRLDistributionPoint(cert)

	expected := "http://crl3.digicert.com/ssca-sha2-g3.crl"

	if server != expected {
		t.Errorf("expected %q, got %q", expected, server)
	}
}

func TestGetDestributionPointFromCertWithoutCRL(t *testing.T) {
	cert, _ := readCertificate("./testdata/cloudflare_origin_ca_rsa_root.crt")
	server, _ := getCRLDistributionPoint(cert)

	expected := ""

	if server != expected {
		t.Errorf("expected %q, got %q", expected, server)
	}
}

func TestFindCert(t *testing.T) {
	// NOTE: DigiCert SHA2 Extended Validation Server CA CRL
	crl, _ := ioutil.ReadFile("./testdata/sha2-ev-server-g2.crl")
	resp, err := x509.ParseCRL(crl)
	if err != nil {
		t.Fatal(err)
	}

	// Serial belongs to https://censys.io/certificates/39e31c9f5913e4ed68c9582de80c8be4689608f622075d0c81b6fe52dfe2db82
	s := new(big.Int)
	s.SetString("17015245701990644280577643802745589798", 10)

	test := FindCert(s, resp)

	if test == nil {
		t.Errorf("expected to find revoked certificate with serial number %q", s.String())
	}
}

func TestFindNonExistingRevokedCert(t *testing.T) {
	// NOTE: DigiCert SHA2 Extended Validation Server CA CRL
	crl, _ := ioutil.ReadFile("./testdata/sha2-ev-server-g2.crl")
	resp, err := x509.ParseCRL(crl)
	if err != nil {
		t.Fatal(err)
	}

	test := FindCert(big.NewInt(0), resp)

	if test != nil {
		t.Error("did not expect to find a revoked certificate")
	}
}

func TestGetCRLResponse(t *testing.T) {
	client = &MockHttpClient{}
	cert, err := readCertificate("./testdata/cisco_revoked.pem")

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

	st, err := GetCRLResponse(client, cert)

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

	expected := "Revoked"
	if st.Status != expected {
		t.Errorf("expected %q, got %q", expected, st.Status)
	}
}

func TestGetCRLResponseNotRevoked(t *testing.T) {
	client = &MockHttpClient{}
	cert, err := readCertificate("./testdata/twitter.pem")

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

	st, err := GetCRLResponse(client, cert)

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

	expected := "Good"
	if st.Status != expected {
		t.Errorf("expected %q, got %q", expected, st.Status)
	}
}
<|endoftext|>