<commit_before>package main

// all the usage
func (cmd *ggcmd) initCommands() {
	cmd.commands = map[string]*action{

		"": {`gg - golang go get vendor manager

Manage vendor directory:

 vinit    Initialize vendor directory.
 vadd     Add package to vendor.
 vlist    List packages being vendored.
 vrebuild Rebuild from config file.
 vupdate  Update packages.

Import rewriting:

 usev     Rewrite to use import vendored packages.
 unusev   Rewrite to undo vendored imports.

Other commands:

 rdep     List dependencies of a go-getable package.
 ldep     List dependencies of local directory/package.
 listcore List known core packages.

Special files:

 _ggv.json Vendor configuration file.
 .gg       Specifies vendor root to use.

Use "gg help <command>" for usage of a specific command.
`, nil},

		// ---------------------------------------------------
		"help": {`Run "gg help"`, cmd.cmdHelp},

		// ---------------------------------------------------
		"vinit": {`gg vinit [options]

Initialize vendor directory.

    Create vendoring description file at current directory. The vendor package
    root will be derived from the current directory and GOPATH.

Options:

 -v --vendor VENDOR_ROOT Create vendor description file at specified
                         package directory under GOPATH.
`, cmd.cmdVinit},

		// ---------------------------------------------------
		"vadd": {`gg vadd [options] <gg-package> [<gg-packages ...]

Add package to vendor.

    For a go-gettable package(s), add to a vendor package directory. Will try
    current directory, "internal" in order to find vendor directory. Else
    specify with -v. If you need specific options for this package (lock,
    rewrite, notes), please vadd only one package.

Options:

 -v --vendor VENDOR_ROOT Vendor package root
 --vcs VCS               git, hg
 --vcs-source URL        Source of the package. https://github.com/a/b
 --revision REVISION     Revision, or latest if not specified.
 --lock=false            Lock on revision when adding done.
 --rewrite=true          Will bring in the package(s), but skip import rewrite.
 --shallow=false         Only get the gg-package without going recursively.
                         Default is recursive.
 --save-repo=false       Keep copy of .git or .hg in vendor directories.
 --dep-tests=true        Check for dependencies of tests as well.
 --notes NOTES           Add notes for package.
 --test=false            Dry run test.
`, cmd.cmdVadd},
		// ---------------------------------------------------
		"voption": {`gg voption [options] [<gg-package> ...]

Future, allow editing options via command line action.
Print or set options for vendored package.

    For vendored packages, you may change the update options. For instance, you
    may lock its revision or disable import rewriting. If you update the
    revision, consider using using vupdate as well to update that package.

Options:
 -v --vendor VENDOR_ROOT Vendor package root
 -a --all                If options specified, apply on all packages.
 --vcs VCS               git, hg, manual
 --vcs-source URL        Source of the package. https://github.com/a/b
 --revision REVISION     Revision, or latest if not specified.
 --lock=false            Lock on revision when adding done.
 --rewrite=true          Will bring in the package(s), but skip import rewrite.
 --notes NOTES           Add notes for package.
`, cmd.cmdVoption},
		// ---------------------------------------------------
		"vrm": {`gg vrm [options] <gg-package> [<gg-package> ...]

Future, allow deleting by command line.
Remove previously vendored package.

    Unlike vadd, this will not use recursive dependency to remove dependent
    packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, nil},
		// ---------------------------------------------------
		"vlist": {`gg vlist [options]

List managed packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, cmd.cmdVlist},
		// ---------------------------------------------------
		"vstrip": {`gg vstrip [options]

Future, allow command line helper to strip vendor directory.
Strip vendor directory.

    Remove everything that is rebuildable.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, nil},
		// ---------------------------------------------------
		"vrebuild": {`gg vrebuild [options]

Rebuild vendor directory.

    Given the configuration file _ggv.json in the vendor directory, strip and
    rebuild as described.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, cmd.cmdVrebuild},
		// ---------------------------------------------------
		"vupdate": {`gg vupdate [options] [<gg-package> ...]

Update previously added vendored packages to latest revision.

    By default it will recheck dependencies of packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 --shallow=false      Skip rechecking of dependencies.
 --save-repo=false    Keep copy of .git or .hg in vendor directories.
 --dep-tests=true     Check for dependencies of tests as well.
 --revision REVISION  Update specified package to revision. (shallow)
 --test               See what would actually get updated without modifying
                      your vendor directory.
`, cmd.cmdVupdate},
		// ---------------------------------------------------
		"usev": {`gg usev [options] [<gg-package> ...]

Use previously vendored package.

    In the current directory, convert imports to vendored imports that
    currently exists. Import rewrites will not recurse into subdirectories with
    vendor configuration file or "internal" directories.

    Vendored directory is specified as --vendor, or as a ".gg" file in the
    directory. If neither is specified, it will look for the vendor directory
    under "internal".

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 -d --dir    DIR         Start at specified directory.
 `, cmd.cmdUsev},
		// ---------------------------------------------------
		"unusev": {`gg unusev [options] [<gg-package> ...]

Unvendor imports.

    This must be run with respect to a vendor package root. Vendored directory
    is specified as --vendor, or as a ".gg" file in the directory. If neither
    is specified, it will look for the vendor directory under "internal".

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 -d --dir    DIR         Start at specified directory.
`, cmd.cmdUnusev},
		// ---------------------------------------------------
		"irewrite": {`gg irewrite [options] <previous-import> <new-import>

Raw import rewrite.

    Starting at the current directory, perform import rewrites as described. It
    will not recurse into subdirectories with the vendor configuration file or
    "internal" directories. It will skip core packages during this import
    rewrite.

Options:
 -d --dir DIR Start import rewrite recursively down.
 --no-recurse Perform default or specified directory only.
 --force      Recursively do all .go files.

`, nil},
		// ---------------------------------------------------
		"rdep": {`gg rdep [options] <gg-package>

Check dependencies of a package in a public repo.

    Given a canonical package name, get dependencies as it currently exists on
    the internet. This is done by creating a clean temporary directory and
    running go get.

Options:

 --dep-tests=true  Check for dependencies of tests as well.
`, cmd.cmdRdep},
		// ---------------------------------------------------
		"ldep": {`gg ldep [options] [<local-package>]

Check dependencies of a package residing on local disk.

    For a local directory/package on your disk, determine the dependencies.
    Skip core packages and subpackages already found under the package being
    queried.

Options:

 --dep-tests=true  Check for dependencies of tests as well.

`, cmd.cmdLdep},
		// ---------------------------------------------------
		"pkgmeta": {`gg pkgmeta

Get meta for package.
`, cmd.cmdPkgmeta},
	}
}
<commit_msg>tweaking usage<commit_after>package main

// all the usage
func (cmd *ggcmd) initCommands() {
	cmd.commands = map[string]*action{

		"": {`gg - golang go get vendor manager

Manage vendor directory:

 vinit    Initialize vendor directory.
 vadd     Add package to vendor.
 vlist    List packages being vendored.
 vrebuild Rebuild from config file.
 vupdate  Update packages.

Import rewriting:

 usev     Rewrite to use import vendored packages.
 unusev   Rewrite to undo vendored imports.

Other commands:

 rdep     List dependencies of a go-getable package.
 ldep     List dependencies of local directory/package.

Special files:

 _ggv.json Vendor configuration file.
 .gg       Specifies vendor root to use.

Use "gg help <command>" for usage of a specific command.
`, nil},

		// ---------------------------------------------------
		"help": {`Run "gg help"`, cmd.cmdHelp},

		// ---------------------------------------------------
		"vinit": {`gg vinit [options]

Initialize vendor directory.

    Create vendoring description file at current directory. The vendor package
    root will be derived from the current directory and GOPATH.

Options:

 -v --vendor VENDOR_ROOT Create vendor description file at specified
                         package directory under GOPATH.
`, cmd.cmdVinit},

		// ---------------------------------------------------
		"vadd": {`gg vadd [options] <gg-package> [<gg-packages ...]

Add package to vendor.

    For a go-gettable package(s), add to a vendor package directory. Will try
    current directory, "internal" in order to find vendor directory. Else
    specify with -v. If you need specific options for this package (lock,
    rewrite, notes), please vadd only one package.

Options:

 -v --vendor VENDOR_ROOT Vendor package root
 --vcs VCS               git, hg
 --vcs-source URL        Source of the package. https://github.com/a/b
 --revision REVISION     Revision, or latest if not specified.
 --lock=false            Lock on revision when adding done.
 --rewrite=true          Will bring in the package(s), but skip import rewrite.
 --shallow=false         Only get the gg-package without going recursively.
                         Default is recursive.
 --save-repo=false       Keep copy of .git or .hg in vendor directories.
 --dep-tests=true        Check for dependencies of tests as well.
 --notes NOTES           Add notes for package.
 --test=false            Dry run test.
`, cmd.cmdVadd},
		// ---------------------------------------------------
		"voption": {`gg voption [options] [<gg-package> ...]

Future, allow editing options via command line action.
Print or set options for vendored package.

    For vendored packages, you may change the update options. For instance, you
    may lock its revision or disable import rewriting. If you update the
    revision, consider using using vupdate as well to update that package.

Options:
 -v --vendor VENDOR_ROOT Vendor package root
 -a --all                If options specified, apply on all packages.
 --vcs VCS               git, hg, manual
 --vcs-source URL        Source of the package. https://github.com/a/b
 --revision REVISION     Revision, or latest if not specified.
 --lock=false            Lock on revision when adding done.
 --rewrite=true          Will bring in the package(s), but skip import rewrite.
 --notes NOTES           Add notes for package.
`, cmd.cmdVoption},
		// ---------------------------------------------------
		"vrm": {`gg vrm [options] <gg-package> [<gg-package> ...]

Future, allow deleting by command line.
Remove previously vendored package.

    Unlike vadd, this will not use recursive dependency to remove dependent
    packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, nil},
		// ---------------------------------------------------
		"vlist": {`gg vlist [options]

List managed packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, cmd.cmdVlist},
		// ---------------------------------------------------
		"vstrip": {`gg vstrip [options]

Future, allow command line helper to strip vendor directory.
Strip vendor directory.

    Remove everything that is rebuildable.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, nil},
		// ---------------------------------------------------
		"vrebuild": {`gg vrebuild [options]

Rebuild vendor directory.

    Given the configuration file _ggv.json in the vendor directory, strip and
    rebuild as described.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
`, cmd.cmdVrebuild},
		// ---------------------------------------------------
		"vupdate": {`gg vupdate [options] [<gg-package> ...]

Update previously added vendored packages to latest revision.

    By default it will recheck dependencies of packages.

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 --shallow=false      Skip rechecking of dependencies.
 --save-repo=false    Keep copy of .git or .hg in vendor directories.
 --dep-tests=true     Check for dependencies of tests as well.
 --revision REVISION  Update specified package to revision. (shallow)
 --test               See what would actually get updated without modifying
                      your vendor directory.
`, cmd.cmdVupdate},
		// ---------------------------------------------------
		"usev": {`gg usev [options] [<gg-package> ...]

Use previously vendored package.

    In the current directory, convert imports to vendored imports that
    currently exists. Import rewrites will not recurse into subdirectories with
    vendor configuration file or "internal" directories.

    Vendored directory is specified as --vendor, or as a ".gg" file in the
    directory. If neither is specified, it will look for the vendor directory
    under "internal".

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 -d --dir    DIR         Start at specified directory.
 `, cmd.cmdUsev},
		// ---------------------------------------------------
		"unusev": {`gg unusev [options] [<gg-package> ...]

Unvendor imports.

    This must be run with respect to a vendor package root. Vendored directory
    is specified as --vendor, or as a ".gg" file in the directory. If neither
    is specified, it will look for the vendor directory under "internal".

Options:
 -v --vendor VENDOR_ROOT Vendor package root.
 -d --dir    DIR         Start at specified directory.
`, cmd.cmdUnusev},
		// ---------------------------------------------------
		"irewrite": {`gg irewrite [options] <previous-import> <new-import>

Raw import rewrite.

    Starting at the current directory, perform import rewrites as described. It
    will not recurse into subdirectories with the vendor configuration file or
    "internal" directories. It will skip core packages during this import
    rewrite.

Options:
 -d --dir DIR Start import rewrite recursively down.
 --no-recurse Perform default or specified directory only.
 --force      Recursively do all .go files.

`, nil},
		// ---------------------------------------------------
		"rdep": {`gg rdep [options] <gg-package>

Check dependencies of a package in a public repo.

    Given a canonical package name, get dependencies as it currently exists on
    the internet. This is done by creating a clean temporary directory and
    running go get.

Options:

 --dep-tests=true  Check for dependencies of tests as well.
`, cmd.cmdRdep},
		// ---------------------------------------------------
		"ldep": {`gg ldep [options] [<local-package>]

Check dependencies of a package residing on local disk.

    For a local directory/package on your disk, determine the dependencies.
    Skip core packages and subpackages already found under the package being
    queried.

Options:

 --dep-tests=true  Check for dependencies of tests as well.

`, cmd.cmdLdep},
		// ---------------------------------------------------
		"pkgmeta": {`gg pkgmeta

Get meta for package.
`, cmd.cmdPkgmeta},
	}
}
<|endoftext|>


<commit_before>package goinsta

import (
	"encoding/json"
	"fmt"
)

type Users struct {
	inst *Instagram
}

// newUsers creates new users struct to interact with user functions.
//
// ...
func newUsers(inst *Instagram) *Users {
	users := &Users{inst: inst}

	return users
}

// SetInstagram sets new instagram to user structure
func (users *Users) SetInstagram(inst *Instagram) {
	users.inst = inst
}

// ByName return a *User structure parsed by username
func (users *Users) ByName(name string) (*User, error) {
	body, err := users.inst.sendSimpleRequest(urlUserByName, name)
	if err == nil {
		resp := userResp{}
		err = json.Unmarshal(body, &resp)
		if err == nil {
			user := &resp.User
			return user, nil
		}
	}
	return nil, err
}

// ByID returns a *User structure parsed by user id
func (users *Users) ByID(id int64) (*User, error) {
	data, err := users.inst.prepareData()
	if err != nil {
		return nil, err
	}

	body, err := users.inst.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlUserById, id),
			Query:    generateSignature(data),
		},
	)
	if err == nil {
		user := userResp{}
		err = json.Unmarshal(body, &user)
		return &user.User, err
	}
	return nil, err
}

type userResp struct {
	Status string `json:"status"`
	User   User   `json:"user"`
}

// User is the representation of instagram's user profile
type User struct {
	//Feed *Feed
	//Followers *Followers
	//Following *Following
	//Status *Friendship
	//Story *Story
	//Messages *Messages

	ID                         int64        `json:"pk"`
	Username                   string       `json:"username"`
	FullName                   string       `json:"full_name"`
	Biography                  string       `json:"biography"`
	ProfilePicURL              string       `json:"profile_pic_url"`
	Email                      string       `json:"email"`
	PhoneNumber                string       `json:"phone_number"`
	IsBusiness                 bool         `json:"is_business"`
	Gender                     int          `json:"gender"`
	ProfilePicID               string       `json:"profile_pic_id"`
	HasAnonymousProfilePicture bool         `json:"has_anonymous_profile_picture"`
	IsPrivate                  bool         `json:"is_private"`
	IsVerified                 bool         `json:"is_verified"`
	MediaCount                 int          `json:"media_count"`
	FollowerCount              int          `json:"follower_count"`
	FollowingCount             int          `json:"following_count"`
	GeoMediaCount              int          `json:"geo_media_count"`
	ExternalURL                string       `json:"external_url"`
	HasBiographyTranslation    bool         `json:"has_biography_translation"`
	ExternalLynxURL            string       `json:"external_lynx_url"`
	HdProfilePicURLInfo        PicURLInfo   `json:"hd_profile_pic_url_info"`
	HdProfilePicVersions       []PicURLInfo `json:"hd_profile_pic_versions"`
	UsertagsCount              int          `json:"usertags_count"`
	HasChaining                bool         `json:"has_chaining"`
	IsFavorite                 bool         `json:"is_favorite"`
	ReelAutoArchive            string       `json:"reel_auto_archive"`
	School                     School       `json:"school"`
	PublicEmail                string       `json:"public_email"`
	PublicPhoneNumber          string       `json:"public_phone_number"`
	PublicPhoneCountryCode     string       `json:"public_phone_country_code"`
	ContactPhoneNumber         string       `json:"contact_phone_number"`
	CityID                     int64        `json:"city_id"`
	CityName                   string       `json:"city_name"`
	AddressStreet              string       `json:"address_street"`
	DirectMessaging            string       `json:"direct_messaging"`
	Latitude                   float64      `json:"latitude"`
	Longitude                  float64      `json:"longitude"`
	Category                   string       `json:"category"`
	BusinessContactMethod      string       `json:"business_contact_method"`
	IsCallToActionEnabled      bool         `json:"is_call_to_action_enabled"`
	FbPageCallToActionID       string       `json:"fb_page_call_to_action_id"`
	Zip                        string       `json:"zip"`
}
<commit_msg>Changed Users by Profile and implemented Next for pagination<commit_after>package goinsta

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

type Users struct {
	inst *Instagram

	// It's a bit confusing have the same structure
	// in the Instagram strucure and in the multiple users
	// calls

	endpoint string

	Status   string `json:"status"`
	BigList  bool   `json:"big_list"`
	Users    []User `json:"users"`
	PageSize int    `json:"page_size"`
	NextID   string `json:"next_max_id"`
}

// newUsers creates new users struct to interact with user functions.
//
// ...
func newUsers(inst *Instagram) *Users {
	users := &Users{inst: inst}

	return users
}

// SetInstagram sets new instagram to user structure
func (users *Users) SetInstagram(inst *Instagram) {
	users.inst = inst
}

var ErrNoMore = errors.New("list ends reached")

// Next allows to paginate after calling:
// Account.Follow* and User.Follow*
//
// New user list is stored inside Users
//
// returns ErrNoMore when list reach the end
func (users *Users) Next() error {
	insta := users.inst
	endpoint := users.endpoint

	body, err := insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query: map[string]string{
				"max_id":             users.NextID,
				"ig_sig_key_version": goInstaSigKeyVersion,
				"rank_token":         insta.rankToken,
			},
		},
	)
	if err == nil {
		usrs := Users{}
		err = json.Unmarshal(body, &usrs)
		if err == nil {
			*users = usrs
			users.inst = insta
			users.endpoint = endpoint
		}
	}
	return err
}

// Profile allows user function interactions
type Profile struct {
	inst *Instagram
}

// ByName return a *User structure parsed by username
func (prof *Profile) ByName(name string) (*User, error) {
	body, err := prof.inst.sendSimpleRequest(urlUserByName, name)
	if err == nil {
		resp := userResp{}
		err = json.Unmarshal(body, &resp)
		if err == nil {
			user := &resp.User
			return user, nil
		}
	}
	return nil, err
}

// ByID returns a *User structure parsed by user id
func (prof *Profile) ByID(id int64) (*User, error) {
	data, err := prof.inst.prepareData()
	if err != nil {
		return nil, err
	}

	body, err := prof.inst.sendRequest(
		&reqOptions{
			Endpoint: fmt.Sprintf(urlUserById, id),
			Query:    generateSignature(data),
		},
	)
	if err == nil {
		user := userResp{}
		err = json.Unmarshal(body, &user)
		return &user.User, err
	}
	return nil, err
}

type userResp struct {
	Status string `json:"status"`
	User   User   `json:"user"`
}

// User is the representation of instagram's user profile
type User struct {
	//Feed *Feed
	//Followers *Followers
	//Following *Following
	//Status *Friendship
	//Story *Story
	//Messages *Messages

	ID                         int64        `json:"pk"`
	Username                   string       `json:"username"`
	FullName                   string       `json:"full_name"`
	Biography                  string       `json:"biography"`
	ProfilePicURL              string       `json:"profile_pic_url"`
	Email                      string       `json:"email"`
	PhoneNumber                string       `json:"phone_number"`
	IsBusiness                 bool         `json:"is_business"`
	Gender                     int          `json:"gender"`
	ProfilePicID               string       `json:"profile_pic_id"`
	HasAnonymousProfilePicture bool         `json:"has_anonymous_profile_picture"`
	IsPrivate                  bool         `json:"is_private"`
	IsVerified                 bool         `json:"is_verified"`
	MediaCount                 int          `json:"media_count"`
	FollowerCount              int          `json:"follower_count"`
	FollowingCount             int          `json:"following_count"`
	GeoMediaCount              int          `json:"geo_media_count"`
	ExternalURL                string       `json:"external_url"`
	HasBiographyTranslation    bool         `json:"has_biography_translation"`
	ExternalLynxURL            string       `json:"external_lynx_url"`
	HdProfilePicURLInfo        PicURLInfo   `json:"hd_profile_pic_url_info"`
	HdProfilePicVersions       []PicURLInfo `json:"hd_profile_pic_versions"`
	UsertagsCount              int          `json:"usertags_count"`
	HasChaining                bool         `json:"has_chaining"`
	IsFavorite                 bool         `json:"is_favorite"`
	ReelAutoArchive            string       `json:"reel_auto_archive"`
	School                     School       `json:"school"`
	PublicEmail                string       `json:"public_email"`
	PublicPhoneNumber          string       `json:"public_phone_number"`
	PublicPhoneCountryCode     string       `json:"public_phone_country_code"`
	ContactPhoneNumber         string       `json:"contact_phone_number"`
	CityID                     int64        `json:"city_id"`
	CityName                   string       `json:"city_name"`
	AddressStreet              string       `json:"address_street"`
	DirectMessaging            string       `json:"direct_messaging"`
	Latitude                   float64      `json:"latitude"`
	Longitude                  float64      `json:"longitude"`
	Category                   string       `json:"category"`
	BusinessContactMethod      string       `json:"business_contact_method"`
	IsCallToActionEnabled      bool         `json:"is_call_to_action_enabled"`
	FbPageCallToActionID       string       `json:"fb_page_call_to_action_id"`
	Zip                        string       `json:"zip"`
}
<|endoftext|>


<commit_before>// Package login2 provides sign in and sign up by oauth2 and email and password.
// Inspired in omniauth and devise gem
//
package login2

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strconv"

	"code.google.com/p/go.crypto/bcrypt"
	"code.google.com/p/goauth2/oauth"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))

// Provider is a oauth2 provider, like facebook or google
// Name is provider name, it's like a key, will can be use it after,
// the package only use it as a index.
// Key is oauth2 key
// Secret is oauth2 secret key
// RedirectURL is a url will config on provider
// TokenURL is a URL to get the token on provider
// AuthURL is a URL to auth user on provider
// UserInfoURL is a URL to get User Information on provider
// Scope is whats the scope your app wants
type Provider struct {
	Name        string
	Key         string
	Secret      string
	RedirectURL string
	TokenURL    string
	AuthURL     string
	UserInfoURL string
	Scope       string
}

// Internal auth config
type builderConfig struct {
	Auth        *oauth.Config
	UserInfoURL string
}

// URLS

type URLS struct {
	Redirect string
	SignIn   string
	SignUp   string
}

type Builder struct {
	Providers           map[string]*builderConfig
	UserSetupFn         func(provider string, user *User, rawResponde *http.Response) (int64, error)
	UserExistsFn        func(email string) bool
	UserCreateFn        func(email string, password string, request *http.Request) (int64, error)
	UserIdByEmail       func(email string) (int64, error)
	UserPasswordByEmail func(email string) (string, error)
	URLS                URLS
}

type User struct {
	Id     string
	Email  string
	Link   string
	Name   string
	Gender string
	Locale string
}

func NewBuilder(userProviders []*Provider) *Builder {
	builder := new(Builder)
	builder.Providers = make(map[string]*builderConfig, 0)

	for _, p := range userProviders {
		config := &oauth.Config{
			ClientId:     p.Key,
			ClientSecret: p.Secret,
			RedirectURL:  p.RedirectURL,
			Scope:        p.Scope,
			AuthURL:      p.AuthURL,
			TokenURL:     p.TokenURL,
			TokenCache:   oauth.CacheFile("cache-" + p.Name + ".json"),
		}

		provider := new(builderConfig)
		provider.Auth = config
		provider.UserInfoURL = p.UserInfoURL

		builder.Providers[p.Name] = provider
	}

	return builder
}

func (b *Builder) Router(r *mux.Router) {
	for provider, _ := range b.Providers {
		r.HandleFunc("/auth/"+provider, b.OAuthAuthorize(provider)).Methods("GET")
	}

	r.HandleFunc("/auth/callback/{provider}", b.OAuthLogin()).Methods("GET")
	r.HandleFunc("/users/sign_in", b.SignIn()).Methods("POST")
	r.HandleFunc("/users/sign_up", b.SignUp()).Methods("POST")
	r.HandleFunc("/users/sign_out", b.SignOut()).Methods("GET")
}

// HTTP server

// OAuthAuthorize Send user to Authorize on provider
func (b *Builder) OAuthAuthorize(provider string) func(http.ResponseWriter, *http.Request) {
	config := b.Providers[provider]

	return func(w http.ResponseWriter, r *http.Request) {
		url := config.Auth.AuthCodeURL("")
		log.Println("Send user to", provider)
		http.Redirect(w, r, url, http.StatusFound)
	}
}

func (b *Builder) OAuthLogin() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		vars := mux.Vars(request)
		provider := vars["provider"]

		userId, err := b.OAuthCallback(provider, request)

		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userId, 10))
		}
	}
}

// OAuthCallback receive code from provider and get user information on provider
func (b *Builder) OAuthCallback(provider string, r *http.Request) (int64, error) {
	config := b.Providers[provider]
	code := r.FormValue("code")
	t := &oauth.Transport{Config: config.Auth}
	t.Exchange(code)
	responseAuth, _ := t.Client().Get(config.UserInfoURL)
	defer responseAuth.Body.Close()

	var user User
	decoder := json.NewDecoder(responseAuth.Body)
	err := decoder.Decode(&user)
	if err != nil {
		panic(err)
	}

	return b.UserSetupFn(provider, &user, responseAuth)
}

// SignUp Hanlder create and login user on database and redirecto to RedirectURL
func (b *Builder) SignUp() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		email := request.FormValue("email")
		password := request.FormValue("password")
		hpassword := generatePassword(password)

		userID, err := b.UserCreateFn(email, hpassword, request)
		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userID, 10))
		}
	}
}

func (b *Builder) SignIn() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		email := r.FormValue("email")
		password := r.FormValue("password")
		userPassword, err := b.UserPasswordByEmail(email)

		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		}

		err = checkPassword(userPassword, password)
		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		} else {
			userId, _ := b.UserIdByEmail(email)
			b.login(r, w, strconv.FormatInt(userId, 10))
		}
	}
}

func (b *Builder) SignOut() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		session, _ := store.Get(r, "_session")
		session.Values["user_id"] = nil
		session.Save(r, w)

		http.Redirect(w, r, b.URLS.SignIn, 302)
	}
}

func (b *Builder) Protected(fn func(string, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		userID := b.CurrentUser(r)
		if userID != "" {
			fn(userID, w, r)
		} else {
			http.Redirect(w, r, b.URLS.SignIn, 302)
		}
	}
}

// helper

func (b *Builder) login(r *http.Request, w http.ResponseWriter, userId string) {
	session, _ := store.Get(r, "_session")
	session.Values["user_id"] = userId
	session.Save(r, w)

	http.Redirect(w, r, b.URLS.Redirect, 302)
}

func (b *Builder) CurrentUser(r *http.Request) string {
	session, _ := store.Get(r, "_session")
	userId := session.Values["user_id"]
	id, _ := userId.(string)
	return id
}

func generatePassword(password string) string {
	h, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
	return string(h[:])
}

func checkPassword(hashedPassword, password string) error {
	return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
<commit_msg>updated password check way<commit_after>// Package login2 provides sign in and sign up by oauth2 and email and password.
// Inspired in omniauth and devise gem
//
package login2

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strconv"

	"code.google.com/p/go.crypto/bcrypt"
	"code.google.com/p/goauth2/oauth"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))

// Provider is a oauth2 provider, like facebook or google
// Name is provider name, it's like a key, will can be use it after,
// the package only use it as a index.
// Key is oauth2 key
// Secret is oauth2 secret key
// RedirectURL is a url will config on provider
// TokenURL is a URL to get the token on provider
// AuthURL is a URL to auth user on provider
// UserInfoURL is a URL to get User Information on provider
// Scope is whats the scope your app wants
type Provider struct {
	Name        string
	Key         string
	Secret      string
	RedirectURL string
	TokenURL    string
	AuthURL     string
	UserInfoURL string
	Scope       string
}

// Internal auth config
type builderConfig struct {
	Auth        *oauth.Config
	UserInfoURL string
}

// URLS

type URLS struct {
	Redirect string
	SignIn   string
	SignUp   string
}

type Builder struct {
	Providers           map[string]*builderConfig
	UserSetupFn         func(provider string, user *User, rawResponde *http.Response) (int64, error)
	UserExistsFn        func(email string) bool
	UserCreateFn        func(email string, password string, request *http.Request) (int64, error)
	UserIdByEmail       func(email string) (int64, error)
	UserPasswordByEmail func(email string) (string, bool)
	URLS                URLS
}

type User struct {
	Id     string
	Email  string
	Link   string
	Name   string
	Gender string
	Locale string
}

func NewBuilder(userProviders []*Provider) *Builder {
	builder := new(Builder)
	builder.Providers = make(map[string]*builderConfig, 0)

	for _, p := range userProviders {
		config := &oauth.Config{
			ClientId:     p.Key,
			ClientSecret: p.Secret,
			RedirectURL:  p.RedirectURL,
			Scope:        p.Scope,
			AuthURL:      p.AuthURL,
			TokenURL:     p.TokenURL,
			TokenCache:   oauth.CacheFile("cache-" + p.Name + ".json"),
		}

		provider := new(builderConfig)
		provider.Auth = config
		provider.UserInfoURL = p.UserInfoURL

		builder.Providers[p.Name] = provider
	}

	return builder
}

func (b *Builder) Router(r *mux.Router) {
	for provider, _ := range b.Providers {
		r.HandleFunc("/auth/"+provider, b.OAuthAuthorize(provider)).Methods("GET")
	}

	r.HandleFunc("/auth/callback/{provider}", b.OAuthLogin()).Methods("GET")
	r.HandleFunc("/users/sign_in", b.SignIn()).Methods("POST")
	r.HandleFunc("/users/sign_up", b.SignUp()).Methods("POST")
	r.HandleFunc("/users/sign_out", b.SignOut()).Methods("GET")
}

// HTTP server

// OAuthAuthorize Send user to Authorize on provider
func (b *Builder) OAuthAuthorize(provider string) func(http.ResponseWriter, *http.Request) {
	config := b.Providers[provider]

	return func(w http.ResponseWriter, r *http.Request) {
		url := config.Auth.AuthCodeURL("")
		log.Println("Send user to", provider)
		http.Redirect(w, r, url, http.StatusFound)
	}
}

func (b *Builder) OAuthLogin() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		vars := mux.Vars(request)
		provider := vars["provider"]

		userId, err := b.OAuthCallback(provider, request)

		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userId, 10))
		}
	}
}

// OAuthCallback receive code from provider and get user information on provider
func (b *Builder) OAuthCallback(provider string, r *http.Request) (int64, error) {
	config := b.Providers[provider]
	code := r.FormValue("code")
	t := &oauth.Transport{Config: config.Auth}
	t.Exchange(code)
	responseAuth, _ := t.Client().Get(config.UserInfoURL)
	defer responseAuth.Body.Close()

	var user User
	decoder := json.NewDecoder(responseAuth.Body)
	err := decoder.Decode(&user)
	if err != nil {
		panic(err)
	}

	return b.UserSetupFn(provider, &user, responseAuth)
}

// SignUp Hanlder create and login user on database and redirecto to RedirectURL
func (b *Builder) SignUp() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		email := request.FormValue("email")
		password := request.FormValue("password")
		hpassword := generatePassword(password)

		userID, err := b.UserCreateFn(email, hpassword, request)
		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userID, 10))
		}
	}
}

func (b *Builder) SignIn() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		email := r.FormValue("email")
		password := r.FormValue("password")
		userPassword, ok := b.UserPasswordByEmail(email)

		if !ok {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		}

		err := checkPassword(userPassword, password)
		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		} else {
			userId, _ := b.UserIdByEmail(email)
			b.login(r, w, strconv.FormatInt(userId, 10))
		}
	}
}

func (b *Builder) SignOut() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		session, _ := store.Get(r, "_session")
		session.Values["user_id"] = nil
		session.Save(r, w)

		http.Redirect(w, r, b.URLS.SignIn, 302)
	}
}

func (b *Builder) Protected(fn func(string, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		userID := b.CurrentUser(r)
		if userID != "" {
			fn(userID, w, r)
		} else {
			http.Redirect(w, r, b.URLS.SignIn, 302)
		}
	}
}

// helper

func (b *Builder) login(r *http.Request, w http.ResponseWriter, userId string) {
	session, _ := store.Get(r, "_session")
	session.Values["user_id"] = userId
	session.Save(r, w)

	http.Redirect(w, r, b.URLS.Redirect, 302)
}

func (b *Builder) CurrentUser(r *http.Request) string {
	session, _ := store.Get(r, "_session")
	userId := session.Values["user_id"]
	id, _ := userId.(string)
	return id
}

func generatePassword(password string) string {
	h, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
	return string(h[:])
}

func checkPassword(hashedPassword, password string) error {
	return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"path/filepath"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}
func createDir(path string){
	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.Mkdir(path,0777)

	}
}

func writeToFile(path string,content string) {
	f,err := os.Create(path)
	check(err)
	f.WriteString(content)
	f.Close()
}

func getStringFromBindata(path string) string  {
	data, err := Asset(path)
	check(err)
	return string(data[:])
}

func addFuncToSettingsGradle(funcname string) {
	absPath, _ := filepath.Abs("./functions")
	if _, err := os.Stat(absPath); err == nil {
		f, err := os.OpenFile("settings.gradle", os.O_APPEND|os.O_WRONLY, 0600)
		check(err)
		if _, err = f.WriteString("include " + "'functions/"+funcname+"'"); err != nil {
			panic(err)
		}
	}

}<commit_msg>settings fix<commit_after>package main

import (
	"os"
	"path/filepath"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}
func createDir(path string){
	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.Mkdir(path,0777)

	}
}

func writeToFile(path string,content string) {
	f,err := os.Create(path)
	check(err)
	f.WriteString(content)
	f.Close()
}

func getStringFromBindata(path string) string  {
	data, err := Asset(path)
	check(err)
	return string(data[:])
}

func addFuncToSettingsGradle(funcname string) {
	absPath, _ := filepath.Abs("./functions")
	if _, err := os.Stat(absPath); err == nil {
		f, err := os.OpenFile("settings.gradle", os.O_APPEND|os.O_WRONLY, 0600)
		check(err)
		if _, err = f.WriteString("include " + "'functions/"+funcname+"'\n"); err != nil {
			panic(err)
		}
	}

}<|endoftext|>


<commit_before>package scipipe

import (
	"fmt"
	"os/exec"
)

func ExecCmd(cmd string) {
	fmt.Println("Executing command: ", cmd)
	_, err := exec.Command("bash", "-lc", cmd).Output()
	Check(err)
}

func Check(e error) {
	if e != nil {
		panic(e)
	}
}
<commit_msg>panic() -> os.Exit in Check()<commit_after>package scipipe

import (
	"fmt"
	// "github.com/go-errors/errors"
	"os"
	"os/exec"
)

func ExecCmd(cmd string) {
	fmt.Println("Executing command: ", cmd)
	_, err := exec.Command("bash", "-lc", cmd).Output()
	Check(err)
}

func Check(err error) {
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/Netflix-Skunkworks/go-jira"
	ui "github.com/gizak/termui"
	"gopkg.in/coryb/yaml.v2"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

func countLabelsFromQuery(query string) map[string]int {
	data, _ := runJiraQuery(query)
	return countLabelsFromQueryData(data)
}

func countLabelsFromQueryData(data interface{}) map[string]int {
	counts := make(map[string]int)
	issues := data.(map[string]interface{})["issues"].([]interface{})
	for _, issue := range issues {
		issueLabels := issue.(map[string]interface{})["fields"].(map[string]interface{})["labels"]
		for _, v := range issueLabels.([]interface{}) {
			label := v.(string)
			counts[label] = counts[label] + 1
		}
	}
	return counts
}

func runJiraCmdEdit(ticketId string) {
	opts := getJiraOpts()
	c := jira.New(opts)
	ui.Close()
	c.CmdEdit(ticketId)
	log.Notice("Regrettably, need to exit after edit. See https://github.com/mikepea/go-jira-ui/issues/8")
	os.Exit(0)
}

func runJiraCmdComment(ticketId string) {
	opts := getJiraOpts()
	c := jira.New(opts)
	ui.Close()
	c.CmdComment(ticketId)
	log.Notice("Regrettably, need to exit after comment. See https://github.com/mikepea/go-jira-ui/issues/8")
	os.Exit(0)
}

func findTicketIdInString(line string) string {
	re := regexp.MustCompile(`\s[A-Z]{3,12}-[0-9]{1,6}`) // no \s at end, need to match BLAH-123[Done]
	return strings.TrimSpace(re.FindString(line))
}

func runJiraQuery(query string) (interface{}, error) {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	return c.FindIssues()
}

func JiraQueryAsStrings(query string) []string {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	data, _ := c.FindIssues()
	buf := new(bytes.Buffer)
	template := c.GetTemplate("jira_ui_list")
	if template == "" {
		template = default_list_template
	}
	jira.RunTemplate(template, data, buf)
	return strings.Split(strings.TrimSpace(buf.String()), "\n")
}

func JiraTicketAsStrings(id string, template string) []string {
	opts := getJiraOpts()
	c := jira.New(opts)
	data, _ := c.ViewIssue(id)
	buf := new(bytes.Buffer)
	jira.RunTemplate(c.GetTemplate(template), data, buf)
	return strings.Split(strings.TrimSpace(buf.String()), "\n")
}

func WrapText(lines []string, maxWidth int) []string {
	out := make([]string, 0)
	insideNoformatBlock := false
	insideCodeBlock := false
	for _, line := range lines {
		if matched, _ := regexp.MatchString(`^\s+\{code`, line); matched {
			insideCodeBlock = !insideCodeBlock
		} else if strings.TrimSpace(line) == "{noformat}" {
			insideNoformatBlock = !insideNoformatBlock
		}
		if len(line) < maxWidth || insideCodeBlock || insideNoformatBlock {
			out = append(out, line)
			continue
		}
		if matched, _ := regexp.MatchString(`^[a-z]+:\s`, line); matched {
			// don't futz with single line field+value.
			// If they are too long, that's their fault.
			out = append(out, line)
			continue
		}
		chars := strings.Split(line, "")
		total := len(chars)
		for i := 0; i < total/maxWidth; i++ {
			start := i * maxWidth
			end := (i + 1) * maxWidth
			out = append(out, strings.Join(chars[start:end], ""))
		}
		if total%maxWidth > 0 {
			start := (total / maxWidth) * maxWidth // integer div :)
			out = append(out, strings.Join(chars[start:], ""))
		}
	}
	return out
}

func parseYaml(file string, v map[string]interface{}) {
	if fh, err := ioutil.ReadFile(file); err == nil {
		log.Debug("Parsing YAML file: %s", file)
		yaml.Unmarshal(fh, &v)
	}
}

func loadConfigs(opts map[string]interface{}) {
	paths := jira.FindParentPaths(".jira.d/jira-ui-config.yml")
	paths = append(jira.FindParentPaths(".jira.d/config.yml"), paths...)
	paths = append([]string{"/etc/go-jira-ui.yml", "/etc/go-jira.yml"}, paths...)

	// iterate paths in reverse
	for i := len(paths) - 1; i >= 0; i-- {
		file := paths[i]
		if _, err := os.Stat(file); err == nil {
			tmp := make(map[string]interface{})
			parseYaml(file, tmp)
			for k, v := range tmp {
				if _, ok := opts[k]; !ok {
					log.Debug("Setting %q to %#v from %s", k, v, file)
					opts[k] = v
				}
			}
		}
	}
}

func doLogin(opts map[string]interface{}) error {
	c := jira.New(opts)
	fmt.Printf("Logging in as %s:\n", opts["user"])
	return c.CmdLogin()
}

func ensureLoggedIntoJira() error {
	homeDir := os.Getenv("HOME")
	opts := getJiraOpts()
	testSessionQuery := fmt.Sprintf("reporter = %s", opts["user"])
	if _, err := os.Stat(fmt.Sprintf("%s/.jira.d/cookies.js", homeDir)); err != nil {
		return doLogin(opts)
	} else if data, err := runJiraQuery(testSessionQuery); err != nil {
		return doLogin(opts)
	} else if val, ok := data.(map[string]interface{})["errorMessages"]; ok {
		if len(val.([]interface{})) > 0 {
			return doLogin(opts)
		}
	}
	return nil
}

func getJiraOpts() map[string]interface{} {
	user := os.Getenv("USER")
	home := os.Getenv("HOME")
	defaultQueryFields := "summary,created,updated,priority,status,reporter,assignee,labels"
	defaultSort := "priority asc, created"
	defaultMaxResults := 1000

	opts := make(map[string]interface{})
	defaults := map[string]interface{}{
		"user":        user,
		"endpoint":    os.Getenv("JIRA_ENDPOINT"),
		"queryfields": defaultQueryFields,
		"directory":   fmt.Sprintf("%s/.jira.d/templates", home),
		"sort":        defaultSort,
		"max_results": defaultMaxResults,
		"method":      "GET",
		"quiet":       true,
	}

	loadConfigs(opts)
	for k, v := range defaults {
		if _, ok := opts[k]; !ok {
			log.Debug("Setting %q to %#v from defaults", k, v)
			opts[k] = v
		}
	}
	return opts
}

func lastLineDisplayed(ls *ui.List, firstLine int, correction int) int {
	return firstLine + ls.Height - correction
}
<commit_msg>Make a maxWidth of 0 disable wrapping<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/Netflix-Skunkworks/go-jira"
	ui "github.com/gizak/termui"
	"gopkg.in/coryb/yaml.v2"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

func countLabelsFromQuery(query string) map[string]int {
	data, _ := runJiraQuery(query)
	return countLabelsFromQueryData(data)
}

func countLabelsFromQueryData(data interface{}) map[string]int {
	counts := make(map[string]int)
	issues := data.(map[string]interface{})["issues"].([]interface{})
	for _, issue := range issues {
		issueLabels := issue.(map[string]interface{})["fields"].(map[string]interface{})["labels"]
		for _, v := range issueLabels.([]interface{}) {
			label := v.(string)
			counts[label] = counts[label] + 1
		}
	}
	return counts
}

func runJiraCmdEdit(ticketId string) {
	opts := getJiraOpts()
	c := jira.New(opts)
	ui.Close()
	c.CmdEdit(ticketId)
	log.Notice("Regrettably, need to exit after edit. See https://github.com/mikepea/go-jira-ui/issues/8")
	os.Exit(0)
}

func runJiraCmdComment(ticketId string) {
	opts := getJiraOpts()
	c := jira.New(opts)
	ui.Close()
	c.CmdComment(ticketId)
	log.Notice("Regrettably, need to exit after comment. See https://github.com/mikepea/go-jira-ui/issues/8")
	os.Exit(0)
}

func findTicketIdInString(line string) string {
	re := regexp.MustCompile(`\s[A-Z]{3,12}-[0-9]{1,6}`) // no \s at end, need to match BLAH-123[Done]
	return strings.TrimSpace(re.FindString(line))
}

func runJiraQuery(query string) (interface{}, error) {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	return c.FindIssues()
}

func JiraQueryAsStrings(query string) []string {
	opts := getJiraOpts()
	opts["query"] = query
	c := jira.New(opts)
	data, _ := c.FindIssues()
	buf := new(bytes.Buffer)
	template := c.GetTemplate("jira_ui_list")
	if template == "" {
		template = default_list_template
	}
	jira.RunTemplate(template, data, buf)
	return strings.Split(strings.TrimSpace(buf.String()), "\n")
}

func JiraTicketAsStrings(id string, template string) []string {
	opts := getJiraOpts()
	c := jira.New(opts)
	data, _ := c.ViewIssue(id)
	buf := new(bytes.Buffer)
	jira.RunTemplate(c.GetTemplate(template), data, buf)
	return strings.Split(strings.TrimSpace(buf.String()), "\n")
}

func WrapText(lines []string, maxWidth int) []string {
	out := make([]string, 0)
	insideNoformatBlock := false
	insideCodeBlock := false
	for _, line := range lines {
		if matched, _ := regexp.MatchString(`^\s+\{code`, line); matched {
			insideCodeBlock = !insideCodeBlock
		} else if strings.TrimSpace(line) == "{noformat}" {
			insideNoformatBlock = !insideNoformatBlock
		}
		if maxWidth == 0 || len(line) < maxWidth || insideCodeBlock || insideNoformatBlock {
			out = append(out, line)
			continue
		}
		if matched, _ := regexp.MatchString(`^[a-z]+:\s`, line); matched {
			// don't futz with single line field+value.
			// If they are too long, that's their fault.
			out = append(out, line)
			continue
		}
		chars := strings.Split(line, "")
		total := len(chars)
		for i := 0; i < total/maxWidth; i++ {
			start := i * maxWidth
			end := (i + 1) * maxWidth
			out = append(out, strings.Join(chars[start:end], ""))
		}
		if total%maxWidth > 0 {
			start := (total / maxWidth) * maxWidth // integer div :)
			out = append(out, strings.Join(chars[start:], ""))
		}
	}
	return out
}

func parseYaml(file string, v map[string]interface{}) {
	if fh, err := ioutil.ReadFile(file); err == nil {
		log.Debug("Parsing YAML file: %s", file)
		yaml.Unmarshal(fh, &v)
	}
}

func loadConfigs(opts map[string]interface{}) {
	paths := jira.FindParentPaths(".jira.d/jira-ui-config.yml")
	paths = append(jira.FindParentPaths(".jira.d/config.yml"), paths...)
	paths = append([]string{"/etc/go-jira-ui.yml", "/etc/go-jira.yml"}, paths...)

	// iterate paths in reverse
	for i := len(paths) - 1; i >= 0; i-- {
		file := paths[i]
		if _, err := os.Stat(file); err == nil {
			tmp := make(map[string]interface{})
			parseYaml(file, tmp)
			for k, v := range tmp {
				if _, ok := opts[k]; !ok {
					log.Debug("Setting %q to %#v from %s", k, v, file)
					opts[k] = v
				}
			}
		}
	}
}

func doLogin(opts map[string]interface{}) error {
	c := jira.New(opts)
	fmt.Printf("Logging in as %s:\n", opts["user"])
	return c.CmdLogin()
}

func ensureLoggedIntoJira() error {
	homeDir := os.Getenv("HOME")
	opts := getJiraOpts()
	testSessionQuery := fmt.Sprintf("reporter = %s", opts["user"])
	if _, err := os.Stat(fmt.Sprintf("%s/.jira.d/cookies.js", homeDir)); err != nil {
		return doLogin(opts)
	} else if data, err := runJiraQuery(testSessionQuery); err != nil {
		return doLogin(opts)
	} else if val, ok := data.(map[string]interface{})["errorMessages"]; ok {
		if len(val.([]interface{})) > 0 {
			return doLogin(opts)
		}
	}
	return nil
}

func getJiraOpts() map[string]interface{} {
	user := os.Getenv("USER")
	home := os.Getenv("HOME")
	defaultQueryFields := "summary,created,updated,priority,status,reporter,assignee,labels"
	defaultSort := "priority asc, created"
	defaultMaxResults := 1000

	opts := make(map[string]interface{})
	defaults := map[string]interface{}{
		"user":        user,
		"endpoint":    os.Getenv("JIRA_ENDPOINT"),
		"queryfields": defaultQueryFields,
		"directory":   fmt.Sprintf("%s/.jira.d/templates", home),
		"sort":        defaultSort,
		"max_results": defaultMaxResults,
		"method":      "GET",
		"quiet":       true,
	}

	loadConfigs(opts)
	for k, v := range defaults {
		if _, ok := opts[k]; !ok {
			log.Debug("Setting %q to %#v from defaults", k, v)
			opts[k] = v
		}
	}
	return opts
}

func lastLineDisplayed(ls *ui.List, firstLine int, correction int) int {
	return firstLine + ls.Height - correction
}
<|endoftext|>


<commit_before>package gotp

import (
	"fmt"
	"math/rand"
	"net/url"
	"strings"
	"time"
)

const (
	OtpTypeTotp = "totp"
	OtpTypeHotp = "hotp"
)

/*
Returns the provisioning URI for the OTP; works for either TOTP or HOTP.
This can then be encoded in a QR Code and used to provision the Google Authenticator app.
For module-internal use.
See also:
    https://github.com/google/google-authenticator/wiki/Key-Uri-Format

params:
    otpType：     otp type, must in totp/hotp
    secret:       the hotp/totp secret used to generate the URI
    accountName:  name of the account
    issuerName:   the name of the OTP issuer; this will be the organization title of the OTP entry in Authenticator
    algorithm:    the algorithm used in the OTP generation
    initialCount: starting counter value. Only works for hotp
    digits:       the length of the OTP generated code.
    period:       the number of seconds the OTP generator is set to expire every code.

returns: provisioning uri
*/
func BuildUri(otpType, secret, accountName, issuerName, algorithm string, initialCount, digits, period int) string {
	if otpType != OtpTypeHotp && otpType != OtpTypeTotp {
		panic("otp type error, got " + otpType)
	}

	urlParams := make([]string, 0)
	urlParams = append(urlParams, "secret="+secret)
	if otpType == OtpTypeHotp {
		urlParams = append(urlParams, fmt.Sprintf("counter=%d", initialCount))
	}
	label := url.QueryEscape(accountName)
	if issuerName != "" {
		issuerNameEscape := url.QueryEscape(issuerName)
		label = issuerNameEscape + ":" + label
		urlParams = append(urlParams, "issuer="+issuerNameEscape)
	}
	if algorithm != "" && algorithm != "sha1" {
		urlParams = append(urlParams, "algorithm="+strings.ToUpper(algorithm))
	}
	if digits != 0 && digits != 6 {
		urlParams = append(urlParams, fmt.Sprintf("digits=%d", digits))
	}
	if period != 0 && period != 30 {
		urlParams = append(urlParams, fmt.Sprintf("period=%d", period))
	}
	return fmt.Sprintf("otpauth://%s/%s?%s", otpType, label, strings.Join(urlParams, "&"))
}

// get current timestamp
func currentTimestamp() int {
	return int(time.Now().Unix())
}

// integer to byte array
func Itob(integer int) []byte {
	byteArr := make([]byte, 8)
	for i := 7; i >= 0; i-- {
		byteArr[i] = byte(integer & 0xff)
		integer = integer >> 8
	}
	return byteArr
}

func RandomSecret(length int) string {
	rand.Seed(time.Now().UnixNano())
	letterRunes := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")

	bytes := make([]rune, length)

	for i := range bytes {
		bytes[i] = letterRunes[rand.Intn(len(letterRunes))]
	}

	return string(bytes)
}
<commit_msg>RandomSecret comment<commit_after>package gotp

import (
	"fmt"
	"math/rand"
	"net/url"
	"strings"
	"time"
)

const (
	OtpTypeTotp = "totp"
	OtpTypeHotp = "hotp"
)

/*
Returns the provisioning URI for the OTP; works for either TOTP or HOTP.
This can then be encoded in a QR Code and used to provision the Google Authenticator app.
For module-internal use.
See also:
    https://github.com/google/google-authenticator/wiki/Key-Uri-Format

params:
    otpType：     otp type, must in totp/hotp
    secret:       the hotp/totp secret used to generate the URI
    accountName:  name of the account
    issuerName:   the name of the OTP issuer; this will be the organization title of the OTP entry in Authenticator
    algorithm:    the algorithm used in the OTP generation
    initialCount: starting counter value. Only works for hotp
    digits:       the length of the OTP generated code.
    period:       the number of seconds the OTP generator is set to expire every code.

returns: provisioning uri
*/
func BuildUri(otpType, secret, accountName, issuerName, algorithm string, initialCount, digits, period int) string {
	if otpType != OtpTypeHotp && otpType != OtpTypeTotp {
		panic("otp type error, got " + otpType)
	}

	urlParams := make([]string, 0)
	urlParams = append(urlParams, "secret="+secret)
	if otpType == OtpTypeHotp {
		urlParams = append(urlParams, fmt.Sprintf("counter=%d", initialCount))
	}
	label := url.QueryEscape(accountName)
	if issuerName != "" {
		issuerNameEscape := url.QueryEscape(issuerName)
		label = issuerNameEscape + ":" + label
		urlParams = append(urlParams, "issuer="+issuerNameEscape)
	}
	if algorithm != "" && algorithm != "sha1" {
		urlParams = append(urlParams, "algorithm="+strings.ToUpper(algorithm))
	}
	if digits != 0 && digits != 6 {
		urlParams = append(urlParams, fmt.Sprintf("digits=%d", digits))
	}
	if period != 0 && period != 30 {
		urlParams = append(urlParams, fmt.Sprintf("period=%d", period))
	}
	return fmt.Sprintf("otpauth://%s/%s?%s", otpType, label, strings.Join(urlParams, "&"))
}

// get current timestamp
func currentTimestamp() int {
	return int(time.Now().Unix())
}

// integer to byte array
func Itob(integer int) []byte {
	byteArr := make([]byte, 8)
	for i := 7; i >= 0; i-- {
		byteArr[i] = byte(integer & 0xff)
		integer = integer >> 8
	}
	return byteArr
}

// generate a random secret of given length
func RandomSecret(length int) string {
	rand.Seed(time.Now().UnixNano())
	letterRunes := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")

	bytes := make([]rune, length)

	for i := range bytes {
		bytes[i] = letterRunes[rand.Intn(len(letterRunes))]
	}

	return string(bytes)
}
<|endoftext|>


<commit_before>package oauth
<commit_msg>Update<commit_after>package oauth

import "github.com/markbates/goth"
<|endoftext|>


<commit_before>package oauth

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

	"github.com/silenceper/wechat/context"
	"github.com/silenceper/wechat/util"
)

const (
	redirectOauthURL      = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect"
	accessTokenURL        = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
	refreshAccessTokenURL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s"
	userInfoURL           = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN"
	checkAccessTokenURL   = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s"
)

//Oauth 保存用户授权信息
type Oauth struct {
	*context.Context
}

//NewOauth 实例化授权信息
func NewOauth(context *context.Context) *Oauth {
	auth := new(Oauth)
	auth.Context = context
	return auth
}

//GetRedirectURL 获取跳转的url地址
func (oauth *Oauth) GetRedirectURL(redirectURI, scope, state string) (string, error) {
	//url encode
	urlStr := url.QueryEscape(redirectURI)
	return fmt.Sprintf(redirectOauthURL, oauth.AppID, urlStr, scope, state), nil
}

//Redirect 跳转到网页授权
func (oauth *Oauth) Redirect(writer http.ResponseWriter, req *http.Request, redirectURI, scope, state string) error {
	location, err := oauth.GetRedirectURL(redirectURI, scope, state)
	if err != nil {
		return err
	}
	http.Redirect(writer, req, location, 302)
	return nil
}

// ResAccessToken 获取用户授权access_token的返回结果
type ResAccessToken struct {
	util.CommonError

	AccessToken  string `json:"access_token"`
	ExpiresIn    int64  `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	OpenID       string `json:"openid"`
	Scope        string `json:"scope"`
}

// GetUserAccessToken 通过网页授权的code 换取access_token(区别于context中的access_token)
func (oauth *Oauth) GetUserAccessToken(code string) (result ResAccessToken, err error) {
	urlStr := fmt.Sprintf(accessTokenURL, oauth.AppID, oauth.AppSecret, code)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}

//RefreshAccessToken 刷新access_token
func (oauth *Oauth) RefreshAccessToken(refreshToken string) (result ResAccessToken, err error) {
	urlStr := fmt.Sprintf(refreshAccessTokenURL, oauth.AppID, refreshToken)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}

//CheckAccessToken 检验access_token是否有效
func (oauth *Oauth) CheckAccessToken(accessToken, openID string) (b bool, err error) {
	urlStr := fmt.Sprintf(checkAccessTokenURL, accessToken, openID)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	var result util.CommonError
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		b = false
		return
	}
	b = true
	return
}

//UserInfo 用户授权获取到用户信息
type UserInfo struct {
	util.CommonError

	OpenID     string   `json:"openid"`
	Nickname   string   `json:"nickname"`
	Sex        int32    `json:"sex"`
	Province   string   `json:"province"`
	City       string   `json:"city"`
	Country    string   `json:"country"`
	HeadImgURL string   `json:"headimgurl"`
	Privilege  []string `json:"privilege"`
	Unionid    string   `json:"unionid"`
}

//GetUserInfo 如果scope为 snsapi_userinfo 则可以通过此方法获取到用户基本信息
func (oauth *Oauth) GetUserInfo(accessToken, openID string) (result UserInfo, err error) {
	urlStr := fmt.Sprintf(userInfoURL, accessToken, openID)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserInfo error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}
<commit_msg>微信开放平台网页应用获取oauth回调地址<commit_after>package oauth

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

	"github.com/silenceper/wechat/context"
	"github.com/silenceper/wechat/util"
)

const (
	redirectOauthURL       = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect"
	webAppRedirectOauthURL = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect"
	accessTokenURL         = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
	refreshAccessTokenURL  = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s"
	userInfoURL            = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN"
	checkAccessTokenURL    = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s"
)

//Oauth 保存用户授权信息
type Oauth struct {
	*context.Context
}

//NewOauth 实例化授权信息
func NewOauth(context *context.Context) *Oauth {
	auth := new(Oauth)
	auth.Context = context
	return auth
}

//GetRedirectURL 获取跳转的url地址
func (oauth *Oauth) GetRedirectURL(redirectURI, scope, state string) (string, error) {
	//url encode
	urlStr := url.QueryEscape(redirectURI)
	return fmt.Sprintf(redirectOauthURL, oauth.AppID, urlStr, scope, state), nil
}

//GetWebAppRedirectURL 获取网页应用跳转的url地址
func (oauth *Oauth) GetWebAppRedirectURL(redirectURI, scope, state string) (string, error) {
	urlStr := url.QueryEscape(redirectURI)
	return fmt.Sprintf(webAppRedirectOauthURL, oauth.AppID, urlStr, scope, state), nil
}

//Redirect 跳转到网页授权
func (oauth *Oauth) Redirect(writer http.ResponseWriter, req *http.Request, redirectURI, scope, state string) error {
	location, err := oauth.GetRedirectURL(redirectURI, scope, state)
	if err != nil {
		return err
	}
	http.Redirect(writer, req, location, 302)
	return nil
}

// ResAccessToken 获取用户授权access_token的返回结果
type ResAccessToken struct {
	util.CommonError

	AccessToken  string `json:"access_token"`
	ExpiresIn    int64  `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	OpenID       string `json:"openid"`
	Scope        string `json:"scope"`
}

// GetUserAccessToken 通过网页授权的code 换取access_token(区别于context中的access_token)
func (oauth *Oauth) GetUserAccessToken(code string) (result ResAccessToken, err error) {
	urlStr := fmt.Sprintf(accessTokenURL, oauth.AppID, oauth.AppSecret, code)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}

//RefreshAccessToken 刷新access_token
func (oauth *Oauth) RefreshAccessToken(refreshToken string) (result ResAccessToken, err error) {
	urlStr := fmt.Sprintf(refreshAccessTokenURL, oauth.AppID, refreshToken)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}

//CheckAccessToken 检验access_token是否有效
func (oauth *Oauth) CheckAccessToken(accessToken, openID string) (b bool, err error) {
	urlStr := fmt.Sprintf(checkAccessTokenURL, accessToken, openID)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	var result util.CommonError
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		b = false
		return
	}
	b = true
	return
}

//UserInfo 用户授权获取到用户信息
type UserInfo struct {
	util.CommonError

	OpenID     string   `json:"openid"`
	Nickname   string   `json:"nickname"`
	Sex        int32    `json:"sex"`
	Province   string   `json:"province"`
	City       string   `json:"city"`
	Country    string   `json:"country"`
	HeadImgURL string   `json:"headimgurl"`
	Privilege  []string `json:"privilege"`
	Unionid    string   `json:"unionid"`
}

//GetUserInfo 如果scope为 snsapi_userinfo 则可以通过此方法获取到用户基本信息
func (oauth *Oauth) GetUserInfo(accessToken, openID string) (result UserInfo, err error) {
	urlStr := fmt.Sprintf(userInfoURL, accessToken, openID)
	var response []byte
	response, err = util.HTTPGet(urlStr)
	if err != nil {
		return
	}
	err = json.Unmarshal(response, &result)
	if err != nil {
		return
	}
	if result.ErrCode != 0 {
		err = fmt.Errorf("GetUserInfo error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
		return
	}
	return
}
<|endoftext|>


<commit_before>package sphinx

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"errors"
	"io"

	"github.com/roasbeef/btcd/btcec"
)

// onionEncrypt obfuscates the data with compliance with BOLT#4. As we use a
// stream cipher, calling onionEncrypt on an already encrypted piece of data
// will decrypt it.
func onionEncrypt(sharedSecret [sha256.Size]byte, data []byte) []byte {

	p := make([]byte, len(data))

	ammagKey := generateKey("ammag", sharedSecret)
	streamBytes := generateCipherStream(ammagKey, uint(len(data)))
	xor(p, data, streamBytes)

	return p
}

// OnionErrorEncrypter is a struct that's used to implement onion error
// encryption as defined within BOLT0004.
type OnionErrorEncrypter struct {
	sharedSecret [sha256.Size]byte
}

// NewOnionErrorEncrypter creates new instance of the onion encryper backed by
// the passed router, with encryption to be doing using the passed
// ephemeralKey.
func NewOnionErrorEncrypter(router *Router,
	ephemeralKey *btcec.PublicKey) (*OnionErrorEncrypter, error) {

	sharedSecret, err := router.generateSharedSecret(ephemeralKey)
	if err != nil {
		return nil, err
	}

	return &OnionErrorEncrypter{
		sharedSecret: sharedSecret,
	}, nil
}

// EncryptError is used to make data obfuscation using the generated shared
// secret.
//
// In context of Lightning Network is either used by the nodes in order to make
// initial obfuscation with the creation of the hmac or by the forwarding nodes
// for backward failure obfuscation of the onion failure blob. By obfuscating
// the onion failure on every node in the path we are adding additional step of
// the security and barrier for malware nodes to retrieve valuable information.
// The reason for using onion obfuscation is to not give
// away to the nodes in the payment path the information about the exact
// failure and its origin.
func (o *OnionErrorEncrypter) EncryptError(initial bool, data []byte) []byte {
	if initial {
		umKey := generateKey("um", o.sharedSecret)
		hash := hmac.New(sha256.New, umKey[:])
		hash.Write(data)
		h := hash.Sum(nil)
		data = append(h, data...)
	}

	return onionEncrypt(o.sharedSecret, data)
}

// Circuit is used encapsulate the data which is needed for data deobfuscation.
type Circuit struct {
	// SessionKey is the key which have been used during generation of the
	// shared secrets.
	SessionKey *btcec.PrivateKey

	// PaymentPath is the pub keys of the nodes in the payment path.
	PaymentPath []*btcec.PublicKey
}

// Decode initializes the circuit from the byte stream.
func (c *Circuit) Decode(r io.Reader) error {
	var keyLength [1]byte
	if _, err := r.Read(keyLength[:]); err != nil {
		return err
	}

	sessionKeyData := make([]byte, uint8(keyLength[0]))
	if _, err := r.Read(sessionKeyData[:]); err != nil {
		return err
	}

	c.SessionKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sessionKeyData)
	var pathLength [1]byte
	if _, err := r.Read(pathLength[:]); err != nil {
		return err
	}
	c.PaymentPath = make([]*btcec.PublicKey, uint8(pathLength[0]))

	for i := 0; i < len(c.PaymentPath); i++ {
		var pubKeyData [btcec.PubKeyBytesLenCompressed]byte
		if _, err := r.Read(pubKeyData[:]); err != nil {
			return err
		}

		pubKey, err := btcec.ParsePubKey(pubKeyData[:], btcec.S256())
		if err != nil {
			return err
		}
		c.PaymentPath[i] = pubKey
	}

	return nil
}

// Encode writes converted circuit in the byte stream.
func (c *Circuit) Encode(w io.Writer) error {
	var keyLength [1]byte
	keyLength[0] = uint8(len(c.SessionKey.Serialize()))
	if _, err := w.Write(keyLength[:]); err != nil {
		return err
	}

	if _, err := w.Write(c.SessionKey.Serialize()); err != nil {
		return err
	}

	var pathLength [1]byte
	pathLength[0] = uint8(len(c.PaymentPath))
	if _, err := w.Write(pathLength[:]); err != nil {
		return err
	}

	for _, pubKey := range c.PaymentPath {
		if _, err := w.Write(pubKey.SerializeCompressed()); err != nil {
			return err
		}
	}

	return nil
}

// OnionErrorDecrypter is a struct that's used to decrypt onion errors in
// response to failed HTLC routing attempts according to BOLT#4.
type OnionErrorDecrypter struct {
	circuit *Circuit
}

// NewOnionErrorDecrypter creates new instance of onion decrypter.
func NewOnionErrorDecrypter(circuit *Circuit) *OnionErrorDecrypter {
	return &OnionErrorDecrypter{
		circuit: circuit,
	}
}

// DecryptError attempts to decrypt the passed encrypted error response. The
// onion failure is encrypted in backward manner, starting from the node where
// error have occurred. As a result, in order to decrypt the error we need get
// all shared secret and apply decryption in the reverse order.
func (o *OnionErrorDecrypter) DecryptError(encryptedData []byte) (*btcec.PublicKey, []byte, error) {

	sharedSecrets := generateSharedSecrets(
		o.circuit.PaymentPath,
		o.circuit.SessionKey,
	)

	var (
		sender      *btcec.PublicKey
		msg         []byte
		dummySecret [sha256.Size]byte
	)
	copy(dummySecret[:], bytes.Repeat([]byte{1}, 32))

	// We'll iterate a constant amount of hops to ensure that we don't give
	// away an timing information pertaining to the position in the route
	// that the error emanated from.
	for i := 0; i < NumMaxHops; i++ {
		var sharedSecret [sha256.Size]byte

		// If we've already found the sender, then we'll use our dummy
		// secret to continue decryption attempts to fill out the rest
		// of the loop. Otherwise, we'll use the next shared secret in
		// line.
		if sender != nil || i > len(sharedSecrets)-1 {
			sharedSecret = dummySecret
		} else {
			sharedSecret = sharedSecrets[i]
		}

		// With the shared secret, we'll now strip off a layer of
		// encryption from the encrypted error payload.
		encryptedData = onionEncrypt(sharedSecret, encryptedData)

		// Next, we'll need to separate the data, from the MAC itself
		// so we can reconstruct and verify it.
		expectedMac := encryptedData[:sha256.Size]
		data := encryptedData[sha256.Size:]

		// With the data split, we'll now re-generate the MAC using its
		// specified key.
		umKey := generateKey("um", sharedSecret)
		h := hmac.New(sha256.New, umKey[:])
		h.Write(data)

		// If the MAC matches up, then we've found the sender of the
		// error and have also obtained the fully decrypted message.
		realMac := h.Sum(nil)
		if hmac.Equal(realMac, expectedMac) && sender == nil {
			sender = o.circuit.PaymentPath[i]
			msg = data
		}
	}

	// If the sender pointer is still nil, then we haven't found the
	// sender, meaning we've failed to decrypt.
	if sender == nil {
		return nil, nil, errors.New("unable to retrieve onion failure")
	}

	return sender, msg, nil
}
<commit_msg>obfuscation: add encode/decode to onion obfuscator<commit_after>package sphinx

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"errors"
	"io"

	"github.com/roasbeef/btcd/btcec"
)

// onionEncrypt obfuscates the data with compliance with BOLT#4. As we use a
// stream cipher, calling onionEncrypt on an already encrypted piece of data
// will decrypt it.
func onionEncrypt(sharedSecret [sha256.Size]byte, data []byte) []byte {

	p := make([]byte, len(data))

	ammagKey := generateKey("ammag", sharedSecret)
	streamBytes := generateCipherStream(ammagKey, uint(len(data)))
	xor(p, data, streamBytes)

	return p
}

// OnionErrorEncrypter is a struct that's used to implement onion error
// encryption as defined within BOLT0004.
type OnionErrorEncrypter struct {
	sharedSecret [sha256.Size]byte
}

// NewOnionErrorEncrypter creates new instance of the onion encryper backed by
// the passed router, with encryption to be doing using the passed
// ephemeralKey.
func NewOnionErrorEncrypter(router *Router,
	ephemeralKey *btcec.PublicKey) (*OnionErrorEncrypter, error) {

	sharedSecret, err := router.generateSharedSecret(ephemeralKey)
	if err != nil {
		return nil, err
	}

	return &OnionErrorEncrypter{
		sharedSecret: sharedSecret,
	}, nil
}

// EncryptError is used to make data obfuscation using the generated shared
// secret.
//
// In context of Lightning Network is either used by the nodes in order to make
// initial obfuscation with the creation of the hmac or by the forwarding nodes
// for backward failure obfuscation of the onion failure blob. By obfuscating
// the onion failure on every node in the path we are adding additional step of
// the security and barrier for malware nodes to retrieve valuable information.
// The reason for using onion obfuscation is to not give
// away to the nodes in the payment path the information about the exact
// failure and its origin.
func (o *OnionErrorEncrypter) EncryptError(initial bool, data []byte) []byte {
	if initial {
		umKey := generateKey("um", o.sharedSecret)
		hash := hmac.New(sha256.New, umKey[:])
		hash.Write(data)
		h := hash.Sum(nil)
		data = append(h, data...)
	}

	return onionEncrypt(o.sharedSecret, data)
}

// Encode writes the encrypter's shared secret to the provided io.Writer.
func (o *OnionErrorEncrypter) Encode(w io.Writer) error {
	_, err := w.Write(o.sharedSecret[:])
	return err
}

// Decode restores the encrypter's share secret from the provided io.Reader.
func (o *OnionErrorEncrypter) Decode(r io.Reader) error {
	_, err := io.ReadFull(r, o.sharedSecret[:])
	return err
}

// Circuit is used encapsulate the data which is needed for data deobfuscation.
type Circuit struct {
	// SessionKey is the key which have been used during generation of the
	// shared secrets.
	SessionKey *btcec.PrivateKey

	// PaymentPath is the pub keys of the nodes in the payment path.
	PaymentPath []*btcec.PublicKey
}

// Decode initializes the circuit from the byte stream.
func (c *Circuit) Decode(r io.Reader) error {
	var keyLength [1]byte
	if _, err := r.Read(keyLength[:]); err != nil {
		return err
	}

	sessionKeyData := make([]byte, uint8(keyLength[0]))
	if _, err := r.Read(sessionKeyData[:]); err != nil {
		return err
	}

	c.SessionKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sessionKeyData)
	var pathLength [1]byte
	if _, err := r.Read(pathLength[:]); err != nil {
		return err
	}
	c.PaymentPath = make([]*btcec.PublicKey, uint8(pathLength[0]))

	for i := 0; i < len(c.PaymentPath); i++ {
		var pubKeyData [btcec.PubKeyBytesLenCompressed]byte
		if _, err := r.Read(pubKeyData[:]); err != nil {
			return err
		}

		pubKey, err := btcec.ParsePubKey(pubKeyData[:], btcec.S256())
		if err != nil {
			return err
		}
		c.PaymentPath[i] = pubKey
	}

	return nil
}

// Encode writes converted circuit in the byte stream.
func (c *Circuit) Encode(w io.Writer) error {
	var keyLength [1]byte
	keyLength[0] = uint8(len(c.SessionKey.Serialize()))
	if _, err := w.Write(keyLength[:]); err != nil {
		return err
	}

	if _, err := w.Write(c.SessionKey.Serialize()); err != nil {
		return err
	}

	var pathLength [1]byte
	pathLength[0] = uint8(len(c.PaymentPath))
	if _, err := w.Write(pathLength[:]); err != nil {
		return err
	}

	for _, pubKey := range c.PaymentPath {
		if _, err := w.Write(pubKey.SerializeCompressed()); err != nil {
			return err
		}
	}

	return nil
}

// OnionErrorDecrypter is a struct that's used to decrypt onion errors in
// response to failed HTLC routing attempts according to BOLT#4.
type OnionErrorDecrypter struct {
	circuit *Circuit
}

// NewOnionErrorDecrypter creates new instance of onion decrypter.
func NewOnionErrorDecrypter(circuit *Circuit) *OnionErrorDecrypter {
	return &OnionErrorDecrypter{
		circuit: circuit,
	}
}

// DecryptError attempts to decrypt the passed encrypted error response. The
// onion failure is encrypted in backward manner, starting from the node where
// error have occurred. As a result, in order to decrypt the error we need get
// all shared secret and apply decryption in the reverse order.
func (o *OnionErrorDecrypter) DecryptError(encryptedData []byte) (*btcec.PublicKey, []byte, error) {

	sharedSecrets := generateSharedSecrets(
		o.circuit.PaymentPath,
		o.circuit.SessionKey,
	)

	var (
		sender      *btcec.PublicKey
		msg         []byte
		dummySecret [sha256.Size]byte
	)
	copy(dummySecret[:], bytes.Repeat([]byte{1}, 32))

	// We'll iterate a constant amount of hops to ensure that we don't give
	// away an timing information pertaining to the position in the route
	// that the error emanated from.
	for i := 0; i < NumMaxHops; i++ {
		var sharedSecret [sha256.Size]byte

		// If we've already found the sender, then we'll use our dummy
		// secret to continue decryption attempts to fill out the rest
		// of the loop. Otherwise, we'll use the next shared secret in
		// line.
		if sender != nil || i > len(sharedSecrets)-1 {
			sharedSecret = dummySecret
		} else {
			sharedSecret = sharedSecrets[i]
		}

		// With the shared secret, we'll now strip off a layer of
		// encryption from the encrypted error payload.
		encryptedData = onionEncrypt(sharedSecret, encryptedData)

		// Next, we'll need to separate the data, from the MAC itself
		// so we can reconstruct and verify it.
		expectedMac := encryptedData[:sha256.Size]
		data := encryptedData[sha256.Size:]

		// With the data split, we'll now re-generate the MAC using its
		// specified key.
		umKey := generateKey("um", sharedSecret)
		h := hmac.New(sha256.New, umKey[:])
		h.Write(data)

		// If the MAC matches up, then we've found the sender of the
		// error and have also obtained the fully decrypted message.
		realMac := h.Sum(nil)
		if hmac.Equal(realMac, expectedMac) && sender == nil {
			sender = o.circuit.PaymentPath[i]
			msg = data
		}
	}

	// If the sender pointer is still nil, then we haven't found the
	// sender, meaning we've failed to decrypt.
	if sender == nil {
		return nil, nil, errors.New("unable to retrieve onion failure")
	}

	return sender, msg, nil
}
<|endoftext|>


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

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package object

import (
	"context"

	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/task"
	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/progress"
	"github.com/vmware/govmomi/vim25/types"
)

// Task is a convenience wrapper around task.Task that keeps a reference to
// the client that was used to create it. This allows users to call the Wait()
// function with only a context parameter, instead of a context parameter, a
// soap.RoundTripper, and reference to the root property collector.
type Task struct {
	Common
}

func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task {
	t := Task{
		Common: NewCommon(c, ref),
	}

	return &t
}

func (t *Task) Wait(ctx context.Context) error {
	_, err := t.WaitForResult(ctx, nil)
	return err
}

func (t *Task) WaitForResult(ctx context.Context, s ...progress.Sinker) (*types.TaskInfo, error) {
	var pr progress.Sinker
	if len(s) == 1 {
		pr = s[0]
	}
	p := property.DefaultCollector(t.c)
	return task.Wait(ctx, t.Reference(), p, pr)
}

func (t *Task) Cancel(ctx context.Context) error {
	_, err := methods.CancelTask(ctx, t.Client(), &types.CancelTask{
		This: t.Reference(),
	})

	return err
}
<commit_msg>Add SetTaskState SetTaskDescription UpdateProgress to object package<commit_after>/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package object

import (
	"context"

	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/task"
	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/progress"
	"github.com/vmware/govmomi/vim25/types"
)

// Task is a convenience wrapper around task.Task that keeps a reference to
// the client that was used to create it. This allows users to call the Wait()
// function with only a context parameter, instead of a context parameter, a
// soap.RoundTripper, and reference to the root property collector.
type Task struct {
	Common
}

func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task {
	t := Task{
		Common: NewCommon(c, ref),
	}

	return &t
}

func (t *Task) Wait(ctx context.Context) error {
	_, err := t.WaitForResult(ctx, nil)
	return err
}

func (t *Task) WaitForResult(ctx context.Context, s ...progress.Sinker) (*types.TaskInfo, error) {
	var pr progress.Sinker
	if len(s) == 1 {
		pr = s[0]
	}
	p := property.DefaultCollector(t.c)
	return task.Wait(ctx, t.Reference(), p, pr)
}

func (t *Task) Cancel(ctx context.Context) error {
	_, err := methods.CancelTask(ctx, t.Client(), &types.CancelTask{
		This: t.Reference(),
	})

	return err
}

// SetTaskState sets task state and optionally sets results or fault, as appropriate for state.
func (t *Task) SetTaskState(ctx context.Context, state types.TaskInfoState, result types.AnyType, fault *types.LocalizedMethodFault) error {
	req := types.SetTaskState{
		This:   t.Reference(),
		State:  state,
		Result: result,
		Fault:  fault,
	}
	_, err := methods.SetTaskState(ctx, t.Common.Client(), &req)
	return err
}

// SetTaskDescription updates task description to describe the current phase of the task.
func (t *Task) SetTaskDescription(ctx context.Context, description types.LocalizableMessage) error {
	req := types.SetTaskDescription{
		This:        t.Reference(),
		Description: description,
	}
	_, err := methods.SetTaskDescription(ctx, t.Common.Client(), &req)
	return err
}

// UpdateProgress Sets percentage done for this task and recalculates overall percentage done.
// If a percentDone value of less than zero or greater than 100 is specified,
// a value of zero or 100 respectively is used.
func (t *Task) UpdateProgress(ctx context.Context, percentDone int) error {
	req := types.UpdateProgress{
		This:        t.Reference(),
		PercentDone: int32(percentDone),
	}
	_, err := methods.UpdateProgress(ctx, t.Common.Client(), &req)
	return err
}
<|endoftext|>


<commit_before>package extensions

import (
	"archive/tar"
	"compress/gzip"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

func RemoveDirectory(dir string) error {
	d, err := os.Open(dir)
	if err != nil {
		return err
	}
	defer d.Close()
	names, err := d.Readdirnames(-1)
	if err != nil {
		return err
	}
	for _, name := range names {
		err = os.RemoveAll(filepath.Join(dir, name))
		if err != nil {
			return err
		}
	}
	os.Remove(dir)
	return nil
}

func CopyFolder(source string, dest string) (err error) {

	sourceinfo, err := os.Stat(source)
	if err != nil {
		return err
	}

	if dest != "" {
		fmt.Println(dest)

		err = os.MkdirAll(dest, sourceinfo.Mode())
		if err != nil {
			fmt.Println("Failed to create Directory: " + dest + ",  " + err.Error())
			return err
		}
	}

	directory, _ := os.Open(source)

	objects, err := directory.Readdir(-1)

	for _, obj := range objects {

		sourcefilepointer := source + "/" + obj.Name()

		dstFilePath := dest + "/" + obj.Name()
		if dest == "" {
			dstFilePath = obj.Name()
		}

		destinationfilepointer := dstFilePath

		if obj.IsDir() {
			err = CopyFolder(sourcefilepointer, destinationfilepointer)
			if err != nil {
				fmt.Println(err)
			}
		} else {
			err = CopyFile(sourcefilepointer, destinationfilepointer)
			if err != nil {
				fmt.Println(err)
			}
		}

	}
	return
}

func CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if err != nil {
		return err
	}

	defer sourcefile.Close()

	destfile, err := os.Create(dest)
	if err != nil {
		return err
	}

	defer destfile.Close()

	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		sourceinfo, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, sourceinfo.Mode())
		}

	}

	return
}

func WriteAndGoFormat(value string, path string) error {

	err := ioutil.WriteFile(path, []byte(value), 0777)
	if err != nil {
		log.Println("Error writing file " + path + ":  " + err.Error())
		return err
	}

	cmd := exec.Command("gofmt", "-w", path)
	err = cmd.Start()
	if err != nil {
		log.Println("Failed to gofmt on file " + path + ":  " + err.Error())
		return err
	}

	log.Println("Saved file " + path + " successfully.")
	return nil
}

func ReadFile(path string) ([]byte, error) {
	return ioutil.ReadFile(path)
}

func WriteToFile(value string, path string, perm os.FileMode) error {
	err := ioutil.WriteFile(path, []byte(value), perm)
	if err != nil {
		log.Println("Error writing file " + path + ":  " + err.Error())
		return err
	}
	return nil
}

func DoesFileExist(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func DoesFileNotExist(path string) bool {
	if _, err := os.Stat(path); err == nil {
		// path/to/whatever exists
		return false
	}
	return true
}

func MD5(path string) (string, error) {
	hasher := md5.New()

	fileData, err := ReadFile(path)
	if err != nil {
		return "", err
	}

	hasher.Write([]byte(fileData))
	val := hex.EncodeToString(hasher.Sum(nil))

	return val, nil
}

func UnGzipfunc(source, target string) error {
	reader, err := os.Open(source)
	if err != nil {
		return err
	}
	defer reader.Close()

	archive, err := gzip.NewReader(reader)
	if err != nil {
		return err
	}
	defer archive.Close()

	target = filepath.Join(target, archive.Name)
	writer, err := os.Create(target)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = io.Copy(writer, archive)
	return err
}

func GetFileSize(path string) (size int64, err error) {
	file, err := os.Open(path)
	if err != nil {
		return
	}
	fi, err := file.Stat()
	if err != nil {
		return
	}
	size = fi.Size()
	return
}

func UnTar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		if info.IsDir() {
			if err = os.MkdirAll(path, info.Mode()); err != nil {
				return err
			}
			continue
		}

		file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
		if err != nil {
			return err
		}
		defer file.Close()
		_, err = io.Copy(file, tarReader)
		if err != nil {
			return err
		}
	}
	return err
}
<commit_msg>Added 2 new File Extensions.<commit_after>package extensions

import (
	"archive/tar"
	"compress/gzip"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

func RemoveDirectory(dir string) error {
	d, err := os.Open(dir)
	if err != nil {
		return err
	}
	defer d.Close()
	names, err := d.Readdirnames(-1)
	if err != nil {
		return err
	}
	for _, name := range names {
		err = os.RemoveAll(filepath.Join(dir, name))
		if err != nil {
			return err
		}
	}
	os.Remove(dir)
	return nil
}

func CopyFolder(source string, dest string) (err error) {

	sourceinfo, err := os.Stat(source)
	if err != nil {
		return err
	}

	if dest != "" {
		fmt.Println(dest)

		err = os.MkdirAll(dest, sourceinfo.Mode())
		if err != nil {
			fmt.Println("Failed to create Directory: " + dest + ",  " + err.Error())
			return err
		}
	}

	directory, _ := os.Open(source)

	objects, err := directory.Readdir(-1)

	for _, obj := range objects {

		sourcefilepointer := source + "/" + obj.Name()

		dstFilePath := dest + "/" + obj.Name()
		if dest == "" {
			dstFilePath = obj.Name()
		}

		destinationfilepointer := dstFilePath

		if obj.IsDir() {
			err = CopyFolder(sourcefilepointer, destinationfilepointer)
			if err != nil {
				fmt.Println(err)
			}
		} else {
			err = CopyFile(sourcefilepointer, destinationfilepointer)
			if err != nil {
				fmt.Println(err)
			}
		}

	}
	return
}

func CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if err != nil {
		return err
	}

	defer sourcefile.Close()

	destfile, err := os.Create(dest)
	if err != nil {
		return err
	}

	defer destfile.Close()

	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		sourceinfo, err := os.Stat(source)
		if err != nil {
			err = os.Chmod(dest, sourceinfo.Mode())
		}

	}

	return
}

func WriteAndGoFormat(value string, path string) error {

	err := ioutil.WriteFile(path, []byte(value), 0777)
	if err != nil {
		log.Println("Error writing file " + path + ":  " + err.Error())
		return err
	}

	cmd := exec.Command("gofmt", "-w", path)
	err = cmd.Start()
	if err != nil {
		log.Println("Failed to gofmt on file " + path + ":  " + err.Error())
		return err
	}

	log.Println("Saved file " + path + " successfully.")
	return nil
}

func ReadFile(path string) ([]byte, error) {
	return ioutil.ReadFile(path)
}

func ReadFileAndParse(path string, v interface{}) (err error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	err = json.Unmarshal(data, &v)
	return
}

func ParseAndWriteFile(path string, v interface{}, perm os.FileMode) (err error) {
	data, err := json.Marshal(v)
	if err != nil {
		return
	}

	err = WriteToFile(string(data), path, perm)
	return
}

func WriteToFile(value string, path string, perm os.FileMode) error {
	err := ioutil.WriteFile(path, []byte(value), perm)
	if err != nil {
		log.Println("Error writing file " + path + ":  " + err.Error())
		return err
	}
	return nil
}

func DoesFileExist(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func DoesFileNotExist(path string) bool {
	if _, err := os.Stat(path); err == nil {
		// path/to/whatever exists
		return false
	}
	return true
}

func MD5(path string) (string, error) {
	hasher := md5.New()

	fileData, err := ReadFile(path)
	if err != nil {
		return "", err
	}

	hasher.Write([]byte(fileData))
	val := hex.EncodeToString(hasher.Sum(nil))

	return val, nil
}

func UnGzipfunc(source, target string) error {
	reader, err := os.Open(source)
	if err != nil {
		return err
	}
	defer reader.Close()

	archive, err := gzip.NewReader(reader)
	if err != nil {
		return err
	}
	defer archive.Close()

	target = filepath.Join(target, archive.Name)
	writer, err := os.Create(target)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = io.Copy(writer, archive)
	return err
}

func GetFileSize(path string) (size int64, err error) {
	file, err := os.Open(path)
	if err != nil {
		return
	}
	fi, err := file.Stat()
	if err != nil {
		return
	}
	size = fi.Size()
	return
}

func UnTar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		if info.IsDir() {
			if err = os.MkdirAll(path, info.Mode()); err != nil {
				return err
			}
			continue
		}

		file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
		if err != nil {
			return err
		}
		defer file.Close()
		_, err = io.Copy(file, tarReader)
		if err != nil {
			return err
		}
	}
	return err
}
<|endoftext|>


<commit_before>package urlcheck

import (
	"code.google.com/p/go.net/publicsuffix"
	"log"
	"net/http"
	"net/http/cookiejar"
)

type Tester interface {
	Test() error
}

var Timeout uint = 5
var Verbose = false
var Version = "urlcheck/2.0"

var client *http.Client

// Set up a HTTP client with a cookie jar
func init() {
	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}

	jar, err := cookiejar.New(&options)
	if err != nil {
		log.Fatal(err)
	}

	client = &http.Client{
		Jar: jar,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			req.Header.Add("User-Agent", Version)
			return nil
		},
	}
}
<commit_msg>client doesn't have to be a pointer<commit_after>package urlcheck

import (
	"code.google.com/p/go.net/publicsuffix"
	"log"
	"net/http"
	"net/http/cookiejar"
)

type Tester interface {
	Test() error
}

var Timeout uint = 5
var Verbose = false
var Version = "urlcheck/2.0"

var client http.Client

// Set up a HTTP client with a cookie jar
func init() {
	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}

	jar, err := cookiejar.New(&options)
	if err != nil {
		log.Fatal(err)
	}

	client = http.Client{
		Jar: jar,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			req.Header.Add("User-Agent", Version)
			return nil
		},
	}
}
<|endoftext|>