<commit_before>package tle

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
)

// First line of the two-line element set format
type Line1 struct {
	LineNumber               string `json:"lineNumber"`
	SatelliteNumber          string `json:"satelliteNumber"`
	Classication             string `json:"classification"`
	InternationalDesignator1 string `json:"internationalDesignator1"`
	InternationalDesignator2 string `json:"internationalDesignator2"`
	InternationalDesignator3 string `json:"internationalDesignator3"`
	EpochYear                string `json:"epochYear"`
	Epoch                    string `json:"epoch"`
	FirstTimeDerivative      string `json:"firstTimeDerivative"`
	SecondTimeDerivative     string `json:"secondTimeDerivative"`
	Bstar                    string `json:"bstar"`
	Zero                     string `json:"zero"`
	ElementSetNumber         string `json:"elementSetNumber"`
	Checksum                 string `json:"checksum"`
}

// The second line of the two-line element set format
type Line2 struct {
	LineNumber              string `json:"lineNumber"`
	SatelliteNumber         string `json:"satelliteNumber"`
	Inclination             string `json:"inclination"`
	RightAscension          string `json:"rightAscension"`
	Eccentricity            string `json:"eccentricity"`
	ArgumentOfPerigee       string `json:"argumentOfPerigee"`
	MeanAnomaly             string `json:"meanAnomaly"`
	MeanMotion              string `json:"meanMotion"`
	RevolutionNumberAtEpoch string `json:"revolutionNumberAtEpoch"`
	Checksum                string `json:"checksum"`
}

// Two-line element set
type Tle struct {
	Title string `json:"title"`
	Line1 Line1  `json:"line1"`
	Line2 Line2  `json:"line2"`
}

// Reads a stream of JSON and translate it to a two-line element set
func (t *Tle) FromJson(r io.Reader) error {
	return json.NewDecoder(r).Decode(&t)
}

// Translates the two-line element set to a JSON byte array
func (t *Tle) ToJson() ([]byte, error) {
	return json.Marshal(t)
}

// Parse a 3-line string array to build the two-line element set
func (t *Tle) Parse(input []string) error {
	if len(input) != 3 {
		return errors.New("Expecting three lines")
	}
	if len(input[0]) > 24 {
		return errors.New("Title line cannot exceed 24 columns")
	}
	if len(input[1]) != 69 {
		return errors.New("Line 1 cannot exceed 69 columns")
	}
	if len(input[2]) != 69 {
		return errors.New("Line 2 cannot exceed 69 columns")
	}

	// The first line is the title (24 columns)
	t.Title = input[0]

	// The second line is `line 1` (69 columns)
	t.Line1.LineNumber = input[1][0:1]
	t.Line1.SatelliteNumber = input[1][2:7]
	t.Line1.Classication = input[1][7:8]
	t.Line1.InternationalDesignator1 = input[1][9:11]
	t.Line1.InternationalDesignator2 = input[1][11:14]
	t.Line1.InternationalDesignator3 = input[1][14:17]
	t.Line1.EpochYear = input[1][18:20]
	t.Line1.Epoch = input[1][20:32]
	t.Line1.FirstTimeDerivative = input[1][33:43]
	t.Line1.SecondTimeDerivative = input[1][44:52]
	t.Line1.Bstar = input[1][53:61]
	t.Line1.Zero = input[1][62:63]
	t.Line1.ElementSetNumber = input[1][64:68]
	t.Line1.Checksum = input[1][68:69]

	// The third line is `line 2` (69 columns)
	t.Line2.LineNumber = input[2][0:1]
	t.Line2.SatelliteNumber = input[2][2:7]
	t.Line2.Inclination = input[2][8:16]
	t.Line2.RightAscension = input[2][17:25]
	t.Line2.Eccentricity = input[2][26:33]
	t.Line2.ArgumentOfPerigee = input[2][34:42]
	t.Line2.MeanAnomaly = input[2][43:51]
	t.Line2.MeanMotion = input[2][52:63]
	t.Line2.RevolutionNumberAtEpoch = input[2][63:68]
	t.Line2.Checksum = input[2][68:69]

	return nil
}

// Scan from a reader taking and output payloads to standard output
func (t *Tle) Scan(reader io.Reader) error {
	// Create a new scanner reading from the standard input
	scanner := bufio.NewScanner(reader)

	// Initialize the payload and counter
	payload := make([]string, 3)
	i := 0

	// Scan each line as it comes in
	for scanner.Scan() {
		text := scanner.Text()
		if text == "" {
			continue
		}

		payload[i] = text
		i = i + 1

		if i > 2 {
			// Create a new two-line element set
			tle := Tle{}
			tle.Parse(payload)

			// Send the formatted object to standard output
			fmt.Println(tle)

			// Re-initiate our variables to receive the next payload
			payload = make([]string, 3)
			i = 0
		}
	}

	// Check for any errors and report them.
	if err := scanner.Err(); err != nil {
		return err
	}

	return nil
}
<commit_msg>scan() populates given struct<commit_after>package tle

import (
	"bufio"
	"encoding/json"
	"errors"
	"io"
)

// First line of the two-line element set format
type Line1 struct {
	LineNumber               string `json:"lineNumber"`
	SatelliteNumber          string `json:"satelliteNumber"`
	Classication             string `json:"classification"`
	InternationalDesignator1 string `json:"internationalDesignator1"`
	InternationalDesignator2 string `json:"internationalDesignator2"`
	InternationalDesignator3 string `json:"internationalDesignator3"`
	EpochYear                string `json:"epochYear"`
	Epoch                    string `json:"epoch"`
	FirstTimeDerivative      string `json:"firstTimeDerivative"`
	SecondTimeDerivative     string `json:"secondTimeDerivative"`
	Bstar                    string `json:"bstar"`
	Zero                     string `json:"zero"`
	ElementSetNumber         string `json:"elementSetNumber"`
	Checksum                 string `json:"checksum"`
}

// The second line of the two-line element set format
type Line2 struct {
	LineNumber              string `json:"lineNumber"`
	SatelliteNumber         string `json:"satelliteNumber"`
	Inclination             string `json:"inclination"`
	RightAscension          string `json:"rightAscension"`
	Eccentricity            string `json:"eccentricity"`
	ArgumentOfPerigee       string `json:"argumentOfPerigee"`
	MeanAnomaly             string `json:"meanAnomaly"`
	MeanMotion              string `json:"meanMotion"`
	RevolutionNumberAtEpoch string `json:"revolutionNumberAtEpoch"`
	Checksum                string `json:"checksum"`
}

// Two-line element set
type Tle struct {
	Title string `json:"title"`
	Line1 Line1  `json:"line1"`
	Line2 Line2  `json:"line2"`
}

// Reads a stream of JSON and translate it to a two-line element set
func (t *Tle) FromJson(r io.Reader) error {
	return json.NewDecoder(r).Decode(&t)
}

// Translates the two-line element set to a JSON byte array
func (t *Tle) ToJson() ([]byte, error) {
	return json.Marshal(t)
}

// Parse a 3-line string array to build the two-line element set
func (t *Tle) Parse(input []string) error {
	if len(input) != 3 {
		return errors.New("Expecting three lines")
	}
	if len(input[0]) > 24 {
		return errors.New("Title line cannot exceed 24 columns")
	}
	if len(input[1]) != 69 {
		return errors.New("Line 1 cannot exceed 69 columns")
	}
	if len(input[2]) != 69 {
		return errors.New("Line 2 cannot exceed 69 columns")
	}

	// The first line is the title (24 columns)
	t.Title = input[0]

	// The second line is `line 1` (69 columns)
	t.Line1.LineNumber = input[1][0:1]
	t.Line1.SatelliteNumber = input[1][2:7]
	t.Line1.Classication = input[1][7:8]
	t.Line1.InternationalDesignator1 = input[1][9:11]
	t.Line1.InternationalDesignator2 = input[1][11:14]
	t.Line1.InternationalDesignator3 = input[1][14:17]
	t.Line1.EpochYear = input[1][18:20]
	t.Line1.Epoch = input[1][20:32]
	t.Line1.FirstTimeDerivative = input[1][33:43]
	t.Line1.SecondTimeDerivative = input[1][44:52]
	t.Line1.Bstar = input[1][53:61]
	t.Line1.Zero = input[1][62:63]
	t.Line1.ElementSetNumber = input[1][64:68]
	t.Line1.Checksum = input[1][68:69]

	// The third line is `line 2` (69 columns)
	t.Line2.LineNumber = input[2][0:1]
	t.Line2.SatelliteNumber = input[2][2:7]
	t.Line2.Inclination = input[2][8:16]
	t.Line2.RightAscension = input[2][17:25]
	t.Line2.Eccentricity = input[2][26:33]
	t.Line2.ArgumentOfPerigee = input[2][34:42]
	t.Line2.MeanAnomaly = input[2][43:51]
	t.Line2.MeanMotion = input[2][52:63]
	t.Line2.RevolutionNumberAtEpoch = input[2][63:68]
	t.Line2.Checksum = input[2][68:69]

	return nil
}

// Scan from a reader taking and output payloads to standard output
func (t *Tle) Scan(reader io.Reader) error {
	// Create a new scanner reading from the standard input
	scanner := bufio.NewScanner(reader)

	// Initialize the payload and counter
	payload := make([]string, 3)
	i := 0

	// Scan each line as it comes in
	for scanner.Scan() {
		text := scanner.Text()
		if text == "" {
			continue
		}

		payload[i] = text
		i = i + 1

		if i > 2 {
			// Create a new two-line element set
			t.Parse(payload)

			// Re-initiate our variables to receive the next payload
			payload = make([]string, 3)
			i = 0
		}
	}

	// Check for any errors and report them.
	if err := scanner.Err(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The oauth2 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 oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error. The existing token may be nil.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Scopes optionally specifies a list of requested permission scopes.
	Scopes []string `json:"scopes,omitempty"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	if opts.ClientID == "" {
		return nil, errors.New("oauth2: missing client ID")
	}
	return &Config{
		opts:     opts,
		authURL:  aURL,
		tokenURL: tURL,
	}, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	// Client is the HTTP client to be used to retrieve
	// tokens from the OAuth 2.0 provider.
	Client *http.Client

	// Transport is the http.RoundTripper to be used
	// to construct new oauth2.Transport instances from
	// this configuration.
	Transport http.RoundTripper

	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
//
// State is a token to protect the user from CSRF attacks. You must
// always provide a non-zero string and validate that it matches the
// the state query parameter on your redirect callback.
// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
//
// Access type is an OAuth extension that gets sent as the
// "access_type" field in the URL from AuthCodeURL.
// It may be "online" (default) or "offline".
// If your application needs to refresh access tokens when the
// user is not present at the browser, then use offline. This
// will result in your application obtaining a refresh token
// the first time your application exchanges an authorization
// code for a user.
//
// Approval prompt indicates whether the user should be
// re-prompted for consent. If set to "auto" (default) the
// user will be prompted only if they haven't previously
// granted consent and the code can only be exchanged for an
// access token. If set to "force" the user will always be prompted,
// and the code can be exchanged for a refresh token.
func (c *Config) AuthCodeURL(state, accessType, prompt string) (authURL string) {
	u := *c.authURL
	v := url.Values{
		"response_type":   {"code"},
		"client_id":       {c.opts.ClientID},
		"redirect_uri":    condVal(c.opts.RedirectURL),
		"scope":           condVal(strings.Join(c.opts.Scopes, " ")),
		"state":           condVal(state),
		"access_type":     condVal(accessType),
		"approval_prompt": condVal(prompt),
	}
	q := v.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
func (c *Config) NewTransport() *Transport {
	return NewTransport(c.transport(), c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 authorization code with
// the provider to fetch a new access token (and refresh token). Once
// it successfully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(code string) (*Transport, error) {
	token, err := c.Exchange(code)
	if err != nil {
		return nil, err
	}
	return NewTransport(c.transport(), c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("oauth2: cannot fetch access token without refresh token")
	}
	return c.retrieveToken(url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {existing.RefreshToken},
	})
}

// Exchange exchanges the authorization code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(code string) (*Token, error) {
	return c.retrieveToken(url.Values{
		"grant_type":   {"authorization_code"},
		"code":         {code},
		"redirect_uri": condVal(c.opts.RedirectURL),
		"scope":        condVal(strings.Join(c.opts.Scopes, " ")),
	})
}

func (c *Config) retrieveToken(v url.Values) (*Token, error) {
	v.Set("client_id", c.opts.ClientID)
	bustedAuth := !providerAuthHeaderWorks(c.tokenURL.String())
	if bustedAuth && c.opts.ClientSecret != "" {
		v.Set("client_secret", c.opts.ClientSecret)
	}
	req, err := http.NewRequest("POST", c.tokenURL.String(), strings.NewReader(v.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	if !bustedAuth && c.opts.ClientSecret != "" {
		req.SetBasicAuth(c.opts.ClientID, c.opts.ClientSecret)
	}
	r, err := c.client().Do(req)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
	}
	if c := r.StatusCode; c < 200 || c > 299 {
		return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body)
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return nil, err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.Unmarshal(body, &resp); err != nil {
			return nil, err
		}
	}
	token := &Token{
		AccessToken:  resp.AccessToken,
		TokenType:    resp.TokenType,
		RefreshToken: resp.RefreshToken,
	}
	// Don't overwrite `RefreshToken` with an empty value
	// if this was a token refreshing request.
	if resp.RefreshToken == "" {
		token.RefreshToken = v.Get("refresh_token")
	}
	if resp.ExpiresIn == 0 {
		token.Expiry = time.Time{}
	} else {
		token.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if token.Extra == nil {
			token.Extra = make(map[string]string)
		}
		token.Extra["id_token"] = resp.IdToken
	}
	return token, nil
}

func (c *Config) transport() http.RoundTripper {
	if c.Transport != nil {
		return c.Transport
	}
	return http.DefaultTransport
}

func (c *Config) client() *http.Client {
	if c.Client != nil {
		return c.Client
	}
	return http.DefaultClient
}

func condVal(v string) []string {
	if v == "" {
		return nil
	}
	return []string{v}
}

// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL
// implements the OAuth2 spec correctly
// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
// In summary:
// - Reddit only accepts client secret in the Authorization header
// - Dropbox accepts either it in URL param or Auth header, but not both.
// - Google only accepts URL param (not spec compliant?), not Auth header
func providerAuthHeaderWorks(tokenURL string) bool {
	if strings.HasPrefix(tokenURL, "https://accounts.google.com/") ||
		strings.HasPrefix(tokenURL, "https://github.com/") ||
		strings.HasPrefix(tokenURL, "https://api.instagram.com/") ||
		strings.HasPrefix(tokenURL, "https://www.douban.com/") ||
		strings.HasPrefix(tokenURL, "https://api.dropbox.com/") ||
		strings.HasPrefix(tokenURL, "https://www.linkedin.com/") {
		// Some sites fail to implement the OAuth2 spec fully.
		return false
	}

	// Assume the provider implements the spec properly
	// otherwise. We can add more exceptions as they're
	// discovered. We will _not_ be adding configurable hooks
	// to this package to let users select server bugs.
	return true
}
<commit_msg>Add SoundCloud to the providers not supporting Auth headers<commit_after>// Copyright 2014 The oauth2 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 oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error. The existing token may be nil.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Scopes optionally specifies a list of requested permission scopes.
	Scopes []string `json:"scopes,omitempty"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	if opts.ClientID == "" {
		return nil, errors.New("oauth2: missing client ID")
	}
	return &Config{
		opts:     opts,
		authURL:  aURL,
		tokenURL: tURL,
	}, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	// Client is the HTTP client to be used to retrieve
	// tokens from the OAuth 2.0 provider.
	Client *http.Client

	// Transport is the http.RoundTripper to be used
	// to construct new oauth2.Transport instances from
	// this configuration.
	Transport http.RoundTripper

	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
//
// State is a token to protect the user from CSRF attacks. You must
// always provide a non-zero string and validate that it matches the
// the state query parameter on your redirect callback.
// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
//
// Access type is an OAuth extension that gets sent as the
// "access_type" field in the URL from AuthCodeURL.
// It may be "online" (default) or "offline".
// If your application needs to refresh access tokens when the
// user is not present at the browser, then use offline. This
// will result in your application obtaining a refresh token
// the first time your application exchanges an authorization
// code for a user.
//
// Approval prompt indicates whether the user should be
// re-prompted for consent. If set to "auto" (default) the
// user will be prompted only if they haven't previously
// granted consent and the code can only be exchanged for an
// access token. If set to "force" the user will always be prompted,
// and the code can be exchanged for a refresh token.
func (c *Config) AuthCodeURL(state, accessType, prompt string) (authURL string) {
	u := *c.authURL
	v := url.Values{
		"response_type":   {"code"},
		"client_id":       {c.opts.ClientID},
		"redirect_uri":    condVal(c.opts.RedirectURL),
		"scope":           condVal(strings.Join(c.opts.Scopes, " ")),
		"state":           condVal(state),
		"access_type":     condVal(accessType),
		"approval_prompt": condVal(prompt),
	}
	q := v.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
func (c *Config) NewTransport() *Transport {
	return NewTransport(c.transport(), c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 authorization code with
// the provider to fetch a new access token (and refresh token). Once
// it successfully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(code string) (*Transport, error) {
	token, err := c.Exchange(code)
	if err != nil {
		return nil, err
	}
	return NewTransport(c.transport(), c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("oauth2: cannot fetch access token without refresh token")
	}
	return c.retrieveToken(url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {existing.RefreshToken},
	})
}

// Exchange exchanges the authorization code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(code string) (*Token, error) {
	return c.retrieveToken(url.Values{
		"grant_type":   {"authorization_code"},
		"code":         {code},
		"redirect_uri": condVal(c.opts.RedirectURL),
		"scope":        condVal(strings.Join(c.opts.Scopes, " ")),
	})
}

func (c *Config) retrieveToken(v url.Values) (*Token, error) {
	v.Set("client_id", c.opts.ClientID)
	bustedAuth := !providerAuthHeaderWorks(c.tokenURL.String())
	if bustedAuth && c.opts.ClientSecret != "" {
		v.Set("client_secret", c.opts.ClientSecret)
	}
	req, err := http.NewRequest("POST", c.tokenURL.String(), strings.NewReader(v.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	if !bustedAuth && c.opts.ClientSecret != "" {
		req.SetBasicAuth(c.opts.ClientID, c.opts.ClientSecret)
	}
	r, err := c.client().Do(req)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
	}
	if c := r.StatusCode; c < 200 || c > 299 {
		return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body)
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return nil, err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.Unmarshal(body, &resp); err != nil {
			return nil, err
		}
	}
	token := &Token{
		AccessToken:  resp.AccessToken,
		TokenType:    resp.TokenType,
		RefreshToken: resp.RefreshToken,
	}
	// Don't overwrite `RefreshToken` with an empty value
	// if this was a token refreshing request.
	if resp.RefreshToken == "" {
		token.RefreshToken = v.Get("refresh_token")
	}
	if resp.ExpiresIn == 0 {
		token.Expiry = time.Time{}
	} else {
		token.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if token.Extra == nil {
			token.Extra = make(map[string]string)
		}
		token.Extra["id_token"] = resp.IdToken
	}
	return token, nil
}

func (c *Config) transport() http.RoundTripper {
	if c.Transport != nil {
		return c.Transport
	}
	return http.DefaultTransport
}

func (c *Config) client() *http.Client {
	if c.Client != nil {
		return c.Client
	}
	return http.DefaultClient
}

func condVal(v string) []string {
	if v == "" {
		return nil
	}
	return []string{v}
}

// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL
// implements the OAuth2 spec correctly
// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
// In summary:
// - Reddit only accepts client secret in the Authorization header
// - Dropbox accepts either it in URL param or Auth header, but not both.
// - Google only accepts URL param (not spec compliant?), not Auth header
func providerAuthHeaderWorks(tokenURL string) bool {
	if strings.HasPrefix(tokenURL, "https://accounts.google.com/") ||
		strings.HasPrefix(tokenURL, "https://github.com/") ||
		strings.HasPrefix(tokenURL, "https://api.instagram.com/") ||
		strings.HasPrefix(tokenURL, "https://www.douban.com/") ||
		strings.HasPrefix(tokenURL, "https://api.dropbox.com/") ||
		strings.HasPrefix(tokenURL, "https://api.soundcloud.com/") ||
		strings.HasPrefix(tokenURL, "https://www.linkedin.com/") {
		// Some sites fail to implement the OAuth2 spec fully.
		return false
	}

	// Assume the provider implements the spec properly
	// otherwise. We can add more exceptions as they're
	// discovered. We will _not_ be adding configurable hooks
	// to this package to let users select server bugs.
	return true
}
<|endoftext|>


<commit_before>// Copyright 2014 The go-gl 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 (
	"fmt"
	"github.com/go-gl/gl"
	"github.com/go-gl/glfw"
	"os"
)

func main() {
	if err := glfw.Init(); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
		return
	}
	defer glfw.Terminate()

	glfw.OpenWindowHint(glfw.FsaaSamples, 4)
	glfw.OpenWindowHint(glfw.OpenGLVersionMajor, 3)
	glfw.OpenWindowHint(glfw.OpenGLVersionMinor, 3)
	glfw.OpenWindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)

	if err := glfw.OpenWindow(1024, 768, 0, 0, 0, 0, 32, 0, glfw.Windowed); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
		return
	}

	gl.Init()
	gl.GetError() // Ignore error

	glfw.SetWindowTitle("Tutorial 01")
	glfw.Enable(glfw.StickyKeys)

	gl.ClearColor(0., 0., 0.4, 0.)
	// Equivalent to a do... while
	for ok := true; ok; ok = (glfw.Key(glfw.KeyEsc) != glfw.KeyPress && glfw.WindowParam(glfw.Opened) == gl.TRUE) {
		glfw.SwapBuffers()
	}

}
<commit_msg>Fixed first tutorial<commit_after>// Copyright 2014 The go-gl 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 (
	"fmt"
	"github.com/go-gl/gl"
	glfw "github.com/go-gl/glfw3"
	"os"

	"runtime"
)

func main() {
	runtime.LockOSThread()

	if !glfw.Init() {
		fmt.Fprintf(os.Stderr, "Can't open GLFW")
		return
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Samples, 4)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile)
	glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True) // needed for macs

	window, err := glfw.CreateWindow(1024, 768, "Tutorial 1", nil, nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		return
	}

	gl.Init()
	gl.GetError() // Ignore error
	window.SetInputMode(glfw.StickyKeys, 1)

	gl.ClearColor(0., 0., 0.4, 0.)
	// Equivalent to a do... while
	for ok := true; ok; ok = (window.GetKey(glfw.KeyEscape) != glfw.Press && !window.ShouldClose()) {
		window.SwapBuffers()
		glfw.PollEvents()
	}

}
<|endoftext|>


<commit_before>package canvas

type Object interface {
	Stroke(Point)
	Fill(Point)

	SetLineStyle(*LineStyle)
}

type pathObj struct {
	c    *Canvas
	path func(*PathBuilder)
	ls   *LineStyle
}

func (p pathObj) Fill(pt Point) {
	pb := &PathBuilder{p.c}

	pb.begin(pt)
	p.path(pb)

	defer p.ls.set(p.c).set(p.c)
	p.c.ctx.Call("fill")
}

func (p pathObj) Stroke(pt Point) {
	pb := &PathBuilder{p.c}

	pb.begin(pt)
	p.path(pb)

	defer p.ls.set(p.c).set(p.c)
	p.c.ctx.Call("stroke")
}

func (p pathObj) SetLineStyle(ls *LineStyle) {
	p.ls = ls
}

type PathBuilder struct {
	c *Canvas
}

func (pb *PathBuilder) begin(p Point) {
	pb.c.ctx.Call("beginPath")
	pb.c.ctx.Call("moveTo", p.X, p.Y)
}

func (pb PathBuilder) Rect(r Rectangle) {
	r = r.Canon()
	pb.c.ctx.Call("rect", r.Min.X, r.Min.Y, r.Dx(), r.Dy())
}

func (pb PathBuilder) MoveTo(p Point) {
	pb.c.ctx.Call("moveTo", p.X, p.Y)
}

func (pb PathBuilder) Line(p Point) {
	pb.c.ctx.Call("lineTo", p.X, p.Y)
}

func (pb PathBuilder) Bezier(cp1, cp2, end Point) {
	pb.c.ctx.Call("bezierCurveTo",
		cp1.X,
		cp1.Y,
		cp2.X,
		cp2.Y,
		end.X,
		end.Y,
	)
}

func (pb PathBuilder) Quadratic(cp, end Point) {
	pb.c.ctx.Call("quadraticCurveTo",
		cp.X,
		cp.Y,
		end.X,
		end.Y,
	)
}

func (pb PathBuilder) Arc(c Point, r float64, sa, ea float64, cc bool) {
	pb.c.ctx.Call("arc",
		c.X,
		c.Y,
		r,
		sa,
		ea,
		cc,
	)
}

type textObj struct {
	c    *Canvas
	text string
	mw   float64
}

func (t textObj) Fill(p Point) {
	if t.mw < 0 {
		t.c.ctx.Call("fillText", t.text, p.X, p.Y)
		return
	}

	t.c.ctx.Call("fillText", t.text, p.X, p.Y, t.mw)
}

func (t textObj) Stroke(p Point) {
	if t.mw < 0 {
		t.c.ctx.Call("strokeText", t.text, p.X, p.Y)
		return
	}

	t.c.ctx.Call("strokeText", t.text, p.X, p.Y, t.mw)
}

func (t textObj) SetLineStyle(*LineStyle) {
}
<commit_msg>Refactor common style code into an embedded struct.<commit_after>package canvas

type Object interface {
	Stroke(Point)
	Fill(Point)

	SetLineStyle(*LineStyle)
}

type commonStyle struct {
	ls *LineStyle
}

func (s *commonStyle) SetLineStyle(ls *LineStyle) {
	s.ls = ls
}

type pathObj struct {
	c    *Canvas
	path func(*PathBuilder)

	commonStyle
}

func (p pathObj) Fill(pt Point) {
	pb := &PathBuilder{p.c}

	pb.begin(pt)
	p.path(pb)

	defer p.ls.set(p.c).set(p.c)
	p.c.ctx.Call("fill")
}

func (p pathObj) Stroke(pt Point) {
	pb := &PathBuilder{p.c}

	pb.begin(pt)
	p.path(pb)

	defer p.ls.set(p.c).set(p.c)
	p.c.ctx.Call("stroke")
}

type PathBuilder struct {
	c *Canvas
}

func (pb *PathBuilder) begin(p Point) {
	pb.c.ctx.Call("beginPath")
	pb.c.ctx.Call("moveTo", p.X, p.Y)
}

func (pb PathBuilder) Rect(r Rectangle) {
	r = r.Canon()
	pb.c.ctx.Call("rect", r.Min.X, r.Min.Y, r.Dx(), r.Dy())
}

func (pb PathBuilder) MoveTo(p Point) {
	pb.c.ctx.Call("moveTo", p.X, p.Y)
}

func (pb PathBuilder) Line(p Point) {
	pb.c.ctx.Call("lineTo", p.X, p.Y)
}

func (pb PathBuilder) Bezier(cp1, cp2, end Point) {
	pb.c.ctx.Call("bezierCurveTo",
		cp1.X,
		cp1.Y,
		cp2.X,
		cp2.Y,
		end.X,
		end.Y,
	)
}

func (pb PathBuilder) Quadratic(cp, end Point) {
	pb.c.ctx.Call("quadraticCurveTo",
		cp.X,
		cp.Y,
		end.X,
		end.Y,
	)
}

func (pb PathBuilder) Arc(c Point, r float64, sa, ea float64, cc bool) {
	pb.c.ctx.Call("arc",
		c.X,
		c.Y,
		r,
		sa,
		ea,
		cc,
	)
}

type textObj struct {
	c    *Canvas
	text string
	mw   float64

	commonStyle
}

func (t textObj) Fill(p Point) {
	if t.mw < 0 {
		t.c.ctx.Call("fillText", t.text, p.X, p.Y)
		return
	}

	t.c.ctx.Call("fillText", t.text, p.X, p.Y, t.mw)
}

func (t textObj) Stroke(p Point) {
	if t.mw < 0 {
		t.c.ctx.Call("strokeText", t.text, p.X, p.Y)
		return
	}

	t.c.ctx.Call("strokeText", t.text, p.X, p.Y, t.mw)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/sideshow/apns2"
	"github.com/sideshow/apns2/certificate"
	"github.com/sideshow/apns2/payload"
	"log"
	"os"
)

func main() {

	pemFile := os.Getenv("JUSTAWAY_APNS_PEM_PATH") // apns.pem

	cert, pemErr := certificate.FromPemFile(pemFile, "")
	if pemErr != nil {
		log.Println("Cert Error:", pemErr)
	}

	notification := &apns2.Notification{}
	notification.DeviceToken = os.Args[len(os.Args)-1]
	notification.Topic = "pw.aska.Justaway"
	notification.Payload = payload.NewPayload().Alert("hello")

	client := apns2.NewClient(cert).Development()
	res, err := client.Push(notification)

	if err != nil {
		log.Println("Error:", err)
		return
	}

	log.Println("APNs ID:", res.ApnsID)
}

// http://sreecharans.blogspot.jp/2011/08/how-to-build-apple-push-notification.html
// - Launch Keychain Assistant from your local Mac and from the login keychain, filter by the Certificates category. You will see an expandable option called “Apple Development Push Services”
// - Expand this option then right click on “Apple Development Push Services” > Export “Apple Development Push Services ID123″. Save this as apns-dev-cert.p12 file somewhere you can access it.
// - Do the same again for the “Private Key” that was revealed when you expanded “Apple Development Push Services” ensuring you save it as apns-dev-key.p12 file.
// openssl pkcs12 -clcerts -nokeys -out apns-cert.pem -in apns-cert.p12
// openssl pkcs12 -nocerts -out apns-key.pem -in apns-key.p12
// openssl rsa -in apns-key.pem -out apns-key-noenc.pem
// cat apns-cert.pem apns-key-noenc.pem > apns.pem
<commit_msg>Update memo<commit_after>package main

import (
	"github.com/sideshow/apns2"
	"github.com/sideshow/apns2/certificate"
	"github.com/sideshow/apns2/payload"
	"log"
	"os"
)

func main() {

	pemFile := os.Getenv("JUSTAWAY_APNS_PEM_PATH") // apns.pem

	cert, pemErr := certificate.FromPemFile(pemFile, "")
	if pemErr != nil {
		log.Println("Cert Error:", pemErr)
	}

	notification := &apns2.Notification{}
	notification.DeviceToken = os.Args[len(os.Args)-1]
	notification.Topic = "pw.aska.Justaway"
	notification.Payload = payload.NewPayload().Alert("hello")

	client := apns2.NewClient(cert).Development()
	res, err := client.Push(notification)

	if err != nil {
		log.Println("Error:", err)
		return
	}

	log.Println("APNs ID:", res.ApnsID)
}

// http://sreecharans.blogspot.jp/2011/08/how-to-build-apple-push-notification.html
// - Launch Keychain Assistant from your local Mac and from the login keychain, filter by the Certificates category.
//   You will see an expandable option called “Apple Push Services”
// - Expand this option then right click on “Apple Push Services” > Export “Apple Push Services ID123″. Save this as apns-cert.p12 file somewhere you can access it.
// - Do the same again for the “Private Key” that was revealed when you expanded “Apple Push Services” ensuring you save it as apns-key.p12 file.
// openssl pkcs12 -clcerts -nokeys -out apns-cert.pem -in apns-cert.p12
// openssl pkcs12 -nocerts -out apns-key.pem -in apns-key.p12
// openssl rsa -in apns-key.pem -out apns-key-noenc.pem
// cat apns-cert.pem apns-key-noenc.pem > apns.pem
<|endoftext|>


<commit_before>package daslog

import (
	"bytes"
	"fmt"
	"testing"
)

// almost dummy test
// TODO : add tests
func TestMain(t *testing.T) {
	var buf bytes.Buffer

	o := Options{
		Destination: &buf,
		Prefix:      "{{.O}} [{{.Q}}]: ",
		LogLevel:    UrgencyLevelCritical,
	}

	l, err := New(o)
	if err != nil {
		fmt.Print(err)
		return
	}

	// notice in Log style
	l.Log(UrgencyLevelNotice, "test notice message")

	// info
	l.Info("test info message")

	// error
	l.Errorf("%s %s %s", "test", "error", "message")
}
<commit_msg>test fix<commit_after>package daslog

import (
	"bytes"
	"testing"
)

// almost dummy test
// TODO : add tests
func TestMain(t *testing.T) {
	var buf bytes.Buffer

	o := Options{
		Destination: &buf,
		Prefix:      "{{.O}} [{{.Q}}]: ",
		LogLevel:    UrgencyLevelCritical,
	}

	l, err := New(o)
	if err != nil {
		t.Fatalf("%v", err)
	}

	// notice in Log style
	l.Log(UrgencyLevelNotice, "test notice message")

	// info
	l.Info("test info message")

	// error
	l.Errorf("%s %s %s", "test", "error", "message")
}
<|endoftext|>


<commit_before>package meep

func RecoverPanics(fn func()) (e error) {
	defer func() {
		e = coerce(recover())
	}()
	fn()
	return
}

func Try(fn func(), plan TryPlan) {
	plan.MustHandle(RecoverPanics(fn))
}

func coerce(rcvrd interface{}) error {
	switch err := rcvrd.(type) {
	case nil:
		// Panics of nils are possible btw but super absurd.  Never do it.
		return nil
	case error:
		return err
	default:
		// Panics of non-error types are bad and you should feel bad.
		return New(&ErrUntypedPanic{Cause: rcvrd})
	}
}

/*
	A wrapper for non-error types raised from a panic.

	The `Try` system will coerce all non-error types to this automatically.
*/
type ErrUntypedPanic struct {
	TraitAutodescribing
	TraitTraceable
	Cause interface{}
}
<commit_msg>Retain deferred stack during try -- better info from any panics that don't capture their own stacks.<commit_after>package meep

/*
	Invokes your function, captures any panics, and returns them.

	This is simply shorthand for writing your own defers/recovers.

	Note that RecoverPanics returns `error` rather than `interface{}`.
	Any values panicked which do not match the `error` interface will
	be wrapped in the `ErrUntypedPanic` type,
	with the original value in the `Cause` field.
*/
func RecoverPanics(fn func()) (e error) {
	defer func() {
		e = coerce(recover())
	}()
	fn()
	return
}

/*
	Invokes your function, captures any panics, and routes them
	through the TryPlan.

	This may be superior to calling a function that returns an error
	and calling `TryPlan.MustHandle` yourself, because any panics
	that *do* occur will retain a stack including their original panic
	location until the TryPlan evaluates, meaning you can capture it
	properly with any error with the `meep.TraitTraceable` property.
*/
func Try(fn func(), plan TryPlan) {
	// Note that this is subtly different than calling
	//  `plan.MustHandle(RecoverPanics(fn))` ...!
	// This calling MustHandle inside the defer is critical to retaining
	// the stack info in the case of e.g. a nil ptr exception, or anything
	// which doesn't do its own explicit stack capture.
	defer func() {
		plan.MustHandle(coerce(recover()))
	}()
	fn()
}

func coerce(rcvrd interface{}) error {
	switch err := rcvrd.(type) {
	case nil:
		// Panics of nils are possible btw but super absurd.  Never do it.
		return nil
	case error:
		return err
	default:
		// Panics of non-error types are bad and you should feel bad.
		return New(&ErrUntypedPanic{Cause: rcvrd})
	}
}

/*
	A wrapper for non-error types raised from a panic.

	The `Try` system will coerce all non-error types to this automatically.
*/
type ErrUntypedPanic struct {
	TraitAutodescribing
	TraitTraceable
	Cause interface{}
}
<|endoftext|>


<commit_before><commit_msg>better not found handling<commit_after><|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/kylelemons/go-gypsy/yaml"
	"log"
	"os"
	"os/exec"
	"sort"
	"strings"
	"time"
)

// Default configuration file
var conffile = flag.String("c", ".tsmrc", "config file")

// Config variables. Provide a default for tarsnap(1) path.
var cfgTarsnapBin string = "/usr/local/bin/tarsnap"
var cfgTarsnapArgs []string
var cfgBackupDirs []string
var cfgExcludeFile string

// Templates for time.Parse()
const iso8601 = "2006-01-02"
const nightly = "nightly-2006-01-02"
const adhoc = "adhoc-2006-01-02_1504"

const day = time.Hour * 24

var info = log.New(os.Stdout, "", log.LstdFlags)

// Shamefully "borrowed" from src/cmd/go/main.go
// Flattens a mix of strings and slices of strings into a single slice.
func commandArgs(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("commandArgs: invalid argument")
		}
	}
	return x
}

// Creates a new Tarsnap archive
func runBackup(archiveName string) {
	info.Printf("Starting backup %s\n", archiveName)
	args := commandArgs("-c", "-f", archiveName, cfgTarsnapArgs, cfgBackupDirs)
	backup := exec.Command(cfgTarsnapBin, args...)
	backup.Stdout = os.Stdout
	backup.Stderr = os.Stderr
	backuperr := backup.Run()
	if backuperr != nil {
		log.Fatal("Error running backup: ", backuperr)
	}
	info.Println("Backup finished")
}

// Deletes a Tarsnap archive
func deleteBackup(backup string) {
	deletecmd := exec.Command(cfgTarsnapBin, "-d", "-f", backup)
	deletecmd.Stdout = os.Stdout
	deletecmd.Stderr = os.Stderr
	err := deletecmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}

// Runs expiry against backup archives
func expireBackups(w, m time.Time, reallyExpire bool) {
	listcmd := exec.Command(cfgTarsnapBin, "--list-archives")
	var stdout bytes.Buffer
	listcmd.Stdout = &stdout
	listcmd.Stderr = os.Stderr
	listerr := listcmd.Run()
	if listerr != nil {
		log.Fatal("Error running command: ", listerr)
	}
	backups := strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n")
	sort.Strings(backups)

	for i := 0; i < len(backups); i++ {
		// Don't expire adhoc backups
		if strings.HasPrefix(backups[i], "adhoc-") {
			continue
		}
		backup, _ := time.Parse(nightly, backups[i])
		eom := time.Date(backup.Year(), backup.Month()+1, 0, 0, 0, 0, 0, backup.Location())
		if (backup.Before(w) && backup.Day() != eom.Day()) || backup.Before(m) {
			if reallyExpire {
				info.Println("Expiring backup", backups[i])
				deleteBackup(backups[i])
			} else {
				fmt.Println("Expired backup", backups[i])
			}
		} else {
			if reallyExpire {
				fmt.Println("Keeping backup", backups[i])
			} else {
				fmt.Println("Current backup", backups[i])
			}
		}
	}
}

func main() {
	flag.Parse()

	config, conferr := yaml.ReadFile(*conffile)
	if conferr != nil {
		log.Fatalf("Error reading config %q: %s", *conffile, conferr)
	}

	tmpTarsnapBin, _ := config.Get("TarsnapBin")
	if tmpTarsnapBin != "" {
		cfgTarsnapBin = tmpTarsnapBin
	}

	count, err := config.Count("TarsnapArgs")
	for i := 0; i < count; i++ {
		s := fmt.Sprintf("TarsnapArgs[%d]", i)
		t, err := config.Get(s)
		if err != nil {
			log.Fatal(err)
		}
		// Remove any quotes from the arg - used to protect
		// options (starting with a -)
		t = strings.Replace(t, `"`, ``, -1)
		cfgTarsnapArgs = append(cfgTarsnapArgs, t)
	}

	count, err = config.Count("BackupDirs")
	if err != nil {
		fmt.Println("No backup directories specified")
		os.Exit(1)
	}
	for i := 0; i < count; i++ {
		s := fmt.Sprintf("BackupDirs[%d]", i)
		t, err := config.Get(s)
		if err != nil {
			log.Fatal(err)
		}
		cfgBackupDirs = append(cfgBackupDirs, t)
	}

	cfgExcludeFile, err := config.Get("ExcludeFile")
	if err == nil {
		cfgTarsnapArgs = append(cfgTarsnapArgs, "-X", cfgExcludeFile)
	}

	// GetInt() returns an int64. Convert this to an int.
	tmpKeepWeeks, err := config.GetInt("KeepWeeks")
	if err != nil {
		fmt.Println("Missing config value KeepWeeks")
		os.Exit(1)
	}
	tmpKeepMonths, err := config.GetInt("KeepMonths")
	if err != nil {
		fmt.Println("Missing config value KeepMonths")
		os.Exit(1)
	}
	cfgKeepWeeks := int(tmpKeepWeeks)
	cfgKeepMonths := int(tmpKeepMonths)

	t := time.Now()
	w := t.AddDate(0, 0, -(7 * cfgKeepWeeks))
	m := t.AddDate(0, -cfgKeepMonths, 0)
	fmt.Printf("Date: %s\nExpire week: %s\nExpire month: %s\n\n", t.Format(iso8601), w.Format(iso8601), m.Format(iso8601))

	if len(os.Args) < 2 {
		fmt.Println("Missing action")
		os.Exit(1)
	}
	action := os.Args[1]
	switch action {
	case "nightly":
		// Run nightly
		runBackup(t.Format(nightly))

		// TODO: Make w and m global?
		cfgExpireBackups, _ := config.GetBool("ExpireBackups")
		if cfgExpireBackups {
			expireBackups(w, m, true)
		} else {
			info.Println("Backup expiration disabled")
		}

		info.Println("All done!")
	case "adhoc":
		// Run adhoc
		runBackup(t.Format(adhoc))
	case "list-expired":
		expireBackups(w, m, false)
	default:
		log.Fatalf("Unknown action '%s'", action)
	}
}
<commit_msg>Fix arg processing.<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/kylelemons/go-gypsy/yaml"
	"log"
	"os"
	"os/exec"
	"sort"
	"strings"
	"time"
)

// Default configuration file
var conffile = flag.String("c", ".tsmrc", "config file")

// Config variables. Provide a default for tarsnap(1) path.
var cfgTarsnapBin string = "/usr/local/bin/tarsnap"
var cfgTarsnapArgs []string
var cfgBackupDirs []string
var cfgExcludeFile string

// Templates for time.Parse()
const iso8601 = "2006-01-02"
const nightly = "nightly-2006-01-02"
const adhoc = "adhoc-2006-01-02_1504"

const day = time.Hour * 24

var info = log.New(os.Stdout, "", log.LstdFlags)

// Shamefully "borrowed" from src/cmd/go/main.go
// Flattens a mix of strings and slices of strings into a single slice.
func commandArgs(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("commandArgs: invalid argument")
		}
	}
	return x
}

// Creates a new Tarsnap archive
func runBackup(archiveName string) {
	info.Printf("Starting backup %s\n", archiveName)
	args := commandArgs("-c", "-f", archiveName, cfgTarsnapArgs, cfgBackupDirs)
	backup := exec.Command(cfgTarsnapBin, args...)
	backup.Stdout = os.Stdout
	backup.Stderr = os.Stderr
	backuperr := backup.Run()
	if backuperr != nil {
		log.Fatal("Error running backup: ", backuperr)
	}
	info.Println("Backup finished")
}

// Deletes a Tarsnap archive
func deleteBackup(backup string) {
	deletecmd := exec.Command(cfgTarsnapBin, "-d", "-f", backup)
	deletecmd.Stdout = os.Stdout
	deletecmd.Stderr = os.Stderr
	err := deletecmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}

// Runs expiry against backup archives
func expireBackups(w, m time.Time, reallyExpire bool) {
	listcmd := exec.Command(cfgTarsnapBin, "--list-archives")
	var stdout bytes.Buffer
	listcmd.Stdout = &stdout
	listcmd.Stderr = os.Stderr
	listerr := listcmd.Run()
	if listerr != nil {
		log.Fatal("Error running command: ", listerr)
	}
	backups := strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n")
	sort.Strings(backups)

	for i := 0; i < len(backups); i++ {
		// Don't expire adhoc backups
		if strings.HasPrefix(backups[i], "adhoc-") {
			continue
		}
		backup, _ := time.Parse(nightly, backups[i])
		eom := time.Date(backup.Year(), backup.Month()+1, 0, 0, 0, 0, 0, backup.Location())
		if (backup.Before(w) && backup.Day() != eom.Day()) || backup.Before(m) {
			if reallyExpire {
				info.Println("Expiring backup", backups[i])
				deleteBackup(backups[i])
			} else {
				fmt.Println("Expired backup", backups[i])
			}
		} else {
			if reallyExpire {
				fmt.Println("Keeping backup", backups[i])
			} else {
				fmt.Println("Current backup", backups[i])
			}
		}
	}
}

func main() {
	flag.Parse()

	config, conferr := yaml.ReadFile(*conffile)
	if conferr != nil {
		log.Fatalf("Error reading config %q: %s", *conffile, conferr)
	}

	tmpTarsnapBin, _ := config.Get("TarsnapBin")
	if tmpTarsnapBin != "" {
		cfgTarsnapBin = tmpTarsnapBin
	}

	count, err := config.Count("TarsnapArgs")
	for i := 0; i < count; i++ {
		s := fmt.Sprintf("TarsnapArgs[%d]", i)
		t, err := config.Get(s)
		if err != nil {
			log.Fatal(err)
		}
		// Remove any quotes from the arg - used to protect
		// options (starting with a -)
		t = strings.Replace(t, `"`, ``, -1)
		cfgTarsnapArgs = append(cfgTarsnapArgs, t)
	}

	count, err = config.Count("BackupDirs")
	if err != nil {
		fmt.Println("No backup directories specified")
		os.Exit(1)
	}
	for i := 0; i < count; i++ {
		s := fmt.Sprintf("BackupDirs[%d]", i)
		t, err := config.Get(s)
		if err != nil {
			log.Fatal(err)
		}
		cfgBackupDirs = append(cfgBackupDirs, t)
	}

	cfgExcludeFile, err := config.Get("ExcludeFile")
	if err == nil {
		cfgTarsnapArgs = append(cfgTarsnapArgs, "-X", cfgExcludeFile)
	}

	// GetInt() returns an int64. Convert this to an int.
	tmpKeepWeeks, err := config.GetInt("KeepWeeks")
	if err != nil {
		fmt.Println("Missing config value KeepWeeks")
		os.Exit(1)
	}
	tmpKeepMonths, err := config.GetInt("KeepMonths")
	if err != nil {
		fmt.Println("Missing config value KeepMonths")
		os.Exit(1)
	}
	cfgKeepWeeks := int(tmpKeepWeeks)
	cfgKeepMonths := int(tmpKeepMonths)

	t := time.Now()
	w := t.AddDate(0, 0, -(7 * cfgKeepWeeks))
	m := t.AddDate(0, -cfgKeepMonths, 0)
	fmt.Printf("Date: %s\nExpire week: %s\nExpire month: %s\n\n", t.Format(iso8601), w.Format(iso8601), m.Format(iso8601))

	if len(os.Args) < 2 {
		fmt.Println("Missing action")
		os.Exit(1)
	}
	action := flag.Args()[0]
	switch action {
	case "nightly":
		// Run nightly
		runBackup(t.Format(nightly))

		// TODO: Make w and m global?
		cfgExpireBackups, _ := config.GetBool("ExpireBackups")
		if cfgExpireBackups {
			expireBackups(w, m, true)
		} else {
			info.Println("Backup expiration disabled")
		}

		info.Println("All done!")
	case "adhoc":
		// Run adhoc
		runBackup(t.Format(adhoc))
	case "list-expired":
		expireBackups(w, m, false)
	default:
		log.Fatalf("Unknown action '%s'", action)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package resolvers

import "context"

// SanityChecks performs some basic checks to see if the resolvers are reliable.
func (rp *ResolverPool) SanityChecks() {
	for _, r := range rp.Resolvers {
		go func(res Resolver) {
			if !goodNamesResolved(r) {
				rp.Log.Printf("SanityChecks: Resolver %s failed to resolve good names", res.Address())
			}
		}(r)

		go func(res Resolver) {
			if !badNamesNotResolved(r) {
				rp.Log.Printf("SanityChecks: Resolver %s returned false positives for bad names", res.Address())
			}
		}(r)
	}
}

func goodNamesResolved(r Resolver) bool {
	results := make(chan bool, 10)
	goodNames := []string{
		"www.owasp.org",
		"twitter.com",
		"github.com",
		"www.google.com",
	}

	ctx, cancel := context.WithCancel(context.Background())
	// Check that valid names can be resolved
	for _, name := range goodNames {
		go resolveForSanityCheck(ctx, r, name, false, results)
	}

	success := true
	var cancelled bool
	l := len(goodNames)
	for i := 0; i < l; i++ {
		select {
		case result := <-results:
			if !result {
				success = false
				cancelled = true
				cancel()
			}
		}
	}

	if !cancelled {
		cancel()
	}
	return success
}

func badNamesNotResolved(r Resolver) bool {
	results := make(chan bool, 10)
	badNames := []string{
		"not-a-real-name.owasp.org",
		"wwww.owasp.org",
		"www-1.owasp.org",
		"www1.owasp.org",
		"wwww.google.com",
		"www-1.google.com",
		"www1.google.com",
		"not-a-real-name.google.com",
	}

	ctx, cancel := context.WithCancel(context.Background())
	// Check that invalid names do not return false positives
	for _, name := range badNames {
		go resolveForSanityCheck(ctx, r, name, true, results)
	}

	success := true
	var cancelled bool
	l := len(badNames)
	for i := 0; i < l; i++ {
		select {
		case result := <-results:
			if !result {
				success = false
				cancelled = true
				cancel()
			}
		}
	}

	if !cancelled {
		cancel()
	}
	return success
}

func resolveForSanityCheck(ctx context.Context, r Resolver, name string, badname bool, ch chan bool) {
	var err error
	again := true
	var success bool

	for i := 0; i < 2 && again; i++ {
		_, again, err = r.Resolve(ctx, name, "A", PriorityCritical)
		if err == nil && !again {
			success = true
			break
		}
	}

	if badname {
		success = !success
	}

	ch <- success
}
<commit_msg>fixed a race condition<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package resolvers

import "context"

// SanityChecks performs some basic checks to see if the resolvers are reliable.
func (rp *ResolverPool) SanityChecks() {
	for _, r := range rp.Resolvers {
		go func(res Resolver) {
			if !goodNamesResolved(res) {
				rp.Log.Printf("SanityChecks: Resolver %s failed to resolve good names", res.Address())
			}
		}(r)

		go func(res Resolver) {
			if !badNamesNotResolved(res) {
				rp.Log.Printf("SanityChecks: Resolver %s returned false positives for bad names", res.Address())
			}
		}(r)
	}
}

func goodNamesResolved(r Resolver) bool {
	results := make(chan bool, 10)
	goodNames := []string{
		"www.owasp.org",
		"twitter.com",
		"github.com",
		"www.google.com",
	}

	ctx, cancel := context.WithCancel(context.Background())
	// Check that valid names can be resolved
	for _, name := range goodNames {
		go resolveForSanityCheck(ctx, r, name, false, results)
	}

	success := true
	var cancelled bool
	l := len(goodNames)
	for i := 0; i < l; i++ {
		select {
		case result := <-results:
			if !result {
				success = false
				cancelled = true
				cancel()
			}
		}
	}

	if !cancelled {
		cancel()
	}
	return success
}

func badNamesNotResolved(r Resolver) bool {
	results := make(chan bool, 10)
	badNames := []string{
		"not-a-real-name.owasp.org",
		"wwww.owasp.org",
		"www-1.owasp.org",
		"www1.owasp.org",
		"wwww.google.com",
		"www-1.google.com",
		"www1.google.com",
		"not-a-real-name.google.com",
	}

	ctx, cancel := context.WithCancel(context.Background())
	// Check that invalid names do not return false positives
	for _, name := range badNames {
		go resolveForSanityCheck(ctx, r, name, true, results)
	}

	success := true
	var cancelled bool
	l := len(badNames)
	for i := 0; i < l; i++ {
		select {
		case result := <-results:
			if !result {
				success = false
				cancelled = true
				cancel()
			}
		}
	}

	if !cancelled {
		cancel()
	}
	return success
}

func resolveForSanityCheck(ctx context.Context, r Resolver, name string, badname bool, ch chan bool) {
	var err error
	again := true
	var success bool

	for i := 0; i < 2 && again; i++ {
		_, again, err = r.Resolve(ctx, name, "A", PriorityCritical)
		if err == nil && !again {
			success = true
			break
		}
	}

	if badname {
		success = !success
	}

	ch <- success
}
<|endoftext|>


<commit_before>package models

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

type Stock struct {
	Change           float64 `json:"Change"`
	ChangePercent    float64 `json:"ChangePercent"`
	ChangePercentYTD float64 `json:"ChangePercentYTD"`
	ChangeYTD        float64 `json:"ChangeYTD"`
	High             float64 `json:"High"`
	LastPrice        float64 `json:"LastPrice"`
	Price            int
	Low              float64 `json:"Low"`
	MSDate           float64 `json:"MSDate"`
	MarketCap        int     `json:"MarketCap"`
	Name             string  `json:"Name"`
	Open             float64 `json:"Open"`
	Status           string  `json:"Status"`
	Symbol           string  `json:"Symbol"`
	Timestamp        string  `json:"Timestamp"`
	Volume           int     `json:"Volume"`
}

func CheckStock(symbol string) *Stock {
	client := new(http.Client)
	res, err := client.Get("http://dev.markitondemand.com/Api/v2/Quote/json?symbol=" + symbol)
	if err != nil {
		log.Panic(err)
	}

	var stock = new(Stock)                        // Make a new instance of the Stock struct
	err = json.NewDecoder(res.Body).Decode(stock) // Populate it with our JSON data
	if err != nil {                               // Die if there was an error
		log.Panic(err)
	}

	stock.Price = int(stock.LastPrice * 100) // Convert to turnips

	return stock
}
<commit_msg>Moving to the Yahoo Finance API<commit_after>package models

import (
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

type Stock struct {
	Name  string
	Ask   float64
	Bid   float64
	Price int
}

func CheckStock(symbol string) *Stock {
	client := new(http.Client)
	res, err := client.Get("http://finance.yahoo.com/d/quotes.csv?s=" + symbol + "&f=nab")
	if err != nil {
		log.Panic(err)
	}

	var stock = new(Stock) // Make a new instance of the Stock struct

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Panic(err)
	}

	response := strings.Split(string(body), ",")

	ask, _ := strconv.ParseFloat(response[1], 64)
	bid, _ := strconv.ParseFloat(response[2], 64)

	stock.Name = response[0]
	stock.Ask = ask * 100
	stock.Bid = bid * 100
	stock.Price = int((stock.Ask + stock.Bid) / 2) // Ghetto and temporary

	return stock
}
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"regexp"
	"time"

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

// Title título de cobrança de entrada
type Title struct {
	CreateDate     time.Time `json:"createDate,omitempty"`
	ExpireDateTime time.Time `json:"expireDateTime,omitempty"`
	ExpireDate     string    `json:"expireDate,omitempty"`
	AmountInCents  uint64    `json:"amountInCents,omitempty"`
	OurNumber      uint      `json:"ourNumber,omitempty"`
	Instructions   string    `json:"instructions,omitempty"`
	DocumentNumber string    `json:"documentNumber,omitempty"`
	NSU            string    `json:"nsu,omitempty"`
}

//ValidateInstructionsLength valida se texto das instruções possui quantidade de caracteres corretos
func (t Title) ValidateInstructionsLength(max int) error {
	if len(t.Instructions) > max {
		return NewErrorResponse("MPInstructions", fmt.Sprintf("Instruções não podem passar de %d caracteres", max))
	}
	return nil
}

//ValidateDocumentNumber número do documento
func (t *Title) ValidateDocumentNumber() error {
	re := regexp.MustCompile("(\\D+)")
	ad := re.ReplaceAllString(t.DocumentNumber, "")
	if ad == "" {
		t.DocumentNumber = ad
	} else if len(ad) < 10 {
		t.DocumentNumber = util.PadLeft(ad, "0", 10)
	} else {
		t.DocumentNumber = ad[:10]
	}
	return nil
}

//IsExpireDateValid retorna um erro se a data de expiração for inválida
func (t *Title) IsExpireDateValid() error {
	d, err := parseDate(t.ExpireDate)
	if err != nil {
		return NewErrorResponse("MPExpireDate", fmt.Sprintf("Data em um formato inválido, esperamos AAAA-MM-DD e recebemos %s", t.ExpireDate))
	}
	n, _ := parseDate(util.BrNow().Format("2006-01-02"))
	t.CreateDate = n
	t.ExpireDateTime = d
	if t.CreateDate.After(t.ExpireDateTime) {
		return NewErrorResponse("MPExpireDate", "Data de expiração não pode ser menor que a data de hoje")
	}
	return nil
}

//IsAmountInCentsValid retorna um erro se o valor em centavos for inválido
func (t *Title) IsAmountInCentsValid() error {
	if t.AmountInCents < 1 {
		return NewErrorResponse("MPAmountInCents", "Valor não pode ser menor do que 1 centavo")
	}
	return nil
}

func parseDate(t string) (time.Time, error) {
	date, err := time.Parse("2006-01-02", t)
	if err != nil {
		return time.Now(), err
	}
	return date, nil
}
<commit_msg>:art:Add BoletoType to Api contract<commit_after>package models

import (
	"fmt"
	"regexp"
	"time"

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

// Title título de cobrança de entrada
type Title struct {
	CreateDate     time.Time `json:"createDate,omitempty"`
	ExpireDateTime time.Time `json:"expireDateTime,omitempty"`
	ExpireDate     string    `json:"expireDate,omitempty"`
	AmountInCents  uint64    `json:"amountInCents,omitempty"`
	OurNumber      uint      `json:"ourNumber,omitempty"`
	Instructions   string    `json:"instructions,omitempty"`
	DocumentNumber string    `json:"documentNumber,omitempty"`
	NSU            string    `json:"nsu,omitempty"`
	BoletoType     string    `json:"boletoType,omitempty"`
}

//ValidateInstructionsLength valida se texto das instruções possui quantidade de caracteres corretos
func (t Title) ValidateInstructionsLength(max int) error {
	if len(t.Instructions) > max {
		return NewErrorResponse("MPInstructions", fmt.Sprintf("Instruções não podem passar de %d caracteres", max))
	}
	return nil
}

//ValidateDocumentNumber número do documento
func (t *Title) ValidateDocumentNumber() error {
	re := regexp.MustCompile("(\\D+)")
	ad := re.ReplaceAllString(t.DocumentNumber, "")
	if ad == "" {
		t.DocumentNumber = ad
	} else if len(ad) < 10 {
		t.DocumentNumber = util.PadLeft(ad, "0", 10)
	} else {
		t.DocumentNumber = ad[:10]
	}
	return nil
}

//IsExpireDateValid retorna um erro se a data de expiração for inválida
func (t *Title) IsExpireDateValid() error {
	d, err := parseDate(t.ExpireDate)
	if err != nil {
		return NewErrorResponse("MPExpireDate", fmt.Sprintf("Data em um formato inválido, esperamos AAAA-MM-DD e recebemos %s", t.ExpireDate))
	}
	n, _ := parseDate(util.BrNow().Format("2006-01-02"))
	t.CreateDate = n
	t.ExpireDateTime = d
	if t.CreateDate.After(t.ExpireDateTime) {
		return NewErrorResponse("MPExpireDate", "Data de expiração não pode ser menor que a data de hoje")
	}
	return nil
}

//IsAmountInCentsValid retorna um erro se o valor em centavos for inválido
func (t *Title) IsAmountInCentsValid() error {
	if t.AmountInCents < 1 {
		return NewErrorResponse("MPAmountInCents", "Valor não pode ser menor do que 1 centavo")
	}
	return nil
}

func parseDate(t string) (time.Time, error) {
	date, err := time.Parse("2006-01-02", t)
	if err != nil {
		return time.Now(), err
	}
	return date, nil
}
<|endoftext|>


<commit_before>package models

import (
  "fmt"
  "github.com/gokyle/uuid"
  "github.com/spacedock-io/registry/db"
  "strings"
)

type Token struct {
  Id        int64
  Signature string
  Access    string
  UserId    int64
  RepoId    int64
  Repo      string
}

func CreateToken(access string, uid int64, repo string) (Token, bool) {
  token := Token{}
  // @TODO: Validate access string
  token.Access = access
  sig, err := uuid.GenerateV4String()
  if err != nil {
    return Token{}, false
  }
  token.Signature = sig
  token.UserId = uid
  token.Repo = repo
  return token, true
}

func GetToken(user *User, repo, access string) (Token, error) {
  t := Token{
    UserId: user.Id,
    Access: access,
    Repo: repo,
  }

  q := db.DB.Where(&t).Find(&t)
  if q.RecordNotFound() {
    return Token{}, TokenNotFound
  } else if q.Error != nil {
    return Token{}, DBErr
  }

  return t, nil
}

func GetTokenString(token string) (Token, error) {
  t := Token{}

  split := strings.Split(token, ",")
  for _, v := range split {
    v := strings.Split(v, "=")
    switch v[0] {
      case "signature": t.Signature = v[1]
      case "repository": t.Repo = v[1]
      case "access": t.Access = v[1]
    }
  }

  q := db.DB.Where(&t).Find(&t)
  if q.RecordNotFound() {
    return Token{}, TokenNotFound
  } else if q.Error != nil {
    return Token{}, q.Error
  }
  return t, nil
}

func (token *Token) String() string {
  return fmt.Sprintf("signature=%s,repository=%s,access=%s", token.Signature,
    token.Repo, token.Access)
}
<commit_msg>Change to UseTokenString, delete token after use<commit_after>package models

import (
  "fmt"
  "github.com/gokyle/uuid"
  "github.com/spacedock-io/registry/db"
  "strings"
)

type Token struct {
  Id        int64
  Signature string
  Access    string
  UserId    int64
  RepoId    int64
  Repo      string
}

func CreateToken(access string, uid int64, repo string) (Token, bool) {
  token := Token{}
  // @TODO: Validate access string
  token.Access = access
  sig, err := uuid.GenerateV4String()
  if err != nil {
    return Token{}, false
  }
  token.Signature = sig
  token.UserId = uid
  token.Repo = repo
  return token, true
}

func GetToken(user *User, repo, access string) (Token, error) {
  t := Token{
    UserId: user.Id,
    Access: access,
    Repo: repo,
  }

  q := db.DB.Where(&t).Find(&t)
  if q.RecordNotFound() {
    return Token{}, TokenNotFound
  } else if q.Error != nil {
    return Token{}, DBErr
  }

  return t, nil
}

func UseTokenString(token string) (Token, error) {
  t := Token{}

  split := strings.Split(token, ",")
  for _, v := range split {
    v := strings.Split(v, "=")
    switch v[0] {
      case "signature": t.Signature = v[1]
      case "repository": t.Repo = v[1]
      case "access": t.Access = v[1]
    }
  }

  q := db.DB.Where(&t).Find(&t)
  if q.RecordNotFound() {
    return Token{}, TokenNotFound
  } else if q.Error != nil {
    return Token{}, q.Error
  }
  defer db.DB.Delete(&t)
  return t, nil
}

func (token *Token) String() string {
  return fmt.Sprintf("signature=%s,repository=%s,access=%s", token.Signature,
    token.Repo, token.Access)
}
<|endoftext|>


<commit_before>package gopush

import "fmt"

func NewIntStack(interpreter *Interpreter) *Stack {
	s := &Stack{
		Functions: make(map[string]Instruction),
	}

	s.Functions["%"] = func() {
		// TODO
	}

	s.Functions["*"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i1 * i2)
	}

	s.Functions["+"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i1 + i2)
	}

	s.Functions["-"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i2 - i1)
	}

	s.Functions["/"] = func() {
		if !interpreter.stackOK("integer", 2) || interpreter.Stacks["integer"].Peek().(int64) == 0 {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i2 / i1)
	}

	s.Functions["<"] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 < i1)
	}

	s.Functions["="] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 == i1)
	}

	s.Functions[">"] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 > i1)
	}

	s.Functions["define"] = func() {
		if !interpreter.stackOK("name", 1) || !interpreter.stackOK("integer", 1) {
			return
		}

		n := interpreter.Stacks["name"].Pop().(string)
		i := interpreter.Stacks["integer"].Pop().(int64)

		interpreter.Definitions[n] = Code{Length: 1, Literal: fmt.Sprint(i)}
	}

	s.Functions["dup"] = func() {
		interpreter.Stacks["integer"].Dup()
	}

	s.Functions["flush"] = func() {
		interpreter.Stacks["integer"].Flush()
	}

	s.Functions["fromboolean"] = func() {
		if !interpreter.stackOK("boolean", 1) {
			return
		}

		b := interpreter.Stacks["boolean"].Pop().(bool)
		if b {
			interpreter.Stacks["integer"].Push(int64(1))
		} else {
			interpreter.Stacks["integer"].Push(int64(0))
		}
	}

	s.Functions["fromfloat"] = func() {
		if !interpreter.stackOK("float", 1) {
			return
		}

		f := interpreter.Stacks["float"].Pop().(float64)
		interpreter.Stacks["integer"].Push(int64(f))
	}

	s.Functions["max"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)

		if i1 > i2 {
			interpreter.Stacks["integer"].Push(i1)
		} else {
			interpreter.Stacks["integer"].Push(i2)
		}
	}

	s.Functions["min"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)

		if i1 < i2 {
			interpreter.Stacks["integer"].Push(i1)
		} else {
			interpreter.Stacks["integer"].Push(i2)
		}
	}

	s.Functions["pop"] = func() {
		interpreter.Stacks["integer"].Pop()
	}

	s.Functions["rand"] = func() {
		// TODO
	}

	s.Functions["rot"] = func() {
		interpreter.Stacks["integer"].Rot()
	}

	s.Functions["shove"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Peek().(int64)

		interpreter.Stacks["integer"].Shove(i2, i1)
		interpreter.Stacks["integer"].Pop()
	}

	s.Functions["stackdepth"] = func() {
		interpreter.Stacks["integer"].Push(interpreter.Stacks["integer"].Len())
	}

	s.Functions["swap"] = func() {
		interpreter.Stacks["integer"].Swap()
	}

	s.Functions["yank"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		idx := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Yank(idx)
	}

	s.Functions["yankdup"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		idx := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].YankDup(idx)
	}

	return s
}
<commit_msg>Implement INTEGER.%<commit_after>package gopush

import "fmt"

func NewIntStack(interpreter *Interpreter) *Stack {
	s := &Stack{
		Functions: make(map[string]Instruction),
	}

	s.Functions["%"] = func() {
		if !interpreter.stackOK("integer", 2) || interpreter.Stacks["integer"].Peek().(int64) == 0 {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)

		mod := i2 % i1
		if (i2 < 0 && i1 > 0) || (i2 > 0 && i1 < 0) {
			mod = i1 + mod
		}

		interpreter.Stacks["integer"].Push(mod)
	}

	s.Functions["*"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i1 * i2)
	}

	s.Functions["+"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i1 + i2)
	}

	s.Functions["-"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i2 - i1)
	}

	s.Functions["/"] = func() {
		if !interpreter.stackOK("integer", 2) || interpreter.Stacks["integer"].Peek().(int64) == 0 {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Push(i2 / i1)
	}

	s.Functions["<"] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 < i1)
	}

	s.Functions["="] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 == i1)
	}

	s.Functions[">"] = func() {
		if !interpreter.stackOK("integer", 2) || !interpreter.stackOK("boolean", 0) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["boolean"].Push(i2 > i1)
	}

	s.Functions["define"] = func() {
		if !interpreter.stackOK("name", 1) || !interpreter.stackOK("integer", 1) {
			return
		}

		n := interpreter.Stacks["name"].Pop().(string)
		i := interpreter.Stacks["integer"].Pop().(int64)

		interpreter.Definitions[n] = Code{Length: 1, Literal: fmt.Sprint(i)}
	}

	s.Functions["dup"] = func() {
		interpreter.Stacks["integer"].Dup()
	}

	s.Functions["flush"] = func() {
		interpreter.Stacks["integer"].Flush()
	}

	s.Functions["fromboolean"] = func() {
		if !interpreter.stackOK("boolean", 1) {
			return
		}

		b := interpreter.Stacks["boolean"].Pop().(bool)
		if b {
			interpreter.Stacks["integer"].Push(int64(1))
		} else {
			interpreter.Stacks["integer"].Push(int64(0))
		}
	}

	s.Functions["fromfloat"] = func() {
		if !interpreter.stackOK("float", 1) {
			return
		}

		f := interpreter.Stacks["float"].Pop().(float64)
		interpreter.Stacks["integer"].Push(int64(f))
	}

	s.Functions["max"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)

		if i1 > i2 {
			interpreter.Stacks["integer"].Push(i1)
		} else {
			interpreter.Stacks["integer"].Push(i2)
		}
	}

	s.Functions["min"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Pop().(int64)

		if i1 < i2 {
			interpreter.Stacks["integer"].Push(i1)
		} else {
			interpreter.Stacks["integer"].Push(i2)
		}
	}

	s.Functions["pop"] = func() {
		interpreter.Stacks["integer"].Pop()
	}

	s.Functions["rand"] = func() {
		// TODO
	}

	s.Functions["rot"] = func() {
		interpreter.Stacks["integer"].Rot()
	}

	s.Functions["shove"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		i1 := interpreter.Stacks["integer"].Pop().(int64)
		i2 := interpreter.Stacks["integer"].Peek().(int64)

		interpreter.Stacks["integer"].Shove(i2, i1)
		interpreter.Stacks["integer"].Pop()
	}

	s.Functions["stackdepth"] = func() {
		interpreter.Stacks["integer"].Push(interpreter.Stacks["integer"].Len())
	}

	s.Functions["swap"] = func() {
		interpreter.Stacks["integer"].Swap()
	}

	s.Functions["yank"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		idx := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].Yank(idx)
	}

	s.Functions["yankdup"] = func() {
		if !interpreter.stackOK("integer", 2) {
			return
		}

		idx := interpreter.Stacks["integer"].Pop().(int64)
		interpreter.Stacks["integer"].YankDup(idx)
	}

	return s
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 VMware, Inc. All Rights Reserved.

package ipmi

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"os/exec"
	"strconv"
	"strings"
)

// Connection wraps the ipmitool program arguments
type Connection struct {
	Path      string
	Hostname  string
	Port      int
	Username  string
	Password  string
	Interface string
}

type rawRequest interface {
	request() []byte // input for impitool raw
	parse([]byte)    // parse output of ipmitool raw
}

func (c *Connection) options() []string {
	intf := c.Interface
	if intf == "" {
		intf = "lanplus"
	}

	options := []string{
		"-H", c.Hostname,
		"-U", c.Username,
		"-P", c.Password,
		"-I", intf,
	}

	if c.Port != 0 {
		options = append(options, "-p", strconv.Itoa(c.Port))
	}

	return options
}

func (c *Connection) run(args ...string) (string, error) {
	path := c.Path
	opts := append(c.options(), args...)

	if path == "" {
		path = "ipmitool"
	}

	cmd := exec.Command(path, opts...)

	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("run %s %s: %s (%s)",
			path, strings.Join(opts, " "), stderr.String(), err)
	}

	return stdout.String(), err
}

func rawDecode(data string) []byte {
	var buf bytes.Buffer

	for _, s := range strings.Split(data, " ") {
		b, err := hex.DecodeString(s)
		if err != nil {
			panic(err)
		}

		_, err = buf.Write(b)
		if err != nil {
			panic(err)
		}
	}

	return buf.Bytes()
}

func rawEncode(data []byte) []string {
	n := len(data)
	buf := make([]string, 0, n)

	// ipmitool raw wasn't happy with hex.Encode
	for i := 0; i < n; i++ {
		buf = append(buf, fmt.Sprintf("%#x", data[i:i+1]))
	}

	return buf
}

func (c *Connection) raw(r rawRequest) error {
	// ipmitool ... raw .. .. ..
	args := []string{"raw"}
	args = append(args, rawEncode(r.request())...)

	output, err := c.run(args...)
	if err != nil {
		return err
	}

	r.parse(rawDecode(strings.TrimSpace(output)))

	return nil
}

func (c *Connection) ChassisStatus() (*ChassisStatus, error) {
	// ipmitool ... chassis status
	s := &ChassisStatus{}
	return s, c.raw(s)
}

func (c *Connection) SetBootDevice(device BootDevice) error {
	// impitool ... chassis bootdev pxe|floppy|etc
	_, err := c.run("chassis", "bootdev", device.String())
	return err
}

func (c *Connection) GetBootFlags() (*BootFlags, error) {
	// ipmitool ... chassis bootparam get 5
	flags := &BootFlags{}
	return flags, c.raw(flags)
}

func (c *Connection) ChassisControl(ctl ChassisControl) error {
	// impitool ... power up|down|cycle|etc
	_, err := c.run("power", ctl.String())
	return err
}
<commit_msg>Use hex.Encode instead of fmt.Sprintf<commit_after>// Copyright (c) 2014 VMware, Inc. All Rights Reserved.

package ipmi

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"os/exec"
	"strconv"
	"strings"
)

// Connection wraps the ipmitool program arguments
type Connection struct {
	Path      string
	Hostname  string
	Port      int
	Username  string
	Password  string
	Interface string
}

type rawRequest interface {
	request() []byte // input for impitool raw
	parse([]byte)    // parse output of ipmitool raw
}

func (c *Connection) options() []string {
	intf := c.Interface
	if intf == "" {
		intf = "lanplus"
	}

	options := []string{
		"-H", c.Hostname,
		"-U", c.Username,
		"-P", c.Password,
		"-I", intf,
	}

	if c.Port != 0 {
		options = append(options, "-p", strconv.Itoa(c.Port))
	}

	return options
}

func (c *Connection) run(args ...string) (string, error) {
	path := c.Path
	opts := append(c.options(), args...)

	if path == "" {
		path = "ipmitool"
	}

	cmd := exec.Command(path, opts...)

	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("run %s %s: %s (%s)",
			path, strings.Join(opts, " "), stderr.String(), err)
	}

	return stdout.String(), err
}

func rawDecode(data string) []byte {
	var buf bytes.Buffer

	for _, s := range strings.Split(data, " ") {
		b, err := hex.DecodeString(s)
		if err != nil {
			panic(err)
		}

		_, err = buf.Write(b)
		if err != nil {
			panic(err)
		}
	}

	return buf.Bytes()
}

func rawEncode(data []byte) []string {
	n := len(data)
	buf := make([]string, 0, n)

	// ipmitool needs every byte to be a separate argument
	for i := 0; i < n; i++ {
		buf = append(buf, "0x"+hex.EncodeToString(data[i:i+1]))
	}

	return buf
}

func (c *Connection) raw(r rawRequest) error {
	// ipmitool ... raw .. .. ..
	args := []string{"raw"}
	args = append(args, rawEncode(r.request())...)

	output, err := c.run(args...)
	if err != nil {
		return err
	}

	r.parse(rawDecode(strings.TrimSpace(output)))

	return nil
}

func (c *Connection) ChassisStatus() (*ChassisStatus, error) {
	// ipmitool ... chassis status
	s := &ChassisStatus{}
	return s, c.raw(s)
}

func (c *Connection) SetBootDevice(device BootDevice) error {
	// impitool ... chassis bootdev pxe|floppy|etc
	_, err := c.run("chassis", "bootdev", device.String())
	return err
}

func (c *Connection) GetBootFlags() (*BootFlags, error) {
	// ipmitool ... chassis bootparam get 5
	flags := &BootFlags{}
	return flags, c.raw(flags)
}

func (c *Connection) ChassisControl(ctl ChassisControl) error {
	// impitool ... power up|down|cycle|etc
	_, err := c.run("power", ctl.String())
	return err
}
<|endoftext|>


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

package rbtree

type Iterator func(i Item) bool

// Ascend will call iterator once for each element greater than pivot
// in ascending order. It will stop whenever the iterator returns false.
func (t *Rbtree) Ascend(pivot Item, iterator Iterator) {
	t.ascend(t.root, pivot, iterator)
}

func (t *Rbtree) ascend(h *Node, pivot Item, iterator Iterator) bool {
	if h == t.NIL {
		return true
	}

	if !less(h.Item, pivot) {
		if !t.ascend(h.Left, pivot, iterator) {
			return false
		}
		if !iterator(h.Item) {
			return false
		}
	}

	return t.ascend(h.Right, pivot, iterator)
}

func (t *Rbtree) Min() Item {
	x := t.min(t.root)

	if x == t.NIL {
		return nil
	}

	return x.Item
}
<commit_msg>Iterator: add descend iterator<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rbtree

type Iterator func(i Item) bool

// Ascend will call iterator once for each element greater or equal than pivot
// in ascending order. It will stop whenever the iterator returns false.
func (t *Rbtree) Ascend(pivot Item, iterator Iterator) {
	t.ascend(t.root, pivot, iterator)
}

func (t *Rbtree) ascend(x *Node, pivot Item, iterator Iterator) bool {
	if x == t.NIL {
		return true
	}

	if !less(x.Item, pivot) {
		if !t.ascend(x.Left, pivot, iterator) {
			return false
		}
		if !iterator(x.Item) {
			return false
		}
	}

	return t.ascend(x.Right, pivot, iterator)
}

// Descend will call iterator once for each element less or equal than pivot
// in descending order. It will stop whenever the iterator returns false.
func (t *Rbtree) Descend(pivot Item, iterator Iterator) {
	t.descend(t.root, pivot, iterator)
}

func (t *Rbtree) descend(x *Node, pivot Item, iterator Iterator) bool {
	if x == nil {
		return true
	}

	if !less(pivot, x.Item) {
		if !t.descend(x.Right, pivot, iterator) {
			return false
		}
		if !iterator(x.Item) {
			return false
		}
	}

	return t.descend(x.Left, pivot, iterator)
}

func (t *Rbtree) Min() Item {
	x := t.min(t.root)

	if x == t.NIL {
		return nil
	}

	return x.Item
}
<|endoftext|>


<commit_before>package parsing

import (
	"bytes"
	"fmt"
	"net/mail"
	"regexp"
	"strings"

	"github.com/acapps/zipwhip-smtp/request"
)

const (
	CONTENT_ENCODING = "content-transfer-encoding"
	CONTENT_TYPE     = "content-type"
	REPLY_TO         = "reply-to"
	SUBJECT          = "subject"
	ZIPWHIP_AUTH     = "zipwhip-auth"
	FROM             = "from"
)

type parseFunc func([]byte, *request.SendRequest) error

var ZipwhipAuthParseTable = map[string]parseFunc{
	ZIPWHIP_AUTH: zipwhipAuth,
}

var FallbackAuthParseTable = map[string]parseFunc{
	SUBJECT: subject,
}

var DefaultParseTable = map[string]parseFunc{
	REPLY_TO: replyTo,
	FROM:     from,
}

const SESSION_FORMAT = "^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}:[0-9]"

var SESSION_MATCHER *regexp.Regexp

func init() {
	SESSION_MATCHER = regexp.MustCompile(SESSION_FORMAT)
}

func Headers(sendRequest *request.SendRequest) error {

	err := authentication(sendRequest)
	if err != nil {
		return fmt.Errorf("Authentication failed: %s", err)
	}

	for key, value := range sendRequest.Headers {

		if _, ok := DefaultParseTable[key]; ok {

			var parseFunction parseFunc = DefaultParseTable[key]

			err := parseFunction(value, sendRequest)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func Recipients(recipients []string, sendRequest *request.SendRequest) error {

	for _, recipient := range recipients {
		nameAddress := strings.Replace(recipient, "\"", "", -1)

		address, err := mail.ParseAddress(nameAddress)
		if err != nil {
			return fmt.Errorf("Error parsing Address: %s because of error: %s", address, err)
		}

		address.Address = strings.Split(address.Address, "@")[0]

		if len(address.Address) >= 9 {
			sendRequest.Recipients = append(sendRequest.Recipients, []byte(address.Address))
		}
	}

	return nil
}

func authentication(sendRequest *request.SendRequest) error {

	if _, ok := sendRequest.Headers[ZIPWHIP_AUTH]; ok {

		var parseFunction parseFunc = ZipwhipAuthParseTable[ZIPWHIP_AUTH]

		err := parseFunction(sendRequest.Headers[ZIPWHIP_AUTH], sendRequest)
		if err != nil {
			return err
		}
	} else if _, ok = sendRequest.Headers[SUBJECT]; ok {

		var parseFunction parseFunc = FallbackAuthParseTable[SUBJECT]

		err := parseFunction(sendRequest.Headers[SUBJECT], sendRequest)
		if err != nil {
			return err
		}
	} else {
		return fmt.Errorf("No authorization mechanism found. %+s", sendRequest.Headers)
	}

	err := sendingStrategy(sendRequest)
	if err != nil {
		return fmt.Errorf("authenication failed due to error determining sending strategy. %s", err)
	}

	return nil
}

func subject(subjectLine []byte, sendRequest *request.SendRequest) error {

	subjectLine = bytes.Replace(subjectLine, []byte("\""), []byte(""), -1)

	sendRequest.Key = subjectLine

	return nil
}

func zipwhipAuth(vendorKey []byte, sendRequest *request.SendRequest) error {

	sendRequest.Key = vendorKey

	return nil
}

func sendingStrategy(sendRequest *request.SendRequest) error {

	if SESSION_MATCHER.Match(sendRequest.Key) {
		sendRequest.Strategy = request.SESSION
		return nil
	}
	if len(sendRequest.Key) > 0 {
		sendRequest.Strategy = request.VENDOR
		return nil
	}

	return fmt.Errorf("No sending strategy could be detected. %s", sendRequest.Key)
}

func replyTo(replyHeader []byte, sendRequest *request.SendRequest) error {

	nameAddress := bytes.Replace(replyHeader, []byte("\""), []byte(""), -1)

	address, err := mail.ParseAddress(string(nameAddress))
	if err != nil {
		return fmt.Errorf("Error parsing Address: %s becasue of error: %s", address, err)
	}

	sendRequest.ReplyTo = *address
	return nil
}

func from(fromHeader []byte, sendRequest *request.SendRequest) error {

	nameAddress := bytes.Replace(fromHeader, []byte("\""), []byte(""), -1)

	address, err := mail.ParseAddress(string(nameAddress))
	if err != nil {
		return fmt.Errorf("Error parsing Address: %s because of error: %s", address, err)
	}

	address.Address = strings.Split(address.Address, "@")[0]

	sendRequest.Sender = *address
	return nil
}
<commit_msg>Better Authentication handling for the different scenarios.<commit_after>package parsing

import (
	"bytes"
	"fmt"
	"net/mail"
	"regexp"
	"strings"

	"github.com/acapps/zipwhip-smtp/request"
    "github.com/acapps/zipwhip-smtp/address"
)

const (
	CONTENT_ENCODING = "content-transfer-encoding"
	CONTENT_TYPE     = "content-type"
	REPLY_TO         = "reply-to"
	SUBJECT          = "subject"
	ZIPWHIP_AUTH     = "zipwhip-auth"
	FROM             = "from"
)

type parseFunc func([]byte, *request.SendRequest) error

//var ZipwhipAuthParseTable = map[string]parseFunc{
//	ZIPWHIP_AUTH: zipwhipAuth,
//}
//
//var FallbackAuthParseTable = map[string]parseFunc{
//	SUBJECT: subject,
//}

var DefaultParseTable = map[string]parseFunc{
	REPLY_TO: replyTo,
	FROM:     from,
}

const (
    SESSION_FORMAT = "^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}:[0-9]"
    SUBJECT_VENDOR_FORMAT = `[a-zA-Z0-9]{1,}::\+[0-9]{11}@smtp.zipwhip.com`
    EMAIL_FORMAT = `\+[0-9]{11}@smtp.zipwhip.com`
)

var (
    SESSION_MATCHER *regexp.Regexp
    SUBJECT_VENDOR_MATCHER *regexp.Regexp
    EMAIL_MATCHER *regexp.Regexp
)

func init() {
	SESSION_MATCHER = regexp.MustCompile(SESSION_FORMAT)
    SUBJECT_VENDOR_MATCHER = regexp.MustCompile(SUBJECT_VENDOR_FORMAT)
    EMAIL_MATCHER = regexp.MustCompile(EMAIL_FORMAT)
}

func Headers(sendRequest *request.SendRequest) error {

    for key, value := range sendRequest.Headers {

        if _, ok := DefaultParseTable[key]; ok {

            var parseFunction parseFunc = DefaultParseTable[key]

            err := parseFunction(value, sendRequest)
            if err != nil {
                return err
            }
        }
    }

	err := authentication(sendRequest)
	if err != nil {
		return fmt.Errorf("Authentication failed: %s", err)
	}

	return nil
}

func Recipients(recipients []string, sendRequest *request.SendRequest) error {

	for _, recipient := range recipients {
		nameAddress := strings.Replace(recipient, "\"", "", -1)

		address, err := mail.ParseAddress(nameAddress)
		if err != nil {
			return fmt.Errorf("Error parsing Address: %s because of error: %s", address, err)
		}

		address.Address = strings.Split(address.Address, "@")[0]

		if len(address.Address) >= 9 {
			sendRequest.Recipients = append(sendRequest.Recipients, []byte(address.Address))
		}
	}

	return nil
}

func SendingStrategy(sendRequest *request.SendRequest) error {

    if SESSION_MATCHER.Match(sendRequest.Key) {
        sendRequest.Strategy = request.SESSION
        return nil
    }

    if len(sendRequest.Key) > 0 {
        sendRequest.Strategy = request.VENDOR
        return nil
    }

    return fmt.Errorf("No sending strategy could be detected. %s", sendRequest.Key)
}

// Authentication is defined by meeting the following criteria
// A. Zipwhip-Auth populated VendorKey and From Address set to a valid Email, phoneNumber@smtp.zipwhip.com
// B. Zipwhip-Auth populated VendorKey and Subject set to a valid Email, phoneNumber@smtp.zipwhip.com
// C. Zipwhip Auth populated SessionKey
// D. Subject populated with VendorKey and From Address set to a valid Email, phoneNumber@smtp.zipwhip.com
// E. Subject populated with SessionKey
func authentication(sendRequest *request.SendRequest) error {

    if _, ok := sendRequest.Headers[ZIPWHIP_AUTH]; ok {

        sendRequest.Key = sendRequest.Headers[ZIPWHIP_AUTH]

        err := authenticationZipwhipAuth(sendRequest)
        if err != nil {
            return fmt.Errorf("An error occurred while runing authentication on ZipwhipAuth. %s", err)
        }

        return nil
    }

    if _, ok := sendRequest.Headers[SUBJECT]; ok {

        sendRequest.Key = sendRequest.Headers[SUBJECT]

        err := authenticationSubject(sendRequest)
        if err != nil {
            return fmt.Errorf("An error occurred while runing authentication on Subject. %s", err)
        }

        return nil
	}

    return fmt.Errorf("No authorization mechanism found. %+s", sendRequest.Headers)
}

func authenticationZipwhipAuth(sendRequest *request.SendRequest) error {

    // C.
    if SESSION_MATCHER.Match(sendRequest.Headers[ZIPWHIP_AUTH]) {

        sendRequest.Strategy = request.SESSION
        return nil
    }

    _, from := sendRequest.Headers[FROM]
    _, subject := sendRequest.Headers[SUBJECT]

    if !from && !subject {
        return fmt.Errorf("Unable to locate appropriate Sender in from or subject.")
    }

    sendRequest.Strategy = request.VENDOR
    var HeaderToParse []byte

    if from {
        HeaderToParse = sendRequest.Headers[FROM]
    } else {
        HeaderToParse = sendRequest.Headers[SUBJECT]
    }

    if EMAIL_MATCHER.Match(HeaderToParse) {

        err := sendRequest.Sender.Parse(HeaderToParse)
        if err != nil {

            return fmt.Errorf("An error occurred while parsing the From Address: %s", err)
        }
        return nil
    }

    return address.IsValidZipwhipAddress(HeaderToParse)
}

func authenticationSubject(sendRequest *request.SendRequest) error {

    return nil
}

func subject(subjectLine []byte, sendRequest *request.SendRequest) error {

	subjectLine = bytes.Replace(subjectLine, []byte("\""), []byte(""), -1)

	sendRequest.Key = subjectLine

	return nil
}

func replyTo(replyHeader []byte, sendRequest *request.SendRequest) error {

	nameAddress := bytes.Replace(replyHeader, []byte("\""), []byte(""), -1)

	address, err := mail.ParseAddress(string(nameAddress))
	if err != nil {
		return fmt.Errorf("Error parsing Address: %s becasue of error: %s", address, err)
	}

	sendRequest.ReplyTo = *address
	return nil
}

func from(fromHeader []byte, sendRequest *request.SendRequest) error {

    fromHeader = bytes.Trim(fromHeader, " <>")
    sendRequest.Headers[FROM] = fromHeader

	return nil
}
<|endoftext|>