<commit_before>package main

import (
	"github.com/nurza/logo"

	"./data"

	"bytes"
	"encoding/json"
	"flag"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

/*
	Global variables
*/
var (
	// Logging
	l       logo.Logger
	Loggers []*logo.Logger

	// Configuration
	BotUsername     string     // Bot's username
	BotChannel      string     // Bot's system channel
	BotIcon         string     // Bot's icon (Slack emoji)
	PushIcon        string     // Push icon (Slack emoji)
	MergeIcon       string     // Merge icon (Slack emoji)
	BuildIcon       string     // Build icon (Slack emoji)
	BotStartMessage string     // Bot's start message
	SlackAPIUrl     string     // Slack API URL
	SlackAPIToken   string     // Slack API Token
	ChannelPrefix   string     // Slack channel prefix
	Verbose         bool       // Enable verbose mode
	HttpTimeout     int        // Http timeout in second
	Redirect        []struct { // List of channel redirect
		Channel      string
		Repositories []string
	}

	// Misc
	currentBuildID float64 = 0      // Current build ID
	n              string  = "%5Cn" // Encoded line return
)

/*
	Flags
*/
var (
	ConfigFile = flag.String("f", "config.json", "Configuration file")
)

const (
	Bot   int = iota
	Push  int = iota
	Merge int = iota
	Build int = iota
)

/*
	Struc for HTTP servers
*/
type PushServ struct{}
type MergeServ struct{}
type BuildServ struct{}

/*
	Load configuration file
*/
func LoadConf() {

	conf := struct {
		BotUsername     string
		BotChannel      string
		BotIcon         string
		PushIcon        string
		MergeIcon       string
		BuildIcon       string
		BotStartMessage string
		SlackAPIUrl     string
		SlackAPIToken   string
		ChannelPrefix   string
		Verbose         bool
		HttpTimeout     float64
		Redirect        []struct {
			Channel      string
			Repositories []string
		}
	}{}

	content, err := ioutil.ReadFile(*ConfigFile)
	if err != nil {
		l.Critical("Error: Read config file error: " + err.Error())
	}

	err = json.Unmarshal(content, &conf)
	if err != nil {
		l.Critical("Error: Parse config file error: " + err.Error())
	}

	BotUsername = conf.BotUsername
	BotChannel = conf.BotChannel
	BotIcon = conf.BotIcon
	PushIcon = conf.PushIcon
	MergeIcon = conf.MergeIcon
	BuildIcon = conf.BuildIcon
	BotStartMessage = conf.BotStartMessage
	SlackAPIUrl = conf.SlackAPIUrl
	SlackAPIToken = conf.SlackAPIToken
	ChannelPrefix = conf.ChannelPrefix
	Verbose = conf.Verbose
	HttpTimeout = int(conf.HttpTimeout)
	Redirect = conf.Redirect
}

/*
	HTTP POST request

	target:		url target
	payload:	payload to send

	Returned values:

	int:	HTTP response status code
	string:	HTTP response body
*/
func Post(target string, payload string) (int, string) {
	// Variables
	var err error          // Error catching
	var res *http.Response // HTTP response
	var req *http.Request  // HTTP request
	var body []byte        // Body response

	// Build request
	req, err = http.NewRequest("POST", target, bytes.NewBufferString(payload))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// Do request
	client := &http.Client{}
	client.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   time.Duration(HttpTimeout) * time.Second,
			KeepAlive: time.Duration(HttpTimeout) * time.Second,
		}).Dial,
		TLSHandshakeTimeout: time.Duration(HttpTimeout) * time.Second,
	}

	res, err = client.Do(req)
	if err != nil {
		l.Error("Error : Curl POST : " + err.Error())
		if res != nil {
			return res.StatusCode, ""
		} else {
			return 0, ""
		}
	}
	defer res.Body.Close()

	// Read body
	body, err = ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		l.Error("Error : Curl POST body read : " + err.Error())
	}

	return res.StatusCode, string(body)
}

/*
	Create a Slack channel

	@param chanName : The Slack channel name (without the #)
*/
func CreateSlackChannel(chanName string) {
	// Variables
	var err error                                       // Error catching
	var supl string = "&name=" + chanName + "&pretty=1" // Additional request
	var resp *http.Response                             // Response

	// API Get
	resp, err = http.Get("https://slack.com/api/channels.join?token=" + SlackAPIToken + supl)

	if err != nil {
		// Error
		l.Error("Error : CreateSlackChannel :", err, "\nResponse :", resp)
	} else {
		// Ok
		l.Verbose("CreateSlackChannel OK\nResponse :", resp)
	}
}

/*
	Encode the git commit message with replacing some special characters not allowed by the Slack API

	@param origin Git message to encode
*/
func MessageEncode(origin string) string {
	var result string = ""

	for _, e := range strings.Split(origin, "") {
		switch e {
		case "\n":
			result += "%5Cn"
		case "+":
			result += "%2B"
		case "\"":
			result += "''"
		case "&":
			result += " and "
		default:
			result += e
		}
	}

	return result
}

/*
	Send a message on Slack

	@param channel : Targeted channel (without the #)
*/
func SendSlackMessage(channel, message string, typeMessage int) {
	// Variables
	var payload string // POST data sent to slack
	var icon string    // Slack emoji

	// toLower(channel)
	l.Silly("toLower =", channel)
	channel = strings.ToLower(channel)
	l.Silly("toLower =", channel)

	// Redirect channel
	l.Silly("RedirectBreak =", channel)
RedirectBreak:
	for _, redirect := range Redirect {
		for _, repo := range redirect.Repositories {
			if channel == repo {
				l.Silly("RedirectBreakSet", channel, "=", redirect.Channel)
				channel = redirect.Channel
				break RedirectBreak
			}
		}
	}
	l.Silly("RedirectBreak =", channel)

	// Insert prefix on non system channels
	l.Silly("ChannelPrefix =", channel)
	if channel != BotChannel {
		channel = ChannelPrefix + channel
	}
	l.Silly("ChannelPrefix =", channel)

	// Crop channel name if len(channel)>21
	l.Silly("Crop =", channel)
	if len(channel) > 21 {
		channel = channel[:21]
	}
	l.Silly("Crop =", channel)

	// Create channel if not exists
	CreateSlackChannel(channel)

	// Set icon
	switch typeMessage {
	case Bot:
		icon = BotIcon
	case Push:
		icon = PushIcon
	case Merge:
		icon = MergeIcon
	case Build:
		icon = BuildIcon
	}

	// POST Payload formating
	payload = "payload="
	payload += `{"channel": "#` + strings.ToLower(channel) + `", "username": "` + BotUsername + `", "text": "` + message + `", "icon_emoji": "` + icon + `"}`

	// Debug information
	if Verbose {
		l.Debug("payload =", payload)
	}

	code, body := Post(SlackAPIUrl, payload)
	if code != 200 {
		l.Error("Error post, Slack API returned:", body)
	}

	// Debug information
	if Verbose {
		l.Debug("Slack API returned:", body)
	}
}

/*
	Handler function to handle http requests for push

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *PushServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Push         // Json structure to parse the push webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Push Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Send the message

		// Date parsing (parsing result example : 18 November 2014 - 14:34)
		date, err = time.Parse("2006-01-02T15:04:05Z07:00", j.Commits[0].Timestamp)
		var dateString = date.Format("02 Jan 06 15:04")

		// Message
		lastCommit := j.Commits[len(j.Commits)-1]
		message += "[PUSH] " + n + "Push on *" + j.Repository.Name + "* by *" + j.User_name + "* at *" + dateString + "* on branch *" + j.Ref + "*:" + n // First line
		message += "Last commit : <" + lastCommit.Url + "|" + lastCommit.Id + "> :" + n                                                                  // Second line
		message += "```" + MessageEncode(lastCommit.Message) + "```"                                                                                // Third line (last commit message)
		SendSlackMessage(j.Repository.Name, message, Push)
	}
}

/*
	Handler function to handle http requests for merge

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *MergeServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Merge        // Json structure to parse the push webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Merge Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Send the message

		// Date parsing (parsing result example : 18 November 2014 - 14:34)
		date, err = time.Parse("2006-01-02 15:04:05 UTC", j.Object_attributes.Created_at)
		var dateString = date.Format("02 Jan 06 15:04")

		// Message
		message += "[MERGE REQUEST " + strings.ToUpper(j.Object_attributes.State) + "] " + n + "Target : *" + j.Object_attributes.Target.Name + "/" + j.Object_attributes.Target_branch + "* Source : *" + j.Object_attributes.Source.Name + "/" + j.Object_attributes.Source_branch + "* : at *" + dateString + "* :" + n // First line
		message += "```" + MessageEncode(j.Object_attributes.Description) + "```"                                                                                // Third line (last commit message)
		SendSlackMessage(j.Object_attributes.Target.Name, message, Merge)
	}
}

/*
	Handler function to handle http requests for build

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *BuildServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Build        // Json structure to parse the build webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Build Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Test if the message is already sent
		if currentBuildID < j.Build_id {
			// Not sent
			currentBuildID = j.Build_id // Update current build ID

			// Send the message

			// Date parsing (parsing result example : 18 November 2014 - 14:34)
			date, err = time.Parse("2006-01-02T15:04:05Z07:00", j.Push_data.Commits[0].Timestamp)
			var dateString = strconv.Itoa(date.Day()) + " " + date.Month().String() + " " + strconv.Itoa(date.Year()) +
				" - " + strconv.Itoa(date.Hour()) + ":" + strconv.Itoa(date.Minute())

			// Message
			lastCommit := j.Push_data.Commits[len(j.Push_data.Commits)-1]
			message += "[BUILD] " + n + strings.ToUpper(j.Build_status) + " : Push on *" + j.Push_data.Repository.Name + "* by *" + j.Push_data.User_name + "* at *" + dateString + "* on branch *" + j.Ref + "*:" + n // First line
			message += "Last commit : <" + lastCommit.Url + "|" + lastCommit.Id + "> :" + n                                                                                // Second line
			message += "```" + MessageEncode(lastCommit.Message) + "```"                                                                                // Third line (last commit message)
			SendSlackMessage(j.Push_data.Repository.Name, message, Build)
		} else {
			// Already sent
			// Do nothing
		}
	}

}

/*
	Main function
*/
func main() {
	flag.Parse()                                             // Parse flags
	l.AddTransport(logo.Console).AddColor(logo.ConsoleColor) // Configure Logger
	l.EnableAllLevels()                                      // Configure Logger
	LoadConf()                                               // Load configuration
	SendSlackMessage(BotChannel, BotStartMessage, Bot)       // Slack notification
	l.Info(BotStartMessage)                                  // Logging
	go http.ListenAndServe(":8100", &PushServ{})             // Run HTTP server for push hook
	go http.ListenAndServe(":8200", &MergeServ{})            // Run HTTP server for merge request hook
	http.ListenAndServe(":8300", &BuildServ{})               // Run HTTP server for build hook
}
<commit_msg>change import of "./data" to be non-relative to prevent local import warning<commit_after>package main

import (
	"github.com/nurza/logo"

	"github.com/ZenlabsFR/GitlabHookServer/data"

	"bytes"
	"encoding/json"
	"flag"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

/*
	Global variables
*/
var (
	// Logging
	l       logo.Logger
	Loggers []*logo.Logger

	// Configuration
	BotUsername     string     // Bot's username
	BotChannel      string     // Bot's system channel
	BotIcon         string     // Bot's icon (Slack emoji)
	PushIcon        string     // Push icon (Slack emoji)
	MergeIcon       string     // Merge icon (Slack emoji)
	BuildIcon       string     // Build icon (Slack emoji)
	BotStartMessage string     // Bot's start message
	SlackAPIUrl     string     // Slack API URL
	SlackAPIToken   string     // Slack API Token
	ChannelPrefix   string     // Slack channel prefix
	Verbose         bool       // Enable verbose mode
	HttpTimeout     int        // Http timeout in second
	Redirect        []struct { // List of channel redirect
		Channel      string
		Repositories []string
	}

	// Misc
	currentBuildID float64 = 0      // Current build ID
	n              string  = "%5Cn" // Encoded line return
)

/*
	Flags
*/
var (
	ConfigFile = flag.String("f", "config.json", "Configuration file")
)

const (
	Bot   int = iota
	Push  int = iota
	Merge int = iota
	Build int = iota
)

/*
	Struc for HTTP servers
*/
type PushServ struct{}
type MergeServ struct{}
type BuildServ struct{}

/*
	Load configuration file
*/
func LoadConf() {

	conf := struct {
		BotUsername     string
		BotChannel      string
		BotIcon         string
		PushIcon        string
		MergeIcon       string
		BuildIcon       string
		BotStartMessage string
		SlackAPIUrl     string
		SlackAPIToken   string
		ChannelPrefix   string
		Verbose         bool
		HttpTimeout     float64
		Redirect        []struct {
			Channel      string
			Repositories []string
		}
	}{}

	content, err := ioutil.ReadFile(*ConfigFile)
	if err != nil {
		l.Critical("Error: Read config file error: " + err.Error())
	}

	err = json.Unmarshal(content, &conf)
	if err != nil {
		l.Critical("Error: Parse config file error: " + err.Error())
	}

	BotUsername = conf.BotUsername
	BotChannel = conf.BotChannel
	BotIcon = conf.BotIcon
	PushIcon = conf.PushIcon
	MergeIcon = conf.MergeIcon
	BuildIcon = conf.BuildIcon
	BotStartMessage = conf.BotStartMessage
	SlackAPIUrl = conf.SlackAPIUrl
	SlackAPIToken = conf.SlackAPIToken
	ChannelPrefix = conf.ChannelPrefix
	Verbose = conf.Verbose
	HttpTimeout = int(conf.HttpTimeout)
	Redirect = conf.Redirect
}

/*
	HTTP POST request

	target:		url target
	payload:	payload to send

	Returned values:

	int:	HTTP response status code
	string:	HTTP response body
*/
func Post(target string, payload string) (int, string) {
	// Variables
	var err error          // Error catching
	var res *http.Response // HTTP response
	var req *http.Request  // HTTP request
	var body []byte        // Body response

	// Build request
	req, err = http.NewRequest("POST", target, bytes.NewBufferString(payload))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// Do request
	client := &http.Client{}
	client.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   time.Duration(HttpTimeout) * time.Second,
			KeepAlive: time.Duration(HttpTimeout) * time.Second,
		}).Dial,
		TLSHandshakeTimeout: time.Duration(HttpTimeout) * time.Second,
	}

	res, err = client.Do(req)
	if err != nil {
		l.Error("Error : Curl POST : " + err.Error())
		if res != nil {
			return res.StatusCode, ""
		} else {
			return 0, ""
		}
	}
	defer res.Body.Close()

	// Read body
	body, err = ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		l.Error("Error : Curl POST body read : " + err.Error())
	}

	return res.StatusCode, string(body)
}

/*
	Create a Slack channel

	@param chanName : The Slack channel name (without the #)
*/
func CreateSlackChannel(chanName string) {
	// Variables
	var err error                                       // Error catching
	var supl string = "&name=" + chanName + "&pretty=1" // Additional request
	var resp *http.Response                             // Response

	// API Get
	resp, err = http.Get("https://slack.com/api/channels.join?token=" + SlackAPIToken + supl)

	if err != nil {
		// Error
		l.Error("Error : CreateSlackChannel :", err, "\nResponse :", resp)
	} else {
		// Ok
		l.Verbose("CreateSlackChannel OK\nResponse :", resp)
	}
}

/*
	Encode the git commit message with replacing some special characters not allowed by the Slack API

	@param origin Git message to encode
*/
func MessageEncode(origin string) string {
	var result string = ""

	for _, e := range strings.Split(origin, "") {
		switch e {
		case "\n":
			result += "%5Cn"
		case "+":
			result += "%2B"
		case "\"":
			result += "''"
		case "&":
			result += " and "
		default:
			result += e
		}
	}

	return result
}

/*
	Send a message on Slack

	@param channel : Targeted channel (without the #)
*/
func SendSlackMessage(channel, message string, typeMessage int) {
	// Variables
	var payload string // POST data sent to slack
	var icon string    // Slack emoji

	// toLower(channel)
	l.Silly("toLower =", channel)
	channel = strings.ToLower(channel)
	l.Silly("toLower =", channel)

	// Redirect channel
	l.Silly("RedirectBreak =", channel)
RedirectBreak:
	for _, redirect := range Redirect {
		for _, repo := range redirect.Repositories {
			if channel == repo {
				l.Silly("RedirectBreakSet", channel, "=", redirect.Channel)
				channel = redirect.Channel
				break RedirectBreak
			}
		}
	}
	l.Silly("RedirectBreak =", channel)

	// Insert prefix on non system channels
	l.Silly("ChannelPrefix =", channel)
	if channel != BotChannel {
		channel = ChannelPrefix + channel
	}
	l.Silly("ChannelPrefix =", channel)

	// Crop channel name if len(channel)>21
	l.Silly("Crop =", channel)
	if len(channel) > 21 {
		channel = channel[:21]
	}
	l.Silly("Crop =", channel)

	// Create channel if not exists
	CreateSlackChannel(channel)

	// Set icon
	switch typeMessage {
	case Bot:
		icon = BotIcon
	case Push:
		icon = PushIcon
	case Merge:
		icon = MergeIcon
	case Build:
		icon = BuildIcon
	}

	// POST Payload formating
	payload = "payload="
	payload += `{"channel": "#` + strings.ToLower(channel) + `", "username": "` + BotUsername + `", "text": "` + message + `", "icon_emoji": "` + icon + `"}`

	// Debug information
	if Verbose {
		l.Debug("payload =", payload)
	}

	code, body := Post(SlackAPIUrl, payload)
	if code != 200 {
		l.Error("Error post, Slack API returned:", body)
	}

	// Debug information
	if Verbose {
		l.Debug("Slack API returned:", body)
	}
}

/*
	Handler function to handle http requests for push

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *PushServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Push         // Json structure to parse the push webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Push Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Send the message

		// Date parsing (parsing result example : 18 November 2014 - 14:34)
		date, err = time.Parse("2006-01-02T15:04:05Z07:00", j.Commits[0].Timestamp)
		var dateString = date.Format("02 Jan 06 15:04")

		// Message
		lastCommit := j.Commits[len(j.Commits)-1]
		message += "[PUSH] " + n + "Push on *" + j.Repository.Name + "* by *" + j.User_name + "* at *" + dateString + "* on branch *" + j.Ref + "*:" + n // First line
		message += "Last commit : <" + lastCommit.Url + "|" + lastCommit.Id + "> :" + n                                                                  // Second line
		message += "```" + MessageEncode(lastCommit.Message) + "```"                                                                                // Third line (last commit message)
		SendSlackMessage(j.Repository.Name, message, Push)
	}
}

/*
	Handler function to handle http requests for merge

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *MergeServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Merge        // Json structure to parse the push webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Merge Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Send the message

		// Date parsing (parsing result example : 18 November 2014 - 14:34)
		date, err = time.Parse("2006-01-02 15:04:05 UTC", j.Object_attributes.Created_at)
		var dateString = date.Format("02 Jan 06 15:04")

		// Message
		message += "[MERGE REQUEST " + strings.ToUpper(j.Object_attributes.State) + "] " + n + "Target : *" + j.Object_attributes.Target.Name + "/" + j.Object_attributes.Target_branch + "* Source : *" + j.Object_attributes.Source.Name + "/" + j.Object_attributes.Source_branch + "* : at *" + dateString + "* :" + n // First line
		message += "```" + MessageEncode(j.Object_attributes.Description) + "```"                                                                                // Third line (last commit message)
		SendSlackMessage(j.Object_attributes.Target.Name, message, Merge)
	}
}

/*
	Handler function to handle http requests for build

	@param w http.ResponseWriter
	@param r *http.Request
*/
func (s *BuildServ) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var j data.Build        // Json structure to parse the build webhook
	var buffer bytes.Buffer // Buffer to get request body
	var body string         // Request body (it's a json)
	var err error           // Error catching
	var message string = "" // Bot's message
	var date time.Time      // Time of the last commit

	// Log
	l.Info("Build Request")

	// Read http request body and put it in a string
	buffer.ReadFrom(r.Body)
	body = buffer.String()

	// Debug information
	if Verbose {
		l.Debug("JsonString receive =", body)
	}

	// Parse json and put it in a the data.Build structure
	err = json.Unmarshal([]byte(body), &j)
	if err != nil {
		// Error
		l.Error("Error : Json parser failed :", err)
	} else {
		// Ok
		// Debug information
		if Verbose {
			l.Debug("JsonObject =", j)
		}

		// Test if the message is already sent
		if currentBuildID < j.Build_id {
			// Not sent
			currentBuildID = j.Build_id // Update current build ID

			// Send the message

			// Date parsing (parsing result example : 18 November 2014 - 14:34)
			date, err = time.Parse("2006-01-02T15:04:05Z07:00", j.Push_data.Commits[0].Timestamp)
			var dateString = strconv.Itoa(date.Day()) + " " + date.Month().String() + " " + strconv.Itoa(date.Year()) +
				" - " + strconv.Itoa(date.Hour()) + ":" + strconv.Itoa(date.Minute())

			// Message
			lastCommit := j.Push_data.Commits[len(j.Push_data.Commits)-1]
			message += "[BUILD] " + n + strings.ToUpper(j.Build_status) + " : Push on *" + j.Push_data.Repository.Name + "* by *" + j.Push_data.User_name + "* at *" + dateString + "* on branch *" + j.Ref + "*:" + n // First line
			message += "Last commit : <" + lastCommit.Url + "|" + lastCommit.Id + "> :" + n                                                                                // Second line
			message += "```" + MessageEncode(lastCommit.Message) + "```"                                                                                // Third line (last commit message)
			SendSlackMessage(j.Push_data.Repository.Name, message, Build)
		} else {
			// Already sent
			// Do nothing
		}
	}

}

/*
	Main function
*/
func main() {
	flag.Parse()                                             // Parse flags
	l.AddTransport(logo.Console).AddColor(logo.ConsoleColor) // Configure Logger
	l.EnableAllLevels()                                      // Configure Logger
	LoadConf()                                               // Load configuration
	SendSlackMessage(BotChannel, BotStartMessage, Bot)       // Slack notification
	l.Info(BotStartMessage)                                  // Logging
	go http.ListenAndServe(":8100", &PushServ{})             // Run HTTP server for push hook
	go http.ListenAndServe(":8200", &MergeServ{})            // Run HTTP server for merge request hook
	http.ListenAndServe(":8300", &BuildServ{})               // Run HTTP server for build hook
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
)

func main() {
	languages := findLanguages()

	data := map[string]uint64{}
	for _, language := range languages {
		data[language] = getSumForLanguage(language)
	}
	enc := json.NewEncoder(os.Stdout)
	enc.Encode(data)
}

func findLanguages() []string {
	resp, err := http.Get("https://github.com/languages")
	if err != nil {
		return []string{}
	}

	pattern := "
<a href=\"/languages/"

	defer resp.Body.Close()

	languages := []string{}

	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')

		if pos := strings.Index(line, pattern); pos != -1 {
			part := line[pos+len(pattern):]
			lang, _ := url.QueryUnescape(strings.Split(part, "\"")[0])
			languages = append(languages, lang)
		}

		if err != nil {
			break
		}
	}

	return languages
}

func getSumForLanguage(language string) uint64 {
	language = strings.Replace(language, "#", "%23", -1)
	url := fmt.Sprintf("https://github.com/languages/%s/most_watched", language)

	resp, err := http.Get(url)
	if err != nil {
		log.Printf("Error downloading %s: %v", url, err)
		return 0
	}
	defer resp.Body.Close()

	sum := uint64(0)
	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')

		if strings.Contains(line, "mini-icon-star") {
			elems := strings.Split(line, " ")
			starsStr := strings.TrimRight(strings.Replace(elems[len(elems)-1], ",", "", -1), "\r\n\t ")
			stars, err := strconv.ParseUint(starsStr, 10, 64)
			if err == nil {
				sum += stars
			}
		}
		if err != nil {
			break
		}
	}
	return sum
}
<commit_msg>parallelize scraping.<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
)

type langsum struct {
	language string
	sum uint64
}

func main() {
	languages := findLanguages()

	data := map[string]uint64{}

	datachan := make(chan langsum)

	for _, language := range languages {
		go func(language string) {
			sum := getSumForLanguage(language)
			datachan <- langsum{language: language, sum: sum}
		}(language)
	}

	for i := 0; i < len(languages); i++ {
		langSum := <-datachan
		data[langSum.language] = langSum.sum
	}

	enc := json.NewEncoder(os.Stdout)
	enc.Encode(data)
}

func findLanguages() []string {
	resp, err := http.Get("https://github.com/languages")
	if err != nil {
		return []string{}
	}

	pattern := "
<a href=\"/languages/"

	defer resp.Body.Close()

	languages := []string{}

	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')

		if pos := strings.Index(line, pattern); pos != -1 {
			part := line[pos+len(pattern):]
			lang, _ := url.QueryUnescape(strings.Split(part, "\"")[0])
			languages = append(languages, lang)
		}

		if err != nil {
			break
		}
	}

	return languages
}

func getSumForLanguage(language string) uint64 {
	language = strings.Replace(language, "#", "%23", -1)
	url := fmt.Sprintf("https://github.com/languages/%s/most_watched", language)

	resp, err := http.Get(url)
	if err != nil {
		log.Printf("Error downloading %s: %v", url, err)
		return 0
	}
	defer resp.Body.Close()

	sum := uint64(0)
	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')

		if strings.Contains(line, "mini-icon-star") {
			elems := strings.Split(line, " ")
			starsStr := strings.TrimRight(strings.Replace(elems[len(elems)-1], ",", "", -1), "\r\n\t ")
			stars, err := strconv.ParseUint(starsStr, 10, 64)
			if err == nil {
				sum += stars
			}
		}
		if err != nil {
			break
		}
	}
	return sum
}
<|endoftext|>


<commit_before>package ungo

import (
	"encoding/base64"
	"errors"
	"net/http/cookiejar"
	"regexp"
)

var side1 string
var side2 string

func Adfly(url string) (string, error) {
	cookie, _ := cookiejar.New(nil)

	HH.Host = "adf.ly"
	html := htmlDownload(url, cookie)

	ysmmregex := regexp.MustCompile("var ysmm = '(.*)';")
	result := ysmmregex.FindAllStringSubmatch(html.Html, -1)[0:]

	if result == nil {
		return "", errors.New(url + " is not a adfly valid link...")
	}

	for i := 0; i < (len(result[0][1])); i++ {
		if i%2 == 0 {
			side1 += string(result[0][1][i])
		} else {
			side2 = string(result[0][1][i]) + side2
		}
	}

	data, err := base64.StdEncoding.DecodeString(side1 + side2)
	if err != nil {
		return "", errors.New("The url can not be decoded!")
	}

	return string(data[2:]), nil
}
<commit_msg>Add Base64Decode and shorten.id shortener!<commit_after>package ungo

import (
	"errors"
	"net/http/cookiejar"
	"regexp"
)

var side1 string
var side2 string

func Adfly(url string) (string, error) {
	cookie, _ := cookiejar.New(nil)

	HH.Host = "adf.ly"
	html := htmlDownload(url, cookie)

	if html.URL == "http://adf.ly/not-found.php" {
		return "" , errors.New("The URL is not a ADFLY valid link...")
	}

	ysmmregex := regexp.MustCompile("var ysmm = '(.*)';")
	result := ysmmregex.FindAllStringSubmatch(html.Html, -1)[0:]

	if result == nil {
		return "", errors.New(url + " is not a adfly valid link...")
	}

	for i := 0; i < (len(result[0][1])); i++ {
		if i%2 == 0 {
			side1 += string(result[0][1][i])
		} else {
			side2 = string(result[0][1][i]) + side2
		}
	}

	data, err := Base64Decode(side1 + side2)
	if err != nil{
		panic(err)
	}

	return string(data[2:]), nil
}
<|endoftext|>


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

package client

import (
	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
)

func NewCmdTeam(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "team",
		// Hide it:
		// Usage:        "Manage teams.",
		ArgumentHelp: "[arguments...]",
		Subcommands: []cli.Command{
			newCmdTeamCreate(cl, g),
			newCmdTeamDelete(cl, g),
			newCmdTeamListMemberships(cl, g),
			newCmdTeamAddMember(cl, g),
			newCmdTeamRemoveMember(cl, g),
			newCmdTeamEditMember(cl, g),
			newCmdTeamLeave(cl, g),
			newCmdTeamRename(cl, g),
			newCmdTeamShowTree(cl, g),
			newCmdTeamAcceptInvite(cl, g),
			newCmdTeamRequestAccess(cl, g),
			newCmdTeamIgnoreRequest(cl, g),
			newCmdTeamListRequests(cl, g),
		},
	}
}
<commit_msg>Reorder team commands<commit_after>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
)

func NewCmdTeam(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "team",
		// Hide it:
		// Usage:        "Manage teams.",
		ArgumentHelp: "[arguments...]",
		Subcommands: []cli.Command{
			newCmdTeamCreate(cl, g),
			newCmdTeamAddMember(cl, g),
			newCmdTeamRemoveMember(cl, g),
			newCmdTeamEditMember(cl, g),
			newCmdTeamListMemberships(cl, g),
			newCmdTeamShowTree(cl, g),
			newCmdTeamRename(cl, g),
			newCmdTeamRequestAccess(cl, g),
			newCmdTeamListRequests(cl, g),
			newCmdTeamIgnoreRequest(cl, g),
			newCmdTeamAcceptInvite(cl, g),
			newCmdTeamLeave(cl, g),
			newCmdTeamDelete(cl, g),
		},
	}
}
<|endoftext|>


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

package rpcwrap

import (
	"bufio"
	"crypto/tls"
	"errors"
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"golang.org/x/net/context"

	log "github.com/golang/glog"
	rpc "github.com/youtube/vitess/go/rpcplus"
	"github.com/youtube/vitess/go/rpcwrap/auth"
	"github.com/youtube/vitess/go/rpcwrap/proto"
	"github.com/youtube/vitess/go/stats"
)

const (
	connected = "200 Connected to Go RPC"
)

var (
	connCount    = stats.NewInt("connection-count")
	connAccepted = stats.NewInt("connection-accepted")
)

type ClientCodecFactory func(conn io.ReadWriteCloser) rpc.ClientCodec

type BufferedConnection struct {
	isClosed bool
	*bufio.Reader
	io.WriteCloser
}

func NewBufferedConnection(conn io.ReadWriteCloser) *BufferedConnection {
	connCount.Add(1)
	connAccepted.Add(1)
	return &BufferedConnection{false, bufio.NewReader(conn), conn}
}

// FIXME(sougou/szopa): Find a better way to track connection count.
func (bc *BufferedConnection) Close() error {
	if !bc.isClosed {
		bc.isClosed = true
		connCount.Add(-1)
	}
	return bc.WriteCloser.Close()
}

// DialHTTP connects to a go HTTP RPC server using the specified codec.
// use 0 as connectTimeout for no timeout
// use nil as config to not use TLS
func DialHTTP(network, address, codecName string, cFactory ClientCodecFactory, connectTimeout time.Duration, config *tls.Config) (*rpc.Client, error) {
	return dialHTTP(network, address, codecName, cFactory, false, connectTimeout, config)
}

// DialAuthHTTP connects to an authenticated go HTTP RPC server using
// the specified codec and credentials.
// use 0 as connectTimeout for no timeout
// use nil as config to not use TLS
func DialAuthHTTP(network, address, user, password, codecName string, cFactory ClientCodecFactory, connectTimeout time.Duration, config *tls.Config) (conn *rpc.Client, err error) {
	if conn, err = dialHTTP(network, address, codecName, cFactory, true, connectTimeout, config); err != nil {
		return
	}
	reply := new(auth.GetNewChallengeReply)
	if err = conn.Call(context.TODO(), "AuthenticatorCRAMMD5.GetNewChallenge", "", reply); err != nil {
		return
	}
	proof := auth.CRAMMD5GetExpected(user, password, reply.Challenge)

	if err = conn.Call(
		context.TODO(),
		"AuthenticatorCRAMMD5.Authenticate",
		auth.AuthenticateRequest{Proof: proof}, new(auth.AuthenticateReply)); err != nil {
		return
	}
	return
}

func dialHTTP(network, address, codecName string, cFactory ClientCodecFactory, auth bool, connectTimeout time.Duration, config *tls.Config) (*rpc.Client, error) {
	var err error
	var conn net.Conn
	if connectTimeout != 0 {
		conn, err = net.DialTimeout(network, address, connectTimeout)
	} else {
		conn, err = net.Dial(network, address)
	}
	if err != nil {
		return nil, err
	}

	if config != nil {
		conn = tls.Client(conn, config)
	}

	_, err = io.WriteString(conn, "CONNECT "+GetRpcPath(codecName, auth)+" HTTP/1.0\n\n")
	if err != nil {
		return nil, err
	}

	// Require successful HTTP response
	// before switching to RPC protocol.
	buffered := NewBufferedConnection(conn)
	resp, err := http.ReadResponse(buffered.Reader, &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {
		return rpc.NewClientWithCodec(cFactory(buffered)), nil
	}
	if err == nil {
		err = errors.New("unexpected HTTP response: " + resp.Status)
	}
	conn.Close()
	return nil, &net.OpError{Op: "dial-http", Net: network + " " + address, Addr: nil, Err: err}
}

type ServerCodecFactory func(conn io.ReadWriteCloser) rpc.ServerCodec

// ServeRPC handles rpc requests using the hijack scheme of rpc
func ServeRPC(codecName string, cFactory ServerCodecFactory) {
	http.Handle(GetRpcPath(codecName, false), &rpcHandler{cFactory, rpc.DefaultServer, false})
}

// ServeAuthRPC handles authenticated rpc requests using the hijack
// scheme of rpc
func ServeAuthRPC(codecName string, cFactory ServerCodecFactory) {
	http.Handle(GetRpcPath(codecName, true), &rpcHandler{cFactory, AuthenticatedServer, true})
}

// ServeCustomRPC serves the given rpc requests with the provided ServeMux,
// authenticated or not
func ServeCustomRPC(handler *http.ServeMux, server *rpc.Server, useAuth bool, codecName string, cFactory ServerCodecFactory) {
	handler.Handle(GetRpcPath(codecName, useAuth), &rpcHandler{cFactory, server, useAuth})
}

// AuthenticatedServer is an rpc.Server instance that serves
// authenticated calls.
var AuthenticatedServer = rpc.NewServer()

// rpcHandler handles rpc queries for a 'CONNECT' method.
type rpcHandler struct {
	cFactory ServerCodecFactory
	server   *rpc.Server
	useAuth  bool
}

// ServeHTTP implements http.Handler's ServeHTTP
func (h *rpcHandler) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	if req.Method != "CONNECT" {
		c.Header().Set("Content-Type", "text/plain; charset=utf-8")
		c.WriteHeader(http.StatusMethodNotAllowed)
		io.WriteString(c, "405 must CONNECT\n")
		return
	}
	conn, _, err := c.(http.Hijacker).Hijack()
	if err != nil {
		log.Errorf("rpc hijacking %s: %v", req.RemoteAddr, err)
		return
	}
	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
	codec := h.cFactory(NewBufferedConnection(conn))
	ctx := proto.NewContext(req.RemoteAddr)
	if h.useAuth {
		if authenticated, err := auth.Authenticate(ctx, codec); !authenticated {
			if err != nil {
				log.Errorf("authentication erred at %s: %v", req.RemoteAddr, err)
			}
			codec.Close()
			return
		}
	}
	h.server.ServeCodecWithContext(ctx, codec)
}

// GetRpcPath returns the toplevel path used for serving RPCs over HTTP
func GetRpcPath(codecName string, auth bool) string {
	path := "/_" + codecName + "_rpc_"
	if auth {
		path += "/auth"
	}
	return path
}

// httpRpcHandler handles rpc queries for a all types of HTTP requests.
type httpRpcHandler struct {
	cFactory ServerCodecFactory
	server   *rpc.Server
}

// ServeHTTP implements http.Handler's ServeHTTP
func (h *httpRpcHandler) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	codec := h.cFactory(NewBufferedConnection(
		&httpReadWriteCloser{rw: c, req: req},
	))

	ctx := proto.NewContext(req.RemoteAddr)

	h.server.ServeCodecWithContextOnce(
		new(sync.Mutex),
		false,
		ctx,
		codec,
	)

	codec.Close()
}

func ServeHTTPRPC(handler *http.ServeMux, server *rpc.Server, codecName string, cFactory ServerCodecFactory) {
	handler.Handle(GetRpcPath(codecName, false), &httpRpcHandler{cFactory, server})
}

type httpReadWriteCloser struct {
	rw  http.ResponseWriter
	req *http.Request
}

func (i *httpReadWriteCloser) Read(p []byte) (n int, err error) {
	return i.req.Body.Read(p)
}

func (i *httpReadWriteCloser) Write(p []byte) (n int, err error) {
	return i.rw.Write(p)
}

func (i *httpReadWriteCloser) Close() error {
	return i.req.Body.Close()
}
<commit_msg>rpcwrap: added better documentation and context creator func<commit_after>// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rpcwrap

import (
	"bufio"
	"crypto/tls"
	"errors"
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"golang.org/x/net/context"

	log "github.com/golang/glog"
	rpc "github.com/youtube/vitess/go/rpcplus"
	"github.com/youtube/vitess/go/rpcwrap/auth"
	"github.com/youtube/vitess/go/rpcwrap/proto"
	"github.com/youtube/vitess/go/stats"
)

const (
	connected = "200 Connected to Go RPC"
)

var (
	connCount    = stats.NewInt("connection-count")
	connAccepted = stats.NewInt("connection-accepted")
)

type ClientCodecFactory func(conn io.ReadWriteCloser) rpc.ClientCodec

type BufferedConnection struct {
	isClosed bool
	*bufio.Reader
	io.WriteCloser
}

func NewBufferedConnection(conn io.ReadWriteCloser) *BufferedConnection {
	connCount.Add(1)
	connAccepted.Add(1)
	return &BufferedConnection{false, bufio.NewReader(conn), conn}
}

// FIXME(sougou/szopa): Find a better way to track connection count.
func (bc *BufferedConnection) Close() error {
	if !bc.isClosed {
		bc.isClosed = true
		connCount.Add(-1)
	}
	return bc.WriteCloser.Close()
}

// DialHTTP connects to a go HTTP RPC server using the specified codec.
// use 0 as connectTimeout for no timeout
// use nil as config to not use TLS
func DialHTTP(network, address, codecName string, cFactory ClientCodecFactory, connectTimeout time.Duration, config *tls.Config) (*rpc.Client, error) {
	return dialHTTP(network, address, codecName, cFactory, false, connectTimeout, config)
}

// DialAuthHTTP connects to an authenticated go HTTP RPC server using
// the specified codec and credentials.
// use 0 as connectTimeout for no timeout
// use nil as config to not use TLS
func DialAuthHTTP(network, address, user, password, codecName string, cFactory ClientCodecFactory, connectTimeout time.Duration, config *tls.Config) (conn *rpc.Client, err error) {
	if conn, err = dialHTTP(network, address, codecName, cFactory, true, connectTimeout, config); err != nil {
		return
	}
	reply := new(auth.GetNewChallengeReply)
	if err = conn.Call(context.TODO(), "AuthenticatorCRAMMD5.GetNewChallenge", "", reply); err != nil {
		return
	}
	proof := auth.CRAMMD5GetExpected(user, password, reply.Challenge)

	if err = conn.Call(
		context.TODO(),
		"AuthenticatorCRAMMD5.Authenticate",
		auth.AuthenticateRequest{Proof: proof}, new(auth.AuthenticateReply)); err != nil {
		return
	}
	return
}

func dialHTTP(network, address, codecName string, cFactory ClientCodecFactory, auth bool, connectTimeout time.Duration, config *tls.Config) (*rpc.Client, error) {
	var err error
	var conn net.Conn
	if connectTimeout != 0 {
		conn, err = net.DialTimeout(network, address, connectTimeout)
	} else {
		conn, err = net.Dial(network, address)
	}
	if err != nil {
		return nil, err
	}

	if config != nil {
		conn = tls.Client(conn, config)
	}

	_, err = io.WriteString(conn, "CONNECT "+GetRpcPath(codecName, auth)+" HTTP/1.0\n\n")
	if err != nil {
		return nil, err
	}

	// Require successful HTTP response
	// before switching to RPC protocol.
	buffered := NewBufferedConnection(conn)
	resp, err := http.ReadResponse(buffered.Reader, &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {
		return rpc.NewClientWithCodec(cFactory(buffered)), nil
	}
	if err == nil {
		err = errors.New("unexpected HTTP response: " + resp.Status)
	}
	conn.Close()
	return nil, &net.OpError{Op: "dial-http", Net: network + " " + address, Addr: nil, Err: err}
}

type ServerCodecFactory func(conn io.ReadWriteCloser) rpc.ServerCodec

// ServeRPC handles rpc requests using the hijack scheme of rpc
func ServeRPC(codecName string, cFactory ServerCodecFactory) {
	http.Handle(GetRpcPath(codecName, false), &rpcHandler{cFactory, rpc.DefaultServer, false})
}

// ServeAuthRPC handles authenticated rpc requests using the hijack
// scheme of rpc
func ServeAuthRPC(codecName string, cFactory ServerCodecFactory) {
	http.Handle(GetRpcPath(codecName, true), &rpcHandler{cFactory, AuthenticatedServer, true})
}

// ServeCustomRPC serves the given rpc requests with the provided ServeMux,
// authenticated or not
func ServeCustomRPC(handler *http.ServeMux, server *rpc.Server, useAuth bool, codecName string, cFactory ServerCodecFactory) {
	handler.Handle(GetRpcPath(codecName, useAuth), &rpcHandler{cFactory, server, useAuth})
}

// AuthenticatedServer is an rpc.Server instance that serves
// authenticated calls.
var AuthenticatedServer = rpc.NewServer()

// rpcHandler handles rpc queries for a 'CONNECT' method.
type rpcHandler struct {
	cFactory ServerCodecFactory
	server   *rpc.Server
	useAuth  bool
}

// ServeHTTP implements http.Handler's ServeHTTP
func (h *rpcHandler) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	if req.Method != "CONNECT" {
		c.Header().Set("Content-Type", "text/plain; charset=utf-8")
		c.WriteHeader(http.StatusMethodNotAllowed)
		io.WriteString(c, "405 must CONNECT\n")
		return
	}
	conn, _, err := c.(http.Hijacker).Hijack()
	if err != nil {
		log.Errorf("rpc hijacking %s: %v", req.RemoteAddr, err)
		return
	}
	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
	codec := h.cFactory(NewBufferedConnection(conn))
	ctx := proto.NewContext(req.RemoteAddr)
	if h.useAuth {
		if authenticated, err := auth.Authenticate(ctx, codec); !authenticated {
			if err != nil {
				log.Errorf("authentication erred at %s: %v", req.RemoteAddr, err)
			}
			codec.Close()
			return
		}
	}
	h.server.ServeCodecWithContext(ctx, codec)
}

// GetRpcPath returns the toplevel path used for serving RPCs over HTTP
func GetRpcPath(codecName string, auth bool) string {
	path := "/_" + codecName + "_rpc_"
	if auth {
		path += "/auth"
	}
	return path
}

// ServeCustomRPC serves the given http rpc requests with the provided ServeMux,
// does not support built-in authentication
func ServeHTTPRPC(
	handler *http.ServeMux,
	server *rpc.Server,
	codecName string,
	cFactory ServerCodecFactory,
	contextCreator func(*http.Request) context.Context) {

	handler.Handle(
		GetRpcPath(codecName, false),
		&httpRpcHandler{
			cFactory:       cFactory,
			server:         server,
			contextCreator: contextCreator,
		},
	)
}

// httpRpcHandler handles rpc queries for a all types of HTTP requests, does not
// maintain a persistent connection.
type httpRpcHandler struct {
	cFactory ServerCodecFactory
	server   *rpc.Server
	// contextCreator creates an application specific context, while creating
	// the context it should not read the request body nor write anything to
	// headers
	contextCreator func(*http.Request) context.Context
}

// ServeHTTP implements http.Handler's ServeHTTP
func (h *httpRpcHandler) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	codec := h.cFactory(NewBufferedConnection(
		&httpReadWriteCloser{rw: c, req: req},
	))

	var ctx context.Context

	if h.contextCreator != nil {
		ctx = h.contextCreator(req)
	} else {
		ctx = proto.NewContext(req.RemoteAddr)
	}

	h.server.ServeCodecWithContextOnce(
		new(sync.Mutex),
		false,
		ctx,
		codec,
	)

	codec.Close()
}

// httpReadWriteCloser wraps http.ResponseWriter and http.Request, with the help
// of those, implements ReadWriteCloser interface
type httpReadWriteCloser struct {
	rw  http.ResponseWriter
	req *http.Request
}

// Read implements Reader interface
func (i *httpReadWriteCloser) Read(p []byte) (n int, err error) {
	return i.req.Body.Read(p)
}

// Write implements Writer interface
func (i *httpReadWriteCloser) Write(p []byte) (n int, err error) {
	return i.rw.Write(p)
}

// Close implements Closer interface
func (i *httpReadWriteCloser) Close() error {
	return i.req.Body.Close()
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/cloudresourcemanager/v1"
)

var IamProjectSchema = map[string]*schema.Schema{
	"project": {
		Type:     schema.TypeString,
		Optional: true,
		ForceNew: true,
	},
}

type ProjectIamUpdater struct {
	resourceId string
	Config     *Config
}

func NewProjectIamUpdater(d *schema.ResourceData, config *Config) (ResourceIamUpdater, error) {
	pid, err := getProject(d, config)
	if err != nil {
		return nil, err
	}

	return &ProjectIamUpdater{
		resourceId: pid,
		Config:     config,
	}, nil
}

func ProjectIdParseFunc(d *schema.ResourceData, _ *Config) error {
	d.Set("project", d.Id())
	return nil
}

func (u *ProjectIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
	p, err := u.Config.clientResourceManager.Projects.GetIamPolicy(u.resourceId,
		&cloudresourcemanager.GetIamPolicyRequest{}).Do()

	if err != nil {
		return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err)
	}

	return p, nil
}

func (u *ProjectIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
	_, err := u.Config.clientResourceManager.Projects.SetIamPolicy(u.resourceId, &cloudresourcemanager.SetIamPolicyRequest{
		Policy:     policy,
		UpdateMask: "bindings,etag,auditConfigs",
	}).Do()

	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err)
	}

	return nil
}

func (u *ProjectIamUpdater) GetResourceId() string {
	return u.resourceId
}

func (u *ProjectIamUpdater) GetMutexKey() string {
	return getProjectIamPolicyMutexKey(u.resourceId)
}

func (u *ProjectIamUpdater) DescribeResource() string {
	return fmt.Sprintf("project %q", u.resourceId)
}
<commit_msg>Mark project as computed for iam-project (#3777)<commit_after>package google

import (
	"fmt"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/cloudresourcemanager/v1"
)

var IamProjectSchema = map[string]*schema.Schema{
	"project": {
		Type:     schema.TypeString,
		Optional: true,
		Computed: true,
		ForceNew: true,
	},
}

type ProjectIamUpdater struct {
	resourceId string
	Config     *Config
}

func NewProjectIamUpdater(d *schema.ResourceData, config *Config) (ResourceIamUpdater, error) {
	pid, err := getProject(d, config)
	if err != nil {
		return nil, err
	}

	return &ProjectIamUpdater{
		resourceId: pid,
		Config:     config,
	}, nil
}

func ProjectIdParseFunc(d *schema.ResourceData, _ *Config) error {
	d.Set("project", d.Id())
	return nil
}

func (u *ProjectIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
	p, err := u.Config.clientResourceManager.Projects.GetIamPolicy(u.resourceId,
		&cloudresourcemanager.GetIamPolicyRequest{}).Do()

	if err != nil {
		return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err)
	}

	return p, nil
}

func (u *ProjectIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
	_, err := u.Config.clientResourceManager.Projects.SetIamPolicy(u.resourceId, &cloudresourcemanager.SetIamPolicyRequest{
		Policy:     policy,
		UpdateMask: "bindings,etag,auditConfigs",
	}).Do()

	if err != nil {
		return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err)
	}

	return nil
}

func (u *ProjectIamUpdater) GetResourceId() string {
	return u.resourceId
}

func (u *ProjectIamUpdater) GetMutexKey() string {
	return getProjectIamPolicyMutexKey(u.resourceId)
}

func (u *ProjectIamUpdater) DescribeResource() string {
	return fmt.Sprintf("project %q", u.resourceId)
}
<|endoftext|>


<commit_before>//
// Generate an RSS feed from a PostgreSQL database containing tweets.
//
// The tweet database is the one populated by my twitter-tcl twitter_poll
// program.
//
package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/horgh/config"
	"github.com/horgh/gorse/gorselib"
	_ "github.com/lib/pq"
)

// FeedURI is the URI set on the RSS feed's channel element's link element. It
// need not be a real URI but should be unique.
var FeedURI = "https://leviathan.summercat.com/tweets/"

// Tweet describe a tweet pulled from the database.
type Tweet struct {
	Nick    string
	Text    string
	Time    time.Time
	TweetID int64
}

// MyConfig holds configuration values.
type MyConfig struct {
	DBUser string
	DBPass string
	DBName string
	DBHost string
	// The number of recent tweets to put in the XML.
	NumTweets uint64
}

// connectToDB opens a new connection to the database.
func connectToDB(name string, user string, pass string, host string) (*sql.DB,
	error) {
	dsn := fmt.Sprintf("user=%s password=%s dbname=%s host=%s", user, pass, name,
		host)

	db, err := sql.Open("postgres", dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to the database: %s", err)
	}

	return db, nil
}

// getTweets retrieves tweets from a database.
func getTweets(config *MyConfig) ([]Tweet, error) {
	db, err := connectToDB(config.DBName, config.DBUser, config.DBPass,
		config.DBHost)
	if err != nil {
		return nil, err
	}

	defer func() {
		err := db.Close()
		if err != nil {
			log.Printf("Database close: %s", err)
		}
	}()

	// get most recent tweets.
	sql := `
SELECT nick, text, time, tweet_id
FROM tweet
ORDER BY time DESC
LIMIT $1
`
	rows, err := db.Query(sql, config.NumTweets)
	if err != nil {
		return nil, fmt.Errorf("query failure: %s", err)
	}

	var tweets []Tweet
	for rows.Next() {
		tweet := Tweet{}

		err = rows.Scan(&tweet.Nick, &tweet.Text, &tweet.Time, &tweet.TweetID)
		if err != nil {
			return nil, fmt.Errorf("failed to scan row: %s", err)
		}

		tweets = append(tweets, tweet)
	}

	return tweets, nil
}

// Create a URL to the status.
//
// Apparently this URL is not in the tweet status payload.
//
// Form: https://twitter.com/<screenname>/status/<tweetid>
func createStatusURL(screenName string, tweetID int64) string {
	return fmt.Sprintf("https://twitter.com/%s/status/%d", screenName, tweetID)
}

func main() {
	log.SetFlags(log.Ltime | log.Llongfile)

	outputFile := flag.String("output-file", "", "Output XML file to write.")
	configFile := flag.String("config-file", "", "Config file")

	flag.Parse()

	if len(*outputFile) == 0 || len(*configFile) == 0 {
		fmt.Println("You must provide a config file.")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var settings MyConfig
	err := config.GetConfig(*configFile, &settings)
	if err != nil {
		log.Fatalf("Failed to retrieve config: %s", err)
	}

	// TODO: We could run validation on each config item.

	gorselib.SetQuiet(true)

	tweets, err := getTweets(&settings)
	if err != nil {
		log.Fatalf("Failed to retrieve tweets: %s", err)
	}

	rss := gorselib.RSSFeed{}
	rss.Name = "Twitreader"
	rss.URI = FeedURI
	rss.Description = "Twitreader tweets"
	rss.LastUpdateTime = time.Now()

	for _, tweet := range tweets {
		item := gorselib.RSSItem{
			Title:           fmt.Sprintf("%s", tweet.Nick),
			URI:             createStatusURL(tweet.Nick, tweet.TweetID),
			Description:     tweet.Text,
			PublicationDate: tweet.Time,
		}
		rss.Items = append(rss.Items, item)
	}

	err = gorselib.WriteFeedXML(&rss, *outputFile)
	if err != nil {
		log.Fatalf("Failed to write XML: %s", err)
	}
}
<commit_msg>Use Feed/Item types instead of RSSFeed/RSSItem<commit_after>//
// Generate an RSS feed from a PostgreSQL database containing tweets.
//
// The tweet database is the one populated by my twitter-tcl twitter_poll
// program.
//
package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/horgh/config"
	"github.com/horgh/gorse/gorselib"
	_ "github.com/lib/pq"
)

// FeedURI is the URI set on the RSS feed's channel element's link element. It
// need not be a real URI but should be unique.
var FeedURI = "https://leviathan.summercat.com/tweets/"

// Tweet describe a tweet pulled from the database.
type Tweet struct {
	Nick    string
	Text    string
	Time    time.Time
	TweetID int64
}

// MyConfig holds configuration values.
type MyConfig struct {
	DBUser string
	DBPass string
	DBName string
	DBHost string
	// The number of recent tweets to put in the XML.
	NumTweets uint64
}

// connectToDB opens a new connection to the database.
func connectToDB(name string, user string, pass string, host string) (*sql.DB,
	error) {
	dsn := fmt.Sprintf("user=%s password=%s dbname=%s host=%s", user, pass, name,
		host)

	db, err := sql.Open("postgres", dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to the database: %s", err)
	}

	return db, nil
}

// getTweets retrieves tweets from a database.
func getTweets(config *MyConfig) ([]Tweet, error) {
	db, err := connectToDB(config.DBName, config.DBUser, config.DBPass,
		config.DBHost)
	if err != nil {
		return nil, err
	}

	defer func() {
		err := db.Close()
		if err != nil {
			log.Printf("Database close: %s", err)
		}
	}()

	// get most recent tweets.
	sql := `
SELECT nick, text, time, tweet_id
FROM tweet
ORDER BY time DESC
LIMIT $1
`
	rows, err := db.Query(sql, config.NumTweets)
	if err != nil {
		return nil, fmt.Errorf("query failure: %s", err)
	}

	var tweets []Tweet
	for rows.Next() {
		tweet := Tweet{}

		err = rows.Scan(&tweet.Nick, &tweet.Text, &tweet.Time, &tweet.TweetID)
		if err != nil {
			return nil, fmt.Errorf("failed to scan row: %s", err)
		}

		tweets = append(tweets, tweet)
	}

	return tweets, nil
}

// Create a URL to the status.
//
// Apparently this URL is not in the tweet status payload.
//
// Form: https://twitter.com/<screenname>/status/<tweetid>
func createStatusURL(screenName string, tweetID int64) string {
	return fmt.Sprintf("https://twitter.com/%s/status/%d", screenName, tweetID)
}

func main() {
	log.SetFlags(log.Ltime | log.Llongfile)

	outputFile := flag.String("output-file", "", "Output XML file to write.")
	configFile := flag.String("config-file", "", "Config file")

	flag.Parse()

	if len(*outputFile) == 0 || len(*configFile) == 0 {
		fmt.Println("You must provide a config file.")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var settings MyConfig
	err := config.GetConfig(*configFile, &settings)
	if err != nil {
		log.Fatalf("Failed to retrieve config: %s", err)
	}

	// TODO: We could run validation on each config item.

	gorselib.SetQuiet(true)

	tweets, err := getTweets(&settings)
	if err != nil {
		log.Fatalf("Failed to retrieve tweets: %s", err)
	}

	rss := gorselib.Feed{
		Title:       "Twitreader",
		Link:        FeedURI,
		Description: "Twitreader tweets",
		PubDate:     time.Now(),
	}

	for _, tweet := range tweets {
		rss.Items = append(rss.Items, gorselib.Item{
			Title:       fmt.Sprintf("%s", tweet.Nick),
			Link:        createStatusURL(tweet.Nick, tweet.TweetID),
			Description: tweet.Text,
			PubDate:     tweet.Time,
		})
	}

	err = gorselib.WriteFeedXML(rss, *outputFile)
	if err != nil {
		log.Fatalf("Failed to write XML: %s", err)
	}
}
<|endoftext|>


<commit_before>package newcot

// Closed represents an instance of the grid in [0, 1]^n.
type Closed struct {
	nd int
}

// NewClosed creates an instance of the grid in [0, 1]^n.
func NewClosed(dimensions uint) *Closed {
	return &Closed{int(dimensions)}
}

// Compute returns the nodes corresponding to the given indices.
func (_ *Closed) Compute(indices []uint64) []float64 {
	nodes := make([]float64, len(indices))

	for i := range nodes {
		level := 0xFFFFFFFF & indices[i]
		if level == 0 {
			nodes[i] = 0.5
		} else {
			nodes[i] = float64(indices[i]>>32) / float64(uint64(2)<<(level-1))
		}
	}

	return nodes
}

// Refine returns the child indices corresponding to a set of parent indices.
func (c *Closed) Refine(indices []uint64) []uint64 {
	nd := c.nd
	nn := len(indices) / nd

	childIndices := make([]uint64, 2*nn*nd*nd)

	nc := 0
	push := func(p, d int, pair uint64) {
		copy(childIndices[nc*nd:], indices[p*nd:(p+1)*nd])
		childIndices[nc*nd+d] = pair
		nc++
	}

	for i := 0; i < nn; i++ {
		for j := 0; j < nd; j++ {
			level := 0xFFFFFFFF & indices[i*nd+j]

			if level == 0 {
				push(i, j, 1|0<<32)
				push(i, j, 1|2<<32)
				continue
			}

			order := indices[i*nd+j] >> 32

			if level == 1 {
				push(i, j, 2|(order+1)<<32)
			} else {
				push(i, j, (level+1)|(2*order-1)<<32)
				push(i, j, (level+1)|(2*order+1)<<32)
			}
		}
	}

	return childIndices[0 : nc*nd]
}

// Parent transforms an index into its parent index in the ith dimension.
func (_ *Closed) Parent(_ []uint64, _ uint) {
}

// Sibling transforms an index into its sibling index in the ith dimension.
func (_ *Closed) Sibling(_ []uint64, _ uint) {
}
<commit_msg>newcot/closed: a cosmetic change<commit_after>package newcot

// Closed represents an instance of the grid in [0, 1]^n.
type Closed struct {
	nd int
}

// NewClosed creates an instance of the grid in [0, 1]^n.
func NewClosed(dimensions uint) *Closed {
	return &Closed{int(dimensions)}
}

// Compute returns the nodes corresponding to the given indices.
func (_ *Closed) Compute(indices []uint64) []float64 {
	nodes := make([]float64, len(indices))

	for i := range nodes {
		level := 0xFFFFFFFF & indices[i]
		if level == 0 {
			nodes[i] = 0.5
		} else {
			nodes[i] = float64(indices[i]>>32) / float64(uint64(2)<<(level-1))
		}
	}

	return nodes
}

// Refine returns the child indices corresponding to a set of parent indices.
func (c *Closed) Refine(indices []uint64) []uint64 {
	nd := c.nd
	nn := len(indices) / nd

	childIndices := make([]uint64, 2*nn*nd*nd)

	nc := 0
	push := func(p, d int, pair uint64) {
		copy(childIndices[nc*nd:], indices[p*nd:(p+1)*nd])
		childIndices[nc*nd+d] = pair
		nc++
	}

	for i := 0; i < nn; i++ {
		for j := 0; j < nd; j++ {
			level := 0xFFFFFFFF & indices[i*nd+j]

			if level == 0 {
				push(i, j, 1|0<<32)
				push(i, j, 1|2<<32)
				continue
			}

			order := indices[i*nd+j] >> 32

			if level == 1 {
				push(i, j, 2|(order+1)<<32)
			} else {
				push(i, j, (level+1)|(2*order-1)<<32)
				push(i, j, (level+1)|(2*order+1)<<32)
			}
		}
	}

	return childIndices[:nc*nd]
}

// Parent transforms an index into its parent index in the ith dimension.
func (_ *Closed) Parent(_ []uint64, _ uint) {
}

// Sibling transforms an index into its sibling index in the ith dimension.
func (_ *Closed) Sibling(_ []uint64, _ uint) {
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/docker"
	_ "github.com/globocom/tsuru/provision/juju"
	_ "github.com/globocom/tsuru/provision/lxc"
	stdlog "log"
	"log/syslog"
	"net"
	"net/http"
	"os"
)

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	log.Fatal(err)
}

func main() {
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		stdlog.Fatal(err)
	}
	log.SetLogger(logger)
	configFile := flag.String("config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	flag.Parse()
	err = config.ReadAndWatchConfigFile(*configFile)
	if err != nil {
		fatal(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	fmt.Printf("Using the database %q from the server %q.\n\n", dbName, connString)

	m := pat.New()

	m.Get("/services/instances", authorizationRequiredHandler(ServicesInstancesHandler))
	m.Post("/services/instances", authorizationRequiredHandler(CreateInstanceHandler))
	m.Put("/services/instances/:instance/:app", authorizationRequiredHandler(bindServiceInstance))
	m.Del("/services/instances/:instance/:app", authorizationRequiredHandler(unbindServiceInstance))
	m.Del("/services/c/instances/:name", authorizationRequiredHandler(RemoveServiceInstanceHandler))
	m.Get("/services/instances/:instance/status", authorizationRequiredHandler(ServiceInstanceStatusHandler))

	m.Get("/services", authorizationRequiredHandler(ServicesHandler))
	m.Post("/services", authorizationRequiredHandler(CreateHandler))
	m.Put("/services", authorizationRequiredHandler(UpdateHandler))
	m.Del("/services/:name", authorizationRequiredHandler(DeleteHandler))
	m.Get("/services/:name", authorizationRequiredHandler(ServiceInfoHandler))
	m.Get("/services/c/:name/doc", authorizationRequiredHandler(Doc))
	m.Get("/services/:name/doc", authorizationRequiredHandler(GetDocHandler))
	m.Put("/services/:name/doc", authorizationRequiredHandler(AddDocHandler))
	m.Put("/services/:service/:team", authorizationRequiredHandler(GrantServiceAccessToTeamHandler))
	m.Del("/services/:service/:team", authorizationRequiredHandler(RevokeServiceAccessFromTeamHandler))

	m.Del("/apps/:app", authorizationRequiredHandler(appDelete))
	m.Get("/apps/:app", authorizationRequiredHandler(appInfo))
	m.Post("/apps/:app", authorizationRequiredHandler(setCName))
	m.Post("/apps/:app/run", authorizationRequiredHandler(runCommand))
	m.Get("/apps/:app/restart", authorizationRequiredHandler(restart))
	m.Get("/apps/:app/env", authorizationRequiredHandler(getEnv))
	m.Post("/apps/:app/env", authorizationRequiredHandler(setEnv))
	m.Del("/apps/:app/env", authorizationRequiredHandler(unsetEnv))
	m.Get("/apps", authorizationRequiredHandler(appList))
	m.Post("/apps", authorizationRequiredHandler(createApp))
	m.Put("/apps/:app/units", authorizationRequiredHandler(addUnits))
	m.Del("/apps/:app/units", authorizationRequiredHandler(removeUnits))
	m.Put("/apps/:app/:team", authorizationRequiredHandler(grantAccessToTeam))
	m.Del("/apps/:app/:team", authorizationRequiredHandler(revokeAccessFromTeam))
	m.Get("/apps/:app/log", authorizationRequiredHandler(appLog))
	m.Post("/apps/:app/log", authorizationRequiredHandler(addLog))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Get("/apps/:appname/avaliable", authorizationRequiredHandler(appIsAvailable))
	m.Get("/apps/:appname/repository/clone", authorizationRequiredHandler(cloneRepository))

	if registrationEnabled, _ := config.GetBool("auth:user-registration"); registrationEnabled {
		m.Post("/users", handler(CreateUser))
	}

	m.Post("/users/:email/tokens", handler(login))
	m.Put("/users/password", authorizationRequiredHandler(ChangePassword))
	m.Del("/users", authorizationRequiredHandler(RemoveUser))
	m.Post("/users/keys", authorizationRequiredHandler(AddKeyToUser))
	m.Del("/users/keys", authorizationRequiredHandler(RemoveKeyFromUser))

	m.Post("/tokens", adminRequiredHandler(generateAppToken))

	m.Get("/teams", authorizationRequiredHandler(ListTeams))
	m.Post("/teams", authorizationRequiredHandler(CreateTeam))
	m.Del("/teams/:name", authorizationRequiredHandler(RemoveTeam))
	m.Put("/teams/:team/:user", authorizationRequiredHandler(AddUserToTeam))
	m.Del("/teams/:team/:user", authorizationRequiredHandler(RemoveUserFromTeam))

	m.Get("/healers", authorizationRequiredHandler(healers))
	m.Get("/healers/:healer", authorizationRequiredHandler(healer))

	if !*dry {
		provisioner, err := config.GetString("provisioner")
		if err != nil {
			fmt.Printf("Warning: %q didn't declare a provisioner, using default provisioner.\n", *configFile)
			provisioner = "juju"
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls-cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls-key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", m)
			fatal(http.Serve(listener, nil))
		}
	}
}
<commit_msg>api: register resetPassword handler<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/docker"
	_ "github.com/globocom/tsuru/provision/juju"
	_ "github.com/globocom/tsuru/provision/lxc"
	stdlog "log"
	"log/syslog"
	"net"
	"net/http"
	"os"
)

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	log.Fatal(err)
}

func main() {
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		stdlog.Fatal(err)
	}
	log.SetLogger(logger)
	configFile := flag.String("config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	flag.Parse()
	err = config.ReadAndWatchConfigFile(*configFile)
	if err != nil {
		fatal(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	fmt.Printf("Using the database %q from the server %q.\n\n", dbName, connString)

	m := pat.New()

	m.Get("/services/instances", authorizationRequiredHandler(ServicesInstancesHandler))
	m.Post("/services/instances", authorizationRequiredHandler(CreateInstanceHandler))
	m.Put("/services/instances/:instance/:app", authorizationRequiredHandler(bindServiceInstance))
	m.Del("/services/instances/:instance/:app", authorizationRequiredHandler(unbindServiceInstance))
	m.Del("/services/c/instances/:name", authorizationRequiredHandler(RemoveServiceInstanceHandler))
	m.Get("/services/instances/:instance/status", authorizationRequiredHandler(ServiceInstanceStatusHandler))

	m.Get("/services", authorizationRequiredHandler(ServicesHandler))
	m.Post("/services", authorizationRequiredHandler(CreateHandler))
	m.Put("/services", authorizationRequiredHandler(UpdateHandler))
	m.Del("/services/:name", authorizationRequiredHandler(DeleteHandler))
	m.Get("/services/:name", authorizationRequiredHandler(ServiceInfoHandler))
	m.Get("/services/c/:name/doc", authorizationRequiredHandler(Doc))
	m.Get("/services/:name/doc", authorizationRequiredHandler(GetDocHandler))
	m.Put("/services/:name/doc", authorizationRequiredHandler(AddDocHandler))
	m.Put("/services/:service/:team", authorizationRequiredHandler(GrantServiceAccessToTeamHandler))
	m.Del("/services/:service/:team", authorizationRequiredHandler(RevokeServiceAccessFromTeamHandler))

	m.Del("/apps/:app", authorizationRequiredHandler(appDelete))
	m.Get("/apps/:app", authorizationRequiredHandler(appInfo))
	m.Post("/apps/:app", authorizationRequiredHandler(setCName))
	m.Post("/apps/:app/run", authorizationRequiredHandler(runCommand))
	m.Get("/apps/:app/restart", authorizationRequiredHandler(restart))
	m.Get("/apps/:app/env", authorizationRequiredHandler(getEnv))
	m.Post("/apps/:app/env", authorizationRequiredHandler(setEnv))
	m.Del("/apps/:app/env", authorizationRequiredHandler(unsetEnv))
	m.Get("/apps", authorizationRequiredHandler(appList))
	m.Post("/apps", authorizationRequiredHandler(createApp))
	m.Put("/apps/:app/units", authorizationRequiredHandler(addUnits))
	m.Del("/apps/:app/units", authorizationRequiredHandler(removeUnits))
	m.Put("/apps/:app/:team", authorizationRequiredHandler(grantAccessToTeam))
	m.Del("/apps/:app/:team", authorizationRequiredHandler(revokeAccessFromTeam))
	m.Get("/apps/:app/log", authorizationRequiredHandler(appLog))
	m.Post("/apps/:app/log", authorizationRequiredHandler(addLog))

	// These handlers don't use :app on purpose. Using :app means that only
	// the token generate for the given app is valid, but these handlers
	// use a token generated for Gandalf.
	m.Get("/apps/:appname/avaliable", authorizationRequiredHandler(appIsAvailable))
	m.Get("/apps/:appname/repository/clone", authorizationRequiredHandler(cloneRepository))

	if registrationEnabled, _ := config.GetBool("auth:user-registration"); registrationEnabled {
		m.Post("/users", handler(CreateUser))
	}

	m.Post("/users/:email/password", handler(resetPassword))
	m.Post("/users/:email/tokens", handler(login))
	m.Put("/users/password", authorizationRequiredHandler(ChangePassword))
	m.Del("/users", authorizationRequiredHandler(RemoveUser))
	m.Post("/users/keys", authorizationRequiredHandler(AddKeyToUser))
	m.Del("/users/keys", authorizationRequiredHandler(RemoveKeyFromUser))

	m.Post("/tokens", adminRequiredHandler(generateAppToken))

	m.Get("/teams", authorizationRequiredHandler(ListTeams))
	m.Post("/teams", authorizationRequiredHandler(CreateTeam))
	m.Del("/teams/:name", authorizationRequiredHandler(RemoveTeam))
	m.Put("/teams/:team/:user", authorizationRequiredHandler(AddUserToTeam))
	m.Del("/teams/:team/:user", authorizationRequiredHandler(RemoveUserFromTeam))

	m.Get("/healers", authorizationRequiredHandler(healers))
	m.Get("/healers/:healer", authorizationRequiredHandler(healer))

	if !*dry {
		provisioner, err := config.GetString("provisioner")
		if err != nil {
			fmt.Printf("Warning: %q didn't declare a provisioner, using default provisioner.\n", *configFile)
			provisioner = "juju"
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls-cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls-key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			listener, err := net.Listen("tcp", listen)
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			http.Handle("/", m)
			fatal(http.Serve(listener, nil))
		}
	}
}
<|endoftext|>


<commit_before>// REST API to access indexing.

// TODO: Implement STATS command.
// TODO: Change the server implementation URL to follow REST philosphy.

package api

type RequestType int

const (
    CREATE RequestType = iota // POST /indexes/create
    DROP                      // DELETE /indexes/uuid
    LIST                      // GET /indexes/list
    SCAN                      // GET /indexes/uuid/scan
    STATS                     // GET /indexes/stats
    // GET /indexes/uuid/stats
    NODES  // GET /indexes/nodes
    NOTIFY // GET /indexes/notify
)

// URL encoded query params
type QueryParams struct {
    Low       Key
    High      Key
    Inclusion Inclusion
    Offset    int
    Limit     int
}

// All API accept IndexRequest structure and returns IndexResponse structure.
// If application is written in Go, and compiled with `indexing` package then
// they can choose the access the underlying interfaces directly.
type IndexRequest struct {
    Type       RequestType
    Index      IndexInfo
    ServerUuid string
    Params     QueryParams
}

//RESPONSE DATA FORMATS
type ResponseStatus int

const (
    SUCCESS ResponseStatus = iota
    ERROR
    INVALID_CACHE
)

type IndexRow struct {
    Key   string
    Value string
}

type IndexError struct {
    Code string
    Msg  string
}

type IndexMetaResponse struct {
    Status     ResponseStatus
    Indexes    []IndexInfo
    ServerUuid string
    Nodes      []NodeInfo
    Errors     []IndexError
}

type IndexScanResponse struct {
    Status    ResponseStatus
    TotalRows int64
    Rows      []IndexRow
    Errors    []IndexError
}

//Indexer Node Info
type NodeInfo struct {
    IndexerURL string
}
<commit_msg>Protocol structs changes<commit_after>// REST API to access indexing.

// TODO: Implement STATS command.
// TODO: Change the server implementation URL to follow REST philosphy.

package api

type RequestType string

const (
    CREATE RequestType = "create"
    DROP   RequestType = "drop"
    LIST   RequestType = "list"
    NOTIFY RequestType = "notify"
    NODES  RequestType = "nodes"
    SCAN   RequestType = "scan"
    STATS  RequestType = "stats"
)

// All API accept IndexRequest structure and returns IndexResponse structure.
// If application is written in Go, and compiled with `indexing` package then
// they can choose the access the underlying interfaces directly.
type IndexRequest struct {
    Type       RequestType `json:"type,omitempty"`
    Index      IndexInfo   `json:"index,omitempty"`
    ServerUuid string      `json:"serverUuid,omitempty"`
    Params     QueryParams `json:"params,omitempty"`
}

// URL encoded query params
type QueryParams struct {
    ScanType  ScanType  `json:"scanType,omitempty"`
    Low       [][]byte  `json:"low,omitempty"`
    High      [][]byte  `json:"high,omitempty"`
    Inclusion Inclusion `json:"inclusion,omitempty"`
    Limit     int64     `json:"limit,omitempty"`
}

type ScanType string

const (
    COUNT      ScanType = "count"
    EXISTS     ScanType = "exists"
    LOOKUP     ScanType = "lookup"
    RANGESCAN  ScanType = "rangeScan"
    FULLSCAN   ScanType = "fullScan"
    RANGECOUNT ScanType = "rangeCount"
)

//RESPONSE DATA FORMATS
type ResponseStatus string

const (
    SUCCESS       ResponseStatus = "success"
    ERROR         ResponseStatus = "error"
    INVALID_CACHE ResponseStatus = "invalid_cache"
)

type IndexRow struct {
    Key   [][]byte `json:"key,omitempty"`
    Value string   `json:"value,omitempty"`
}

type IndexError struct {
    Code string `json:"code,omitempty"`
    Msg  string `json:"msg,omitempty"`
}

type IndexMetaResponse struct {
    Status     ResponseStatus `json:"status,omitempty"`
    Indexes    []IndexInfo    `json:"indexes,omitempty"`
    ServerUuid string         `json:"serverUuid,omitempty"`
    Nodes      []NodeInfo     `json:"nodes,omitempty"`
    Errors     []IndexError   `json:"errors,omitempty"`
}

type IndexScanResponse struct {
    Status    ResponseStatus `json:"status,omitempty"`
    TotalRows uint64         `json:"totalrows,omitempty"`
    Rows      []IndexRow     `json:"rows,omitempty"`
    Errors    []IndexError   `json:"errors,omitempty"`
}

//Indexer Node Info
type NodeInfo struct {
    IndexerURL string `json:"indexerURL,omitempty"`
}
<|endoftext|>


<commit_before>package api

import (
	"net/http"
	"net/http/httputil"

	"github.com/gin-gonic/gin"
	"github.com/mundipagg/boleto-api/config"
	"github.com/mundipagg/boleto-api/log"

	"github.com/mundipagg/boleto-api/models"
)

//InstallRestAPI "instala" e sobe o servico de rest
func InstallRestAPI() {
	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(executionController())
	if config.Get().DevMode && !config.Get().MockMode {
		router.Use(gin.Logger())
	}
	InstallV1(router)
	router.StaticFile("/favicon.ico", "./boleto/favicon.ico")
	router.GET("/boleto", getBoleto)
	router.GET("/boleto/confirmation", confirmation)
	router.POST("/boleto/confirmation", confirmation)
	router.Run(config.Get().APIPort)
}

func confirmation(c *gin.Context) {
	if dump, err := httputil.DumpRequest(c.Request, true); err == nil {
		l := log.CreateLog()
		l.BankName = "BradescoShopFacil"
		l.Operation = "BoletoConfirmation"
		l.Request(string(dump), c.Request.URL.String(), nil)
	}
	c.String(200, "OK")
}

func checkError(c *gin.Context, err error, l *log.Log) bool {

	if err != nil {
		errResp := models.BoletoResponse{
			Errors: models.NewErrors(),
		}

		switch v := err.(type) {
		case models.IErrorResponse:
			errResp.Errors.Append(v.ErrorCode(), v.Error())
			c.JSON(http.StatusBadRequest, errResp)

		case models.IHttpNotFound:
			errResp.Errors.Append("MP404", v.Error())
			l.Warn(errResp, v.Error())
			c.JSON(http.StatusNotFound, errResp)

		case models.IFormatError:
			errResp.Errors.Append("MP400", v.Error())
			l.Warn(errResp, v.Error())
			c.JSON(http.StatusBadRequest, errResp)

		case models.IServerError:
			errResp.Errors.Append("MP500", "Internal Error")
			l.Fatal(v.Error(), v.Message())
			c.JSON(http.StatusInternalServerError, errResp)

		default:
			l.Fatal(err.Error(), "")
			errResp.Errors.Append("MP500", "Internal Error")
			c.JSON(http.StatusInternalServerError, errResp)
		}
		return true
	}
	return false
}
<commit_msg>:art: Cria StaticFile para icons.min.css<commit_after>package api

import (
	"net/http"
	"net/http/httputil"

	"github.com/gin-gonic/gin"
	"github.com/mundipagg/boleto-api/config"
	"github.com/mundipagg/boleto-api/log"

	"github.com/mundipagg/boleto-api/models"
)

//InstallRestAPI "instala" e sobe o servico de rest
func InstallRestAPI() {
	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(executionController())
	if config.Get().DevMode && !config.Get().MockMode {
		router.Use(gin.Logger())
	}
	InstallV1(router)
	router.StaticFile("/favicon.ico", "./boleto/favicon.ico")
	router.StaticFile("/icons.min.css", "./boleto/icons.min.css")
	router.GET("/boleto", getBoleto)
	router.GET("/boleto/confirmation", confirmation)
	router.POST("/boleto/confirmation", confirmation)
	router.Run(config.Get().APIPort)
}

func confirmation(c *gin.Context) {
	if dump, err := httputil.DumpRequest(c.Request, true); err == nil {
		l := log.CreateLog()
		l.BankName = "BradescoShopFacil"
		l.Operation = "BoletoConfirmation"
		l.Request(string(dump), c.Request.URL.String(), nil)
	}
	c.String(200, "OK")
}

func checkError(c *gin.Context, err error, l *log.Log) bool {

	if err != nil {
		errResp := models.BoletoResponse{
			Errors: models.NewErrors(),
		}

		switch v := err.(type) {
		case models.IErrorResponse:
			errResp.Errors.Append(v.ErrorCode(), v.Error())
			c.JSON(http.StatusBadRequest, errResp)

		case models.IHttpNotFound:
			errResp.Errors.Append("MP404", v.Error())
			l.Warn(errResp, v.Error())
			c.JSON(http.StatusNotFound, errResp)

		case models.IFormatError:
			errResp.Errors.Append("MP400", v.Error())
			l.Warn(errResp, v.Error())
			c.JSON(http.StatusBadRequest, errResp)

		case models.IServerError:
			errResp.Errors.Append("MP500", "Internal Error")
			l.Fatal(v.Error(), v.Message())
			c.JSON(http.StatusInternalServerError, errResp)

		default:
			l.Fatal(err.Error(), "")
			errResp.Errors.Append("MP500", "Internal Error")
			c.JSON(http.StatusInternalServerError, errResp)
		}
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package graphite

//Copyright 2015 MediaMath <http://www.mediamath.com>.  All rights reserved.
//Use of this source code is governed by a BSD-style
//license that can be found in the LICENSE file.

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

//Event to record in graphite
type Event struct {
	What string `json:"what"`
	Tags string `json:"tags"`
	Data string `json:"data"`
	When int64  `json:"when,omitempty"`
}

//At will set the When field with the appropriately formatted time
func (e *Event) At(t time.Time) *Event {
	e.When = t.UTC().Unix()
	return e
}

//NewEvent creates an event with the provided data
func NewEvent(what string, data string, tags ...string) *Event {
	return &Event{
		What: what,
		Tags: strings.Join(tags, ","),
		Data: data,
	}
}

//NewTaggedEvent creates an event with 1 tag and the what is the same as the tag
func NewTaggedEvent(tag string, data string) *Event {
	return &Event{
		What: tag,
		Tags: tag,
		Data: data,
	}
}

//New creates a new graphite client
func New(username, password, addr string) *Graphite {
	return &Graphite{username, password, addr, &http.Client{Timeout: time.Duration(10) * time.Second}}
}

//Graphite is a wrapper around the graphite events API
type Graphite struct {
	username string
	password string
	addr     string
	Client   *http.Client
}

//Publish sends the event to the graphite API
func (g *Graphite) Publish(event *Event) error {
	b, err := json.Marshal(event)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", g.addr, bytes.NewBuffer(b))

	if err != nil {
		return err
	}

	if g.username != "" && g.password != "" {
		req.SetBasicAuth(g.username, g.password)
	}

	resp, err := g.Client.Do(req)

	if err != nil {
		return err
	}

	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		return fmt.Errorf("%v:%v:%s:%s", g.addr, resp.StatusCode, body, b)
	}

	return nil
}
<commit_msg>add less verbose option<commit_after>package graphite

//Copyright 2015 MediaMath <http://www.mediamath.com>.  All rights reserved.
//Use of this source code is governed by a BSD-style
//license that can be found in the LICENSE file.

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

//Event to record in graphite
type Event struct {
	What string `json:"what"`
	Tags string `json:"tags"`
	Data string `json:"data"`
	When int64  `json:"when,omitempty"`
}

//At will set the When field with the appropriately formatted time
func (e *Event) At(t time.Time) *Event {
	e.When = t.UTC().Unix()
	return e
}

//NewEvent creates an event with the provided data
func NewEvent(what string, data string, tags ...string) *Event {
	return &Event{
		What: what,
		Tags: strings.Join(tags, ","),
		Data: data,
	}
}

//NewTaggedEvent creates an event with 1 tag and the what is the same as the tag
func NewTaggedEvent(tag string, data string) *Event {
	return &Event{
		What: tag,
		Tags: tag,
		Data: data,
	}
}

//New creates a new graphite client
func New(username, password, addr string) *Graphite {
	return NewVerbose(username, password, addr, true)
}

//NewVerbose creates a new client with verbosity set
func NewVerbose(username, password, addr string, verbose bool) *Graphite {
	return &Graphite{username, password, addr, &http.Client{Timeout: time.Duration(10) * time.Second}, verbose}
}

//Graphite is a wrapper around the graphite events API
type Graphite struct {
	username string
	password string
	addr     string
	Client   *http.Client
	verbose  bool
}

//Publish sends the event to the graphite API
func (g *Graphite) Publish(event *Event) error {
	b, err := json.Marshal(event)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", g.addr, bytes.NewBuffer(b))

	if err != nil {
		return err
	}

	if g.username != "" && g.password != "" {
		req.SetBasicAuth(g.username, g.password)
	}

	resp, err := g.Client.Do(req)

	if err != nil {
		return err
	}

	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		if g.verbose {
			return fmt.Errorf("%v:%v:%s:%s", g.addr, resp.StatusCode, body, b)
		}

		return fmt.Errorf("%v:%v:%s", g.addr, resp.StatusCode, b)
	}

	return nil
}
<|endoftext|>


<commit_before>package model

import (
	"errors"
)

var (
	ErrTooManyRequests       = errors.New("too many requests")
	ErrNotEnoughImages       = errors.New("not enough images")
	ErrTooManyImages         = errors.New("too many images")
	ErrImageTooLarge         = errors.New("image too big")
	ErrNotImage              = errors.New("not image")
	ErrAlbumNotFound         = errors.New("album not found")
	ErrPairNotFound          = errors.New("pair not found")
	ErrTokenNotFound         = errors.New("token not found")
	ErrImageNotFound         = errors.New("image not found")
	ErrAlbumAlreadyExists    = errors.New("album already exists")
	ErrTokenAlreadyExists    = errors.New("token already exists")
	ErrThirdPartyUnavailable = errors.New("third party unavailable")
	ErrUnknown               = errors.New("unknown")
)
<commit_msg>Change error message<commit_after>package model

import (
	"errors"
)

var (
	ErrTooManyRequests       = errors.New("too many requests")
	ErrNotEnoughImages       = errors.New("not enough images")
	ErrTooManyImages         = errors.New("too many images")
	ErrImageTooLarge         = errors.New("image too large")
	ErrNotImage              = errors.New("not image")
	ErrAlbumNotFound         = errors.New("album not found")
	ErrPairNotFound          = errors.New("pair not found")
	ErrTokenNotFound         = errors.New("token not found")
	ErrImageNotFound         = errors.New("image not found")
	ErrAlbumAlreadyExists    = errors.New("album already exists")
	ErrTokenAlreadyExists    = errors.New("token already exists")
	ErrThirdPartyUnavailable = errors.New("third party unavailable")
	ErrUnknown               = errors.New("unknown")
)
<|endoftext|>


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

package siv_test

import (
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestEncrypt(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type EncryptTest struct{}

func init() { RegisterTestSuite(&EncryptTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *EncryptTest) NilKey() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) ShortKey() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) LongKey() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) TooMuchAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) JustLittleEnoughAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) OutputIsDeterministic() {
	ExpectEq("TODO", "")

func (t *EncryptTest) Rfc5297TestCaseA1() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) Rfc5297TestCaseA2() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) GeneratedTestCases() {
	ExpectEq("TODO", "")
}
<commit_msg>EncryptTest.NilKey<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package siv_test

import (
	"github.com/jacobsa/aes/siv"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestEncrypt(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type EncryptTest struct{}

func init() { RegisterTestSuite(&EncryptTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *EncryptTest) NilKey() {
	key := []byte(nil)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) ShortKey() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) LongKey() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) TooMuchAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) JustLittleEnoughAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) OutputIsDeterministic() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) Rfc5297TestCaseA1() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) Rfc5297TestCaseA2() {
	ExpectEq("TODO", "")
}

func (t *EncryptTest) GeneratedTestCases() {
	ExpectEq("TODO", "")
}
<|endoftext|>