<commit_before>package main

import (
	//"flag"
	"bufio"
	"fmt"

	"github.com/toorop/govh"
	//"github.com/Toorop/govh/ip"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/toqueteos/webbrowser"
	"github.com/wsxiaoys/terminal"
	//"strings"
)

const (
	NL      = "\r\n"
	TAB     = "   "
	NLTAB   = NL + TAB
	VERSION = "2.0"
)

var (
	// ck represents the consumer key
	ck string
	// region represents API region.
	// EU (default) or CA
	region string
)

func init() {
	// region
	region = os.Getenv("OVH_REGION")

	// Consumer key
	ck = os.Getenv("OVH_CONSUMER_KEY")

	// if No ConsumerKey, request one
	if len(ck) == 0 {
		var r []byte

		if runtime.GOOS == "windows" {
			fmt.Println(NL, "No consumer key found in environnement vars !", NL)
		} else {
			terminal.Stdout.Clear().Move(0, 0).Color("r").
				Print("No consumer key found in environnement vars !").Nl().Nl().Reset()
		}
		for {
			fmt.Print("Have you a valid Consumer Key for that app ? (y/n) : ")

			r, _, _ = bufio.NewReader(os.Stdin).ReadLine()
			if r[0] == 110 || r[0] == 121 {
				break
			}
		}
		// Yes
		if r[0] == 121 {
			fmt.Println("\r\nRun the following command :", NL)
			if runtime.GOOS == "windows" {
				fmt.Println("SET OVH_CONSUMER_KEY=your_consumer_key", NL)
			} else {
				fmt.Println("export OVH_CONSUMER_KEY=your_consumer_key", NL)
			}
			fmt.Println("and restart ovh CLI application.", NL)
			os.Exit(0)
		}

		ck, link, err := govh.AuthGetConsumerKey(getAppKey(region), region)
		if err != nil {
			dieError(err)
		}
		fmt.Print("\r\nYour consumer key is : ")
		if runtime.GOOS != "windows" {
			terminal.Stdout.Color("g").Print(ck).Nl().Reset().Nl()
		} else {
			fmt.Print(ck)
		}

		fmt.Println("Now you need to validate it :")
		if runtime.GOOS != "windows" {
			fmt.Printf("\t- If you have a browser available on this machine it will open to the validation page.\n\t- If not, copy and paste the link below in a browser to validate your key :\r\n\r\n%s\r\n", link)
			webbrowser.Open(link)
		} else {
			fmt.Printf("To do it just copy and paste the link below in a browser and follow instructions on OVH website :\r\n\r\n%s\r\n", link)
		}

		fmt.Println("\r\nWhen it will be done run the following command : \r\n")
		if runtime.GOOS == "windows" {
			fmt.Printf("SET OVH_CONSUMER_KEY=%s%s%s", ck, NL, NL)
		} else {
			fmt.Printf("export OVH_CONSUMER_KEY=%s%s%s", ck, NL, NL)
		}
		fmt.Println("and restart ovh CLI application.\r\n")
		os.Exit(0)
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "ovh"
	app.Usage = "ovh-cli brings OVH services to the command line."
	app.Version = VERSION
	app.Author = "Stèphane Depierrepont aka Toorop"
	app.Email = "toorop@toorop.fr"
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

SECTIONS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Description}}
   {{end}}
OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	cli.CommandHelpTemplate = `
   {{.Name}} - {{.Description}}

USAGE:
   {{.Usage}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	cli.SubcommandHelpTemplate = `
   {{.Name}} - {{.Usage}}

SUBS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Description}}
   {{end}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	// New govh client
	client := govh.New(getAppKey(region), getAppSecret(region), ck, region)

	// default action: help
	app.Action = func(c *cli.Context) {
		cli.ShowAppHelp(c)
	}

	// Main  getFwCmds
	app.Commands = []cli.Command{
		{
			Name:        "me",
			Usage:       "me subsection",
			Description: "Commands about me",
			Subcommands: getMeCmds(client),
		},
		{
			Name:        "domain",
			Usage:       "domain subsection",
			Description: "Commands about domains",
			Subcommands: getDomainCmds(client),
		},
		{
			Name:        "ip",
			Usage:       "IP subsection",
			Description: "Commands about IP",
			Subcommands: getIPCmds(client),
		}, {
			Name:        "fw",
			Usage:       "Firewall subsection",
			Description: "Commands OVH firewall",
			//	Subcommands: getFwCmds(client),
		}, {
			Name:        "server",
			Usage:       "Server subsection",
			Description: "Commands about OVH server",
			Subcommands: getServerCmds(client),
		}, {
			Name:        "sms",
			Usage:       "Sms subsection",
			Description: "Commands about OVH SMS",
			Subcommands: getSmsCmds(client),
		}, {
			Name:        "spam",
			Usage:       "Spam subsection",
			Description: "Commands about OVH antispam protection",
			Subcommands: getSpamCmds(client),
		}, {
			Name:        "cloud",
			Usage:       "Cloud subsection",
			Description: "Commands about OVH cloud",
			Subcommands: getCloudCmds(client),
		}, {
			Name:        "dedicatedcloud",
			Usage:       "Dedicated Cloud subsection",
			Description: "Commands about OVH Dedicated Cloud",
			Subcommands: getDedicatedCloudCmds(client),
		},
	}

	app.Run(os.Args)
}
<commit_msg>Spelling fix, resolve #6<commit_after>package main

import (
	//"flag"
	"bufio"
	"fmt"

	"github.com/toorop/govh"
	//"github.com/Toorop/govh/ip"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/toqueteos/webbrowser"
	"github.com/wsxiaoys/terminal"
	//"strings"
)

const (
	NL      = "\r\n"
	TAB     = "   "
	NLTAB   = NL + TAB
	VERSION = "2.0"
)

var (
	// ck represents the consumer key
	ck string
	// region represents API region.
	// EU (default) or CA
	region string
)

func init() {
	// region
	region = os.Getenv("OVH_REGION")

	// Consumer key
	ck = os.Getenv("OVH_CONSUMER_KEY")

	// if No ConsumerKey, request one
	if len(ck) == 0 {
		var r []byte

		if runtime.GOOS == "windows" {
			fmt.Println(NL, "No consumer key found in environment vars !", NL)
		} else {
			terminal.Stdout.Clear().Move(0, 0).Color("r").
				Print("No consumer key found in environment vars !").Nl().Nl().Reset()
		}
		for {
			fmt.Print("Have you a valid Consumer Key for that app ? (y/n) : ")

			r, _, _ = bufio.NewReader(os.Stdin).ReadLine()
			if r[0] == 110 || r[0] == 121 {
				break
			}
		}
		// Yes
		if r[0] == 121 {
			fmt.Println("\r\nRun the following command :", NL)
			if runtime.GOOS == "windows" {
				fmt.Println("SET OVH_CONSUMER_KEY=your_consumer_key", NL)
			} else {
				fmt.Println("export OVH_CONSUMER_KEY=your_consumer_key", NL)
			}
			fmt.Println("and restart ovh CLI application.", NL)
			os.Exit(0)
		}

		ck, link, err := govh.AuthGetConsumerKey(getAppKey(region), region)
		if err != nil {
			dieError(err)
		}
		fmt.Print("\r\nYour consumer key is : ")
		if runtime.GOOS != "windows" {
			terminal.Stdout.Color("g").Print(ck).Nl().Reset().Nl()
		} else {
			fmt.Print(ck)
		}

		fmt.Println("Now you need to validate it :")
		if runtime.GOOS != "windows" {
			fmt.Printf("\t- If you have a browser available on this machine it will open to the validation page.\n\t- If not, copy and paste the link below in a browser to validate your key :\r\n\r\n%s\r\n", link)
			webbrowser.Open(link)
		} else {
			fmt.Printf("To do it just copy and paste the link below in a browser and follow instructions on OVH website :\r\n\r\n%s\r\n", link)
		}

		fmt.Println("\r\nWhen it will be done run the following command : \r\n")
		if runtime.GOOS == "windows" {
			fmt.Printf("SET OVH_CONSUMER_KEY=%s%s%s", ck, NL, NL)
		} else {
			fmt.Printf("export OVH_CONSUMER_KEY=%s%s%s", ck, NL, NL)
		}
		fmt.Println("and restart ovh CLI application.\r\n")
		os.Exit(0)
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "ovh"
	app.Usage = "ovh-cli brings OVH services to the command line."
	app.Version = VERSION
	app.Author = "Stèphane Depierrepont aka Toorop"
	app.Email = "toorop@toorop.fr"
	cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}

SECTIONS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Description}}
   {{end}}
OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	cli.CommandHelpTemplate = `
   {{.Name}} - {{.Description}}

USAGE:
   {{.Usage}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	cli.SubcommandHelpTemplate = `
   {{.Name}} - {{.Usage}}

SUBS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Description}}
   {{end}}

OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}
`

	// New govh client
	client := govh.New(getAppKey(region), getAppSecret(region), ck, region)

	// default action: help
	app.Action = func(c *cli.Context) {
		cli.ShowAppHelp(c)
	}

	// Main  getFwCmds
	app.Commands = []cli.Command{
		{
			Name:        "me",
			Usage:       "me subsection",
			Description: "Commands about me",
			Subcommands: getMeCmds(client),
		},
		{
			Name:        "domain",
			Usage:       "domain subsection",
			Description: "Commands about domains",
			Subcommands: getDomainCmds(client),
		},
		{
			Name:        "ip",
			Usage:       "IP subsection",
			Description: "Commands about IP",
			Subcommands: getIPCmds(client),
		}, {
			Name:        "fw",
			Usage:       "Firewall subsection",
			Description: "Commands OVH firewall",
			//	Subcommands: getFwCmds(client),
		}, {
			Name:        "server",
			Usage:       "Server subsection",
			Description: "Commands about OVH server",
			Subcommands: getServerCmds(client),
		}, {
			Name:        "sms",
			Usage:       "Sms subsection",
			Description: "Commands about OVH SMS",
			Subcommands: getSmsCmds(client),
		}, {
			Name:        "spam",
			Usage:       "Spam subsection",
			Description: "Commands about OVH antispam protection",
			Subcommands: getSpamCmds(client),
		}, {
			Name:        "cloud",
			Usage:       "Cloud subsection",
			Description: "Commands about OVH cloud",
			Subcommands: getCloudCmds(client),
		}, {
			Name:        "dedicatedcloud",
			Usage:       "Dedicated Cloud subsection",
			Description: "Commands about OVH Dedicated Cloud",
			Subcommands: getDedicatedCloudCmds(client),
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "github.com/spf13/cobra"
import "os"
import "github.com/tj/go-debug"
import "github.com/lucsky/cuid"
import "runtime"
import "strings"

func init() {
	pkgCmd := &cobra.Command{
		Use:   "pkg",
		Short: "adds all the current folder to a zip file recursively",
		Run:   pkg,
	}
	flg := pkgCmd.Flags()

	flg.BoolP("verbose", "v", false, "verbosity")
	flg.StringP("output", "o", "", "output file name")

	cmds = append(cmds, pkgCmd)
}

// packages your package up into a zip file
func pkg(c *cobra.Command, _ []string) {
	var err error
	debug := debug.Debug("cmd.pkg")
	var binName string

	if cfg != nil {
		binName = cfg.Pkg.Name
	}

	flagName, _ := c.Flags().GetString("output")
	if flagName != "" {
		binName = flagName
	}

	if binName == "" {
		binName = "lambda-phage-" + cuid.New()
	}

	// add ".zip" to the filename if one is not found
	if strings.Index(binName, ".zip") != (len(binName) - 4) {
		binName += ".zip"
	}

	zFile, err := newZipFile(binName)

	if err != nil {
		zipFileFail(err)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Printf("Error opening directory, %s", wd)
		return
	}

	root, err := os.Open(".")

	if err != nil {
		fmt.Printf("Error opening directory, %s", wd)
		return
	}

	var infoCh chan string
	verbose, _ := c.Flags().GetBool("verbose")
	if verbose {
		infoCh = make(chan string, 1000)
	}

	errCh := make(chan error)

	go func() {
		err := zFile.AddDirectory(root, infoCh)
		if err != nil {
			errCh <- err
			return
		}

		if infoCh != nil {
			close(infoCh)
		}

		close(errCh)
	}()

	for {
		select {
		case i := <-infoCh:
			if i != "" {
				fmt.Println(i)
			}

		case e := <-errCh:
			if e != nil {
				fmt.Println(e)
			}
			debug("errored")
			return
		}
	}

	err = zFile.Close()

}

func zipFileFail(err error) {
	_, f, l, _ := runtime.Caller(1)
	fmt.Printf("[%s:%s]error creating zip file, %s\n", f, l, err.Error())
	return
}
<commit_msg>make pkg return errors so we can reuse that function without splitting apart move filename logic to a function<commit_after>package main

import "fmt"
import "github.com/spf13/cobra"
import "os"
import "github.com/tj/go-debug"
import "github.com/lucsky/cuid"
import "runtime"
import "strings"

func init() {
	pkgCmd := &cobra.Command{
		Use:   "pkg",
		Short: "adds all the current folder to a zip file recursively",
		RunE:  pkg,
	}
	flg := pkgCmd.Flags()

	flg.BoolP("verbose", "v", false, "verbosity")
	flg.StringP("output", "o", "", "output file name")

	cmds = append(cmds, pkgCmd)
}

// packages your package up into a zip file
func pkg(c *cobra.Command, _ []string) error {
	var err error
	debug := debug.Debug("cmd.pkg")

	binName := getArchiveName(c)
	zFile, err := newZipFile(binName)

	if err != nil {
		return zipFileFail(err)
	}

	wd, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("Error opening directory, %s", wd)
	}

	root, err := os.Open(".")

	if err != nil {
		return fmt.Errorf("Error opening directory, %s", wd)
	}

	var infoCh chan string
	verbose, _ := c.Flags().GetBool("verbose")
	if verbose {
		infoCh = make(chan string, 1000)
	}

	errCh := make(chan error)

	go func() {
		err := zFile.AddDirectory(root, infoCh)
		if err != nil {
			errCh <- err
			return
		}

		if infoCh != nil {
			close(infoCh)
		}

		close(errCh)
	}()

	for {
		select {
		case i := <-infoCh:
			if i != "" {
				fmt.Println(i)
			}

		case e := <-errCh:
			if e != nil {
				debug("errored")
				return e
			}
		}
	}

	return zFile.Close()
}

// based on whatever has been passed in, this will determine the
// filename for the archive
func getArchiveName(c *cobra.Command) string {
	var binName string

	if cfg != nil {
		binName = cfg.Pkg.Name
	}

	flagName, _ := c.Flags().GetString("output")
	if flagName != "" {
		binName = flagName
	}

	if binName == "" {
		binName = "lambda-phage-" + cuid.New()
	}

	// add ".zip" to the filename if one is not found
	if strings.Index(binName, ".zip") != (len(binName) - 4) {
		binName += ".zip"
	}

	return binName
}

func zipFileFail(err error) error {
	_, f, l, _ := runtime.Caller(1)
	return fmt.Errorf("[%s:%s]error creating zip file, %s\n", f, l, err.Error())
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"os/exec"
)

type Package struct {
	Dir        string
	Root       string
	ImportPath string
	Deps       []string
	Standard   bool

	Error struct {
		Err string
	}
}

// MustLoadPackages is like LoadPackages but it calls log.Fatal
// if an error occurs.
func MustLoadPackages(name ...string) []*Package {
	p, err := LoadPackages(name...)
	if err != nil {
		log.Fatal(err)
	}
	return p
}

// LoadPackages loads the named packages using go list -json.
// Unlike the go tool, an empty argument list is treated as
// an empty list; "." must be given explicitly if desired.
func LoadPackages(name ...string) (a []*Package, err error) {
	if len(name) == 0 {
		return nil, nil
	}
	args := []string{"list", "-e", "-json"}
	cmd := exec.Command("go", append(args, name...)...)
	r, err := cmd.StdoutPipe()
	if err != nil {
		panic(err)
	}
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		return nil, err
	}
	d := json.NewDecoder(r)
	for {
		info := new(Package)
		err = d.Decode(info)
		if err == io.EOF {
			break
		}
		if err != nil {
			info.Error.Err = err.Error()
		}
		a = append(a, info)
	}
	err = cmd.Wait()
	if err != nil {
		return nil, err
	}
	return a, nil
}
<commit_msg>calm down<commit_after>package main

import (
	"encoding/json"
	"io"
	"log"
	"os"
	"os/exec"
)

type Package struct {
	Dir        string
	Root       string
	ImportPath string
	Deps       []string
	Standard   bool

	Error struct {
		Err string
	}
}

// MustLoadPackages is like LoadPackages but it calls log.Fatal
// if an error occurs.
func MustLoadPackages(name ...string) []*Package {
	p, err := LoadPackages(name...)
	if err != nil {
		log.Fatal(err)
	}
	return p
}

// LoadPackages loads the named packages using go list -json.
// Unlike the go tool, an empty argument list is treated as
// an empty list; "." must be given explicitly if desired.
func LoadPackages(name ...string) (a []*Package, err error) {
	if len(name) == 0 {
		return nil, nil
	}
	args := []string{"list", "-e", "-json"}
	cmd := exec.Command("go", append(args, name...)...)
	r, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	if err != nil {
		return nil, err
	}
	d := json.NewDecoder(r)
	for {
		info := new(Package)
		err = d.Decode(info)
		if err == io.EOF {
			break
		}
		if err != nil {
			info.Error.Err = err.Error()
		}
		a = append(a, info)
	}
	err = cmd.Wait()
	if err != nil {
		return nil, err
	}
	return a, nil
}
<|endoftext|>


<commit_before>package pos

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
)

// https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html
var Descriptions map[string]string = map[string]string{
	"CC":   "Coordinating conjunction",
	"CD":   "Cardinal number",
	"DT":   "Determiner",
	"EX":   "Existential there",
	"FW":   "Foreign word",
	"IN":   "Preposition or subordinating conjunction",
	"JJ":   "Adjective",
	"JJR":  "Adjective, comparative",
	"JJS":  "Adjective, superlative",
	"LS":   "List item marker",
	"MD":   "Modal",
	"NN":   "Noun, singular or mass",
	"NNS":  "Noun, plural",
	"NNP":  "Proper noun, singular",
	"NNPS": "Proper noun, plural",
	"PDT":  "Predeterminer",
	"POS":  "Possessive ending",
	"PRP":  "Personal pronoun",
	"PRP$": "Possessive pronoun",
	"RB":   "Adverb",
	"RBR":  "Adverb, comparative",
	"RBS":  "Adverb, superlative",
	"RP":   "Particle",
	"SYM":  "Symbol",
	"TO":   "to",
	"UH":   "Interjection",
	"VB":   "Verb, base form",
	"VBD":  "Verb, past tense",
	"VBG":  "Verb, gerund or present participle",
	"VBN":  "Verb, past participle",
	"VBP":  "Verb, non-3rd person singular present",
	"VBZ":  "Verb, 3rd person singular present",
	"WDT":  "Wh-determiner",
	"WP":   "Wh-pronoun",
	"WP$":  "Possessive wh-pronoun",
	"WRB":  "Wh-adverb",
}

type POSTagger struct {
	model  string
	tagger string
	java   string
	opts   []string
}

type Result struct {
	Word string
	TAG  string
}

func (r *Result) TAGDescription() string {
	return Descriptions[r.TAG]
}

func NewPOSTagger(m, t string) *POSTagger {
	return &POSTagger{
		model:  m,
		tagger: t,
		java:   "java",
		opts:   []string{"-mx300m"},
	}
}

func (p *POSTagger) SetModel(m string) {
	p.model = m
}

func (p *POSTagger) SetTagger(t string) {
	p.tagger = t
}

func (p *POSTagger) SetJavaPath(j string) {
	p.java = j
}

func (p *POSTagger) SetJavaOpts(opts []string) {
	p.opts = opts
}

func (p *POSTagger) parse(out string) []*Result {
	words := strings.Split(out, " ")

	res := make([]*Result, len(words))
	for i, word := range words {
		split := strings.Split(word, "_")
		res[i] = &Result{
			Word: split[0],
			TAG:  split[1],
		}
	}

	return res
}

func (p *POSTagger) Tag(input string) ([]*Result, error) {
	var (
		tmp  *os.File
		err  error
		args []string
	)

	if tmp, err = ioutil.TempFile("", "nlptemp"); err != nil {
		return nil, err
	}
	defer os.Remove(tmp.Name())
	tmp.WriteString(input)

	args = append(p.opts, []string{
		"-cp",
		p.tagger + ":",
		"edu.stanford.nlp.tagger.maxent.MaxentTagger",
		"-model",
		p.model,
		"-textFile",
		tmp.Name(),
		"-encoding",
		"utf8",
	}...)

	cmd := exec.Command(p.java, args...)

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

	if err = cmd.Run(); err != nil {
		return nil, err
	}

	return p.parse(out.String()), nil
}
<commit_msg>os separator support<commit_after>package pos

import (
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
)

// https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html
var Descriptions map[string]string = map[string]string{
	"CC":   "Coordinating conjunction",
	"CD":   "Cardinal number",
	"DT":   "Determiner",
	"EX":   "Existential there",
	"FW":   "Foreign word",
	"IN":   "Preposition or subordinating conjunction",
	"JJ":   "Adjective",
	"JJR":  "Adjective, comparative",
	"JJS":  "Adjective, superlative",
	"LS":   "List item marker",
	"MD":   "Modal",
	"NN":   "Noun, singular or mass",
	"NNS":  "Noun, plural",
	"NNP":  "Proper noun, singular",
	"NNPS": "Proper noun, plural",
	"PDT":  "Predeterminer",
	"POS":  "Possessive ending",
	"PRP":  "Personal pronoun",
	"PRP$": "Possessive pronoun",
	"RB":   "Adverb",
	"RBR":  "Adverb, comparative",
	"RBS":  "Adverb, superlative",
	"RP":   "Particle",
	"SYM":  "Symbol",
	"TO":   "to",
	"UH":   "Interjection",
	"VB":   "Verb, base form",
	"VBD":  "Verb, past tense",
	"VBG":  "Verb, gerund or present participle",
	"VBN":  "Verb, past participle",
	"VBP":  "Verb, non-3rd person singular present",
	"VBZ":  "Verb, 3rd person singular present",
	"WDT":  "Wh-determiner",
	"WP":   "Wh-pronoun",
	"WP$":  "Possessive wh-pronoun",
	"WRB":  "Wh-adverb",
}

type POSTagger struct {
	model     string
	tagger    string
	java      string
	opts      []string
	separator string
}

type Result struct {
	Word string
	TAG  string
}

func (r *Result) TAGDescription() string {
	return Descriptions[r.TAG]
}

func NewPOSTagger(m, t string) *POSTagger {
	separator := ":"
	if runtime.GOOS == "windows" {
		separator = ";"
	}

	return &POSTagger{
		model:     m,
		tagger:    t,
		java:      "java",
		opts:      []string{"-mx300m"},
		separator: separator,
	}
}

func (p *POSTagger) SetModel(m string) {
	p.model = m
}

func (p *POSTagger) SetTagger(t string) {
	p.tagger = t
}

func (p *POSTagger) SetJavaPath(j string) {
	p.java = j
}

func (p *POSTagger) SetJavaOpts(opts []string) {
	p.opts = opts
}

func (p *POSTagger) parse(out string) []*Result {
	words := strings.Split(out, " ")

	res := make([]*Result, len(words))
	for i, word := range words {
		split := strings.Split(word, "_")
		res[i] = &Result{
			Word: split[0],
			TAG:  split[1],
		}
	}

	return res
}

func (p *POSTagger) Tag(input string) ([]*Result, error) {
	var (
		tmp  *os.File
		err  error
		args []string
	)

	if tmp, err = ioutil.TempFile("", "nlptemp"); err != nil {
		return nil, err
	}
	defer os.Remove(tmp.Name())
	tmp.WriteString(input)

	args = append(p.opts, []string{
		"-cp",
		p.tagger + p.separator,
		"edu.stanford.nlp.tagger.maxent.MaxentTagger",
		"-model",
		p.model,
		"-textFile",
		tmp.Name(),
		"-encoding",
		"utf8",
	}...)

	cmd := exec.Command(p.java, args...)

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

	if err = cmd.Run(); err != nil {
		return nil, err
	}

	return p.parse(out.String()), nil
}
<|endoftext|>


<commit_before>package sudoku

import (
	"math/rand"
)

type blockBlockInteractionTechnique struct {
	*basicSolveTechnique
}

func (self *blockBlockInteractionTechnique) Difficulty() float64 {
	//TODO: think more about how difficult this technique is.
	return self.difficultyHelper(2.5)
}

func (self *blockBlockInteractionTechnique) Find(grid *Grid) []*SolveStep {

	var results []*SolveStep

	pairs := pairwiseBlocks(grid)

	//We're going to be looking at a lot of blocks again and again, so might as well cache this.
	unfilledCellsForBlock := make([]CellList, DIM)
	filledNumsForBlock := make([]IntSlice, DIM)
	for i := 0; i < DIM; i++ {
		unfilledCellsForBlock[i] = grid.Block(i).FilterByHasPossibilities()
		filledNumsForBlock[i] = grid.Block(i).FilledNums()
	}

	//For each pair of blocks (in random order)
	for _, pairIndex := range rand.Perm(len(pairs)) {
		pair := pairs[pairIndex]
		excludeNums := filledNumsForBlock[pair[0]].toIntSet().union(filledNumsForBlock[pair[1]].toIntSet())
		for _, i := range rand.Perm(DIM) {
			//Skip numbers entirely where either of the blocks has a cell with it set, since there obviously
			//won't be any cells in both blocks that have that possibility.
			if _, ok := excludeNums[i]; ok {
				continue
			}
			//Find cells in each block that have that possibility.
			firstBlockCells := unfilledCellsForBlock[pair[0]].FilterByPossible(i)
			secondBlockCells := unfilledCellsForBlock[pair[1]].FilterByPossible(i)

			//Now we need to figure out if these blocks are in the same row or same col
			var majorAxisIsRow bool
			rowOne, colOne, _, _ := grid.blockExtents(pair[0])
			rowTwo, colTwo, _, _ := grid.blockExtents(pair[1])

			if rowOne == rowTwo {
				majorAxisIsRow = true
			} else if colOne == colTwo {
				majorAxisIsRow = false
			} else {
				panic("This shouldn't happen")
			}

			var blockOneIndexes IntSlice
			var blockTwoIndexes IntSlice

			if majorAxisIsRow {
				blockOneIndexes = firstBlockCells.CollectNums(getRow).Unique()
				blockTwoIndexes = secondBlockCells.CollectNums(getRow).Unique()
			} else {
				blockOneIndexes = firstBlockCells.CollectNums(getCol).Unique()
				blockTwoIndexes = secondBlockCells.CollectNums(getCol).Unique()
			}

			if len(blockOneIndexes) != 2 || len(blockTwoIndexes) != 2 {
				//There can only be two rows or columns in play for this technique to work.
				continue
			}

			if !blockOneIndexes.SameContentAs(blockTwoIndexes) {
				//Meh, they didn't line up into the same major axis cells.
				continue
			}

			var targetCells CellList

			if majorAxisIsRow {
				targetCells = grid.Row(blockOneIndexes[0])
				targetCells = append(targetCells, grid.Row(blockOneIndexes[0])...)
				targetCells = targetCells.RemoveCells(grid.Block(pair[0])).RemoveCells(grid.Block(pair[1]))
			} else {
				targetCells = grid.Col(blockOneIndexes[0])
				targetCells = append(targetCells, grid.Col(blockOneIndexes[0])...)
				targetCells = targetCells.RemoveCells(grid.Block(pair[0])).RemoveCells(grid.Block(pair[1]))
			}

			//Okay, we have a possible set. Now we need to create a step.
			step := &SolveStep{
				targetCells,
				append(firstBlockCells, secondBlockCells...),
				[]int{i},
				nil,
				self,
			}

			if step.IsUseful(grid) {
				results = append(results, step)
			}
		}

	}
	return results
}

func (self *blockBlockInteractionTechnique) Description(step *SolveStep) string {
	//TODO: implement and test this.
	return ""
}

//Technically in the future different grids could have different blcok partioning schemes
func pairwiseBlocks(grid *Grid) [][]int {
	//Returns a list of pairs of block IDs, where the blocks are in either the same row or column.

	//TODO: implement this in a way that doesn't generate all of the pairs and cull.
	var result [][]int

	for _, pair := range subsetIndexes(DIM, 2) {
		if len(pair) != 2 {
			return nil
		}
		//Get the upper left cell cooordinates for both blocks.
		rowOne, colOne, _, _ := grid.blockExtents(pair[0])
		rowTwo, colTwo, _, _ := grid.blockExtents(pair[1])
		//Then see if thw coords are the same.
		if rowOne == rowTwo || colOne == colTwo {
			//Found one that's the same, keep it
			result = append(result, pair)

			//Note: we don't have to worry about getting the same blocks back for the front and back of the pair, thanks
			//to how subsetIndexes works.
		}
	}
	return result

}
<commit_msg>Made it so ALL TESTS PASS. I wasn't putting together the right list of target cells (I was duplicating cells).<commit_after>package sudoku

import (
	"math/rand"
)

type blockBlockInteractionTechnique struct {
	*basicSolveTechnique
}

func (self *blockBlockInteractionTechnique) Difficulty() float64 {
	//TODO: think more about how difficult this technique is.
	return self.difficultyHelper(2.5)
}

func (self *blockBlockInteractionTechnique) Find(grid *Grid) []*SolveStep {

	var results []*SolveStep

	pairs := pairwiseBlocks(grid)

	//We're going to be looking at a lot of blocks again and again, so might as well cache this.
	unfilledCellsForBlock := make([]CellList, DIM)
	filledNumsForBlock := make([]IntSlice, DIM)
	for i := 0; i < DIM; i++ {
		unfilledCellsForBlock[i] = grid.Block(i).FilterByHasPossibilities()
		filledNumsForBlock[i] = grid.Block(i).FilledNums()
	}

	//For each pair of blocks (in random order)
	for _, pairIndex := range rand.Perm(len(pairs)) {
		pair := pairs[pairIndex]
		excludeNums := filledNumsForBlock[pair[0]].toIntSet().union(filledNumsForBlock[pair[1]].toIntSet())
		for _, i := range rand.Perm(DIM) {
			//Skip numbers entirely where either of the blocks has a cell with it set, since there obviously
			//won't be any cells in both blocks that have that possibility.
			if _, ok := excludeNums[i]; ok {
				continue
			}
			//Find cells in each block that have that possibility.
			firstBlockCells := unfilledCellsForBlock[pair[0]].FilterByPossible(i)
			secondBlockCells := unfilledCellsForBlock[pair[1]].FilterByPossible(i)

			//Now we need to figure out if these blocks are in the same row or same col
			var majorAxisIsRow bool
			rowOne, colOne, _, _ := grid.blockExtents(pair[0])
			rowTwo, colTwo, _, _ := grid.blockExtents(pair[1])

			if rowOne == rowTwo {
				majorAxisIsRow = true
			} else if colOne == colTwo {
				majorAxisIsRow = false
			} else {
				panic("This shouldn't happen")
			}

			var blockOneIndexes IntSlice
			var blockTwoIndexes IntSlice

			if majorAxisIsRow {
				blockOneIndexes = firstBlockCells.CollectNums(getRow).Unique()
				blockTwoIndexes = secondBlockCells.CollectNums(getRow).Unique()
			} else {
				blockOneIndexes = firstBlockCells.CollectNums(getCol).Unique()
				blockTwoIndexes = secondBlockCells.CollectNums(getCol).Unique()
			}

			if len(blockOneIndexes) != 2 || len(blockTwoIndexes) != 2 {
				//There can only be two rows or columns in play for this technique to work.
				continue
			}

			if !blockOneIndexes.SameContentAs(blockTwoIndexes) {
				//Meh, they didn't line up into the same major axis cells.
				continue
			}

			var targetCells CellList

			if majorAxisIsRow {
				targetCells = grid.Row(blockOneIndexes[0])
				targetCells = append(targetCells, grid.Row(blockOneIndexes[1])...)
				targetCells = targetCells.RemoveCells(grid.Block(pair[0])).RemoveCells(grid.Block(pair[1]))
			} else {
				targetCells = grid.Col(blockOneIndexes[0])
				targetCells = append(targetCells, grid.Col(blockOneIndexes[1])...)
				targetCells = targetCells.RemoveCells(grid.Block(pair[0])).RemoveCells(grid.Block(pair[1]))
			}

			//Okay, we have a possible set. Now we need to create a step.
			step := &SolveStep{
				targetCells,
				append(firstBlockCells, secondBlockCells...),
				[]int{i},
				nil,
				self,
			}

			if step.IsUseful(grid) {
				results = append(results, step)
			}
		}

	}
	return results
}

func (self *blockBlockInteractionTechnique) Description(step *SolveStep) string {
	//TODO: implement and test this.
	return ""
}

//Technically in the future different grids could have different blcok partioning schemes
func pairwiseBlocks(grid *Grid) [][]int {
	//Returns a list of pairs of block IDs, where the blocks are in either the same row or column.

	//TODO: implement this in a way that doesn't generate all of the pairs and cull.
	var result [][]int

	for _, pair := range subsetIndexes(DIM, 2) {
		if len(pair) != 2 {
			return nil
		}
		//Get the upper left cell cooordinates for both blocks.
		rowOne, colOne, _, _ := grid.blockExtents(pair[0])
		rowTwo, colTwo, _, _ := grid.blockExtents(pair[1])
		//Then see if thw coords are the same.
		if rowOne == rowTwo || colOne == colTwo {
			//Found one that's the same, keep it
			result = append(result, pair)

			//Note: we don't have to worry about getting the same blocks back for the front and back of the pair, thanks
			//to how subsetIndexes works.
		}
	}
	return result

}
<|endoftext|>


<commit_before>package httpbackend

import (
	"log"
	"net/http"

	"goji.io/pat"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func mod(next sessionHandlerFunc) sessionHandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, session *models.HTTPSession) {
		log.Println(session)
		channel := pat.Param(r, "channel")
		if channel == "" {
			http.Error(w, "Сhannel variable is not defined", http.StatusUnprocessableEntity)
			return
		}
		channelInfo, error := repos.GetChannelInfo(&channel)
		if error != nil {
			log.Println(error)
			http.Error(w, "That channel is not defined", http.StatusForbidden)
			return
		}
		if channelInfo.GetIfUserIsMod(&session.Username) == true {
			next(w, r, session)
		} else {
			http.Error(w, "You're not moderator", http.StatusForbidden)
			return
		}
	}
}

func withMod(next sessionHandlerFunc) http.HandlerFunc {
	return withAuth(mod(next))
}
<commit_msg>debugging mods middleware<commit_after>package httpbackend

import (
	"log"
	"net/http"

	"goji.io/pat"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func mod(next sessionHandlerFunc) sessionHandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, session *models.HTTPSession) {
		log.Println(session)
		channel := pat.Param(r, "channel")
		if channel == "" {
			http.Error(w, "Сhannel variable is not defined", http.StatusUnprocessableEntity)
			return
		}
		channelInfo, error := repos.GetChannelInfo(&channel)
		log.Println(channelInfo)
		if error != nil {
			log.Println(error)
			http.Error(w, "That channel is not defined", http.StatusForbidden)
			return
		}
		if channelInfo.GetIfUserIsMod(&session.Username) == true {
			next(w, r, session)
		} else {
			http.Error(w, "You're not moderator", http.StatusForbidden)
			return
		}
	}
}

func withMod(next sessionHandlerFunc) http.HandlerFunc {
	return withAuth(mod(next))
}
<|endoftext|>


<commit_before>package httpclient

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"strconv"
	"testing"
)

const (
	BASE_URL     = "http://httpbin.org/"
	GET_URL      = BASE_URL + "get"
	POST_URL     = BASE_URL + "post"
	REDIRECT_URL = BASE_URL + "redirect-to?url=http://example.com"
)

var (
	params = map[string]interface{}{
		"string": "one",
		"int":    2,
		"number": 3.14,
		"bool":   true,
		"list":   []string{"one", "two", "three"},
		"empty":  []int{},
	}
)

func TestURLWithParams(test *testing.T) {
	test.Log(URLWithParams(GET_URL, params))
}

func TestURLWithPathParams(test *testing.T) {
	test.Log(URLWithPathParams(GET_URL, "another", nil))
	test.Log(URLWithPathParams(GET_URL+"/", "another", nil))
}

func TestGet(test *testing.T) {
	resp, err := Get(GET_URL, nil)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestGetWithParams(test *testing.T) {
	resp, err := Get(GET_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestPostWithParams(test *testing.T) {

	resp, err := Post(POST_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestGetJSON(test *testing.T) {
	resp, err := Get(GET_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		test.Log(resp.Json().Map())
	}
}

func TestClient(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	req := client.Request("GET", "get", nil, nil)
	resp, err := client.Do(req)
	test.Log(err, string(resp.Content()))

	req = client.Request("POST", "post", bytes.NewBuffer([]byte("the body")), nil)
	resp, err = client.Do(req)
	test.Log(err, string(resp.Content()))
}

func TestClientGet(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Get("get", nil, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientPost(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := bytes.NewBuffer([]byte("the body"))

	resp, err := client.Post("post", data, map[string]string{"Content-Type": "text/plain", "Content-Disposition": "attachment;filename=test.txt", "Content-Length": strconv.Itoa(data.Len())})
	test.Log(err, string(resp.Content()))
}

func TestClientUpload(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := []byte("the quick brown fox")

	resp, err := client.UploadFile("POST", "post", "file", "testfile.txt", data, map[string]string{
		"description": "testing file upload",
	}, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientGetRedirect(test *testing.T) {
	client := NewHttpClient(REDIRECT_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Get("", nil, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientHeadRedirect(test *testing.T) {
	client := NewHttpClient(REDIRECT_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Head("", nil, nil)
	location := "<no-location>"
	if resp != nil {
		location = resp.Header.Get("Location")
	}
	test.Log(err, location)
}

func TestRetryAfter(test *testing.T) {
	response := HttpResponse{http.Response{
		Status:        "503 Try Again",
		StatusCode:    503,
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
		Header:        http.Header{},
		ContentLength: 0,
	}}

	response.Header.Set("Retry-After", "42")
	response.Header.Set("X-Extended-Error", "Retry")

	err := response.ResponseError()
	test.Logf("%v\n", err)

	herr, ok := err.(HttpError)
	if !ok {
		test.Fail()
	}

	if herr.Code != 503 {
		test.Fail()
	}

	if herr.RetryAfter == 0 {
		test.Fail()
	}

	test.Log(herr.Header)
}

func TestContentDisposition(test *testing.T) {
	response := HttpResponse{http.Response{
		Status:        "200 OK",
		StatusCode:    200,
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
		Header:        http.Header{
                    "Content-Type": []string{"text/plain"},
                    "Content-Disposition": []string{`form-data; name="field2"; filename="example.txt`},
                },
		ContentLength: 100,
	}}

        ctype, name, filename := response.ContentDisposition()
        test.Log("ctype", ctype, "name", name, "filename", filename)
}

func TestSendRequestGet(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(GET, client.Path("get"))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestGetParams(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(GET, client.Path("get"), Params(params))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestPost(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := bytes.NewBuffer([]byte("the body"))

	resp, err := client.SendRequest(POST, client.Path("post"), Body(data),
		Header(map[string]string{
			"Content-Type":        "text/plain",
			"Content-Disposition": "attachment;filename=test.txt",
		}))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestJson(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(POST, client.Path("post"), JsonBody(params),
		Header(map[string]string{
			"Content-Type":        "text/plain",
			"Content-Disposition": "attachment;filename=test.txt",
		}))
	test.Log(err, string(resp.Content()))
}

func TestCheckStatus(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := CheckStatus(client.SendRequest(GET, client.Path("status/555")))
	test.Log(err, string(resp.Content()))
}
<commit_msg>reformat<commit_after>package httpclient

import (
	"bytes"
	"io/ioutil"
	"net/http"
	"strconv"
	"testing"
)

const (
	BASE_URL     = "http://httpbin.org/"
	GET_URL      = BASE_URL + "get"
	POST_URL     = BASE_URL + "post"
	REDIRECT_URL = BASE_URL + "redirect-to?url=http://example.com"
)

var (
	params = map[string]interface{}{
		"string": "one",
		"int":    2,
		"number": 3.14,
		"bool":   true,
		"list":   []string{"one", "two", "three"},
		"empty":  []int{},
	}
)

func TestURLWithParams(test *testing.T) {
	test.Log(URLWithParams(GET_URL, params))
}

func TestURLWithPathParams(test *testing.T) {
	test.Log(URLWithPathParams(GET_URL, "another", nil))
	test.Log(URLWithPathParams(GET_URL+"/", "another", nil))
}

func TestGet(test *testing.T) {
	resp, err := Get(GET_URL, nil)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestGetWithParams(test *testing.T) {
	resp, err := Get(GET_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestPostWithParams(test *testing.T) {

	resp, err := Post(POST_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		defer resp.Body.Close()
		body, _ := ioutil.ReadAll(resp.Body)
		test.Log(string(body))
	}
}

func TestGetJSON(test *testing.T) {
	resp, err := Get(GET_URL, params)
	if err != nil {
		test.Error(err)
	} else {
		test.Log(resp.Json().Map())
	}
}

func TestClient(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	req := client.Request("GET", "get", nil, nil)
	resp, err := client.Do(req)
	test.Log(err, string(resp.Content()))

	req = client.Request("POST", "post", bytes.NewBuffer([]byte("the body")), nil)
	resp, err = client.Do(req)
	test.Log(err, string(resp.Content()))
}

func TestClientGet(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Get("get", nil, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientPost(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := bytes.NewBuffer([]byte("the body"))

	resp, err := client.Post("post", data, map[string]string{"Content-Type": "text/plain", "Content-Disposition": "attachment;filename=test.txt", "Content-Length": strconv.Itoa(data.Len())})
	test.Log(err, string(resp.Content()))
}

func TestClientUpload(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := []byte("the quick brown fox")

	resp, err := client.UploadFile("POST", "post", "file", "testfile.txt", data, map[string]string{
		"description": "testing file upload",
	}, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientGetRedirect(test *testing.T) {
	client := NewHttpClient(REDIRECT_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Get("", nil, nil)
	test.Log(err, string(resp.Content()))
}

func TestClientHeadRedirect(test *testing.T) {
	client := NewHttpClient(REDIRECT_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.Head("", nil, nil)
	location := "<no-location>"
	if resp != nil {
		location = resp.Header.Get("Location")
	}
	test.Log(err, location)
}

func TestRetryAfter(test *testing.T) {
	response := HttpResponse{http.Response{
		Status:        "503 Try Again",
		StatusCode:    503,
		Proto:         "HTTP/1.1",
		ProtoMajor:    1,
		ProtoMinor:    1,
		Header:        http.Header{},
		ContentLength: 0,
	}}

	response.Header.Set("Retry-After", "42")
	response.Header.Set("X-Extended-Error", "Retry")

	err := response.ResponseError()
	test.Logf("%v\n", err)

	herr, ok := err.(HttpError)
	if !ok {
		test.Fail()
	}

	if herr.Code != 503 {
		test.Fail()
	}

	if herr.RetryAfter == 0 {
		test.Fail()
	}

	test.Log(herr.Header)
}

func TestContentDisposition(test *testing.T) {
	response := HttpResponse{http.Response{
		Status:     "200 OK",
		StatusCode: 200,
		Proto:      "HTTP/1.1",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Header: http.Header{
			"Content-Type":        []string{"text/plain"},
			"Content-Disposition": []string{`form-data; name="field2"; filename="example.txt`},
		},
		ContentLength: 100,
	}}

	ctype, name, filename := response.ContentDisposition()
	test.Log("ctype", ctype, "name", name, "filename", filename)
}

func TestSendRequestGet(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(GET, client.Path("get"))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestGetParams(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(GET, client.Path("get"), Params(params))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestPost(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	data := bytes.NewBuffer([]byte("the body"))

	resp, err := client.SendRequest(POST, client.Path("post"), Body(data),
		Header(map[string]string{
			"Content-Type":        "text/plain",
			"Content-Disposition": "attachment;filename=test.txt",
		}))
	test.Log(err, string(resp.Content()))
}

func TestSendRequestJson(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := client.SendRequest(POST, client.Path("post"), JsonBody(params),
		Header(map[string]string{
			"Content-Type":        "text/plain",
			"Content-Disposition": "attachment;filename=test.txt",
		}))
	test.Log(err, string(resp.Content()))
}

func TestCheckStatus(test *testing.T) {
	client := NewHttpClient(BASE_URL)
	client.UserAgent = "TestClient 0.1"
	client.Verbose = true

	resp, err := CheckStatus(client.SendRequest(GET, client.Path("status/555")))
	test.Log(err, string(resp.Content()))
}
<|endoftext|>


<commit_before>package ndp

import (
	"bytes"
	"net"
	"strings"
	"testing"
)

func TestICMPOptionDNSSearchList(t *testing.T) {
	option := &ICMPOptionDNSSearchList{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeDNSSearchList,
		},
		Lifetime:    10,
		DomainNames: []string{"basement.golang.org."},
	}

	if option.Type() != ICMPOptionTypeDNSSearchList {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeDNSSearchList)
	}

	if option.Len() != 4 {
		t.Errorf("wrong length, %d != 4", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// dnssl option (31), length 32 (4):  lifetime 10s, domain(s): basement.golang.org.
	fixture := []byte{31, 4, 0, 0, 0, 0, 0, 10, 8, 98, 97, 115, 101, 109, 101, 110, 116, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	// check with multiple domain names
	option.DomainNames = []string{"basement.golang.org.", "golang.org."}
	if option.Len() != 6 {
		t.Errorf("wrong length, %d != 6", option.Len())
	}

	marshal, err = option.Marshal()
	if err != nil {
		t.Error(err)
	}

	fixture = []byte{31, 6, 0, 0, 0, 0, 0, 10, 8, 98, 97, 115, 101, 109, 101, 110, 116, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 0, 0, 0, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of \n%v (%d) did not match \n%v (%d)", fixture, len(fixture), marshal, len(marshal))
	}

	descfix := "dnssl option (31), length 48 (6): lifetime 10s, domain(s) basement.golang.org., golang.org."
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionMTU(t *testing.T) {
	option := &ICMPOptionMTU{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeMTU,
		},
		MTU: 1500,
	}

	if option.Type() != ICMPOptionTypeMTU {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeMTU)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// mtu option (5), length 8 (1):  1500
	fixture := []byte{5, 1, 0, 0, 0, 0, 5, 220}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "mtu option (5), length 8 (1): 1500"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionSourceLinkLayerAddress(t *testing.T) {
	var err error
	option := &ICMPOptionSourceLinkLayerAddress{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeSourceLinkLayerAddress,
		},
	}
	option.LinkLayerAddress, err = net.ParseMAC("a1:b2:c3:d4:e6:f7")
	if err != nil {
		t.Error(err)
	}

	if option.Type() != ICMPOptionTypeSourceLinkLayerAddress {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeSourceLinkLayerAddress)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// source link-address option (1), length 8 (1): a1:b2:c3:d4:e6:f7
	fixture := []byte{1, 1, 161, 178, 195, 212, 230, 247}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "source link-layer address option (1), length 8 (1): a1:b2:c3:d4:e6:f7"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionTargetLinkLayerAddress(t *testing.T) {
	var err error
	option := &ICMPOptionTargetLinkLayerAddress{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeTargetLinkLayerAddress,
		},
	}
	option.LinkLayerAddress, err = net.ParseMAC("a1:b2:c3:d4:e6:f7")
	if err != nil {
		t.Error(err)
	}

	if option.Type() != ICMPOptionTypeTargetLinkLayerAddress {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeTargetLinkLayerAddress)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// target link-address option (1), length 8 (1): a1:b2:c3:d4:e6:f7
	fixture := []byte{2, 1, 161, 178, 195, 212, 230, 247}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "target link-layer Address option (2), length 8 (1): a1:b2:c3:d4:e6:f7"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionPrefixInformation(t *testing.T) {
	option := &ICMPOptionPrefixInformation{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypePrefixInformation,
		},
		PrefixLength:      64,
		OnLink:            true,
		Auto:              true,
		ValidLifetime:     2592000,
		PreferredLifetime: 604800,
		Prefix:            net.ParseIP("2a00:1450:400e:802::"),
	}

	if option.Type() != ICMPOptionTypePrefixInformation {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypePrefixInformation)
	}

	if option.Len() != 4 {
		t.Errorf("wrong length, %d != 4", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// prefix info option (3), length 32 (4): 2a00:1450:400e:802::/64, Flags [onlink, auto], valid time 2592000s, pref. time 604800s
	fixture := []byte{3, 4, 64, 192, 0, 39, 141, 0, 0, 9, 58, 128, 0, 0, 0, 0, 42, 0, 20, 80, 64, 14, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "prefix info option (3), length 32 (4): 2a00:1450:400e:802::/64, Flags [onlink auto], valid time 2592000s, pref. time 604800s"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionRecursiveDNSServer(t *testing.T) {
	option := &ICMPOptionRecursiveDNSServer{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeRecursiveDNSServer,
		},
		Lifetime: 300,
		Servers:  []net.IP{net.ParseIP("2001:4860:4860::8844")},
	}

	if option.Type() != ICMPOptionTypeRecursiveDNSServer {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeRecursiveDNSServer)
	}

	if option.Len() != 3 {
		t.Errorf("wrong length, %d != 3", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// rdnss option (25), length 40 (5):  lifetime 300s, addr: 2001:4860:4860::8844
	fixture := []byte{25, 3, 0, 0, 0, 0, 1, 44, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 68}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "rdnss option (25), length 24 (3): lifetime 300s, addr: 2001:4860:4860::8844"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}

	// check with multiple nameserver IPs
	option.Servers = []net.IP{net.ParseIP("2001:4860:4860::8844"), net.ParseIP("2001:4860:4860::8888")}

	if option.Len() != 5 {
		t.Errorf("wrong length, %d != 5", option.Len())
	}

	marshal, err = option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// rdnss option (25), length 40 (5):  lifetime 300s, addr: 2001:4860:4860::8844 addr: 2001:4860:4860::8888
	fixture = []byte{25, 5, 0, 0, 0, 0, 1, 44, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 68, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix = "rdnss option (25), length 40 (5): lifetime 300s, addr: 2001:4860:4860::8844 addr: 2001:4860:4860::8888"
	desc = option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}
<commit_msg>added test for dnssl description<commit_after>package ndp

import (
	"bytes"
	"net"
	"strings"
	"testing"
)

func TestICMPOptionDNSSearchList(t *testing.T) {
	option := &ICMPOptionDNSSearchList{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeDNSSearchList,
		},
		Lifetime:    10,
		DomainNames: []string{"basement.golang.org."},
	}

	if option.Type() != ICMPOptionTypeDNSSearchList {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeDNSSearchList)
	}

	if option.Len() != 4 {
		t.Errorf("wrong length, %d != 4", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// dnssl option (31), length 32 (4):  lifetime 10s, domain(s): basement.golang.org.
	fixture := []byte{31, 4, 0, 0, 0, 0, 0, 10, 8, 98, 97, 115, 101, 109, 101, 110, 116, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "dnssl option (31), length 32 (4): lifetime 10s, domain(s) basement.golang.org."
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}

	// check with multiple domain names
	option.DomainNames = []string{"basement.golang.org.", "golang.org."}
	if option.Len() != 6 {
		t.Errorf("wrong length, %d != 6", option.Len())
	}

	marshal, err = option.Marshal()
	if err != nil {
		t.Error(err)
	}

	fixture = []byte{31, 6, 0, 0, 0, 0, 0, 10, 8, 98, 97, 115, 101, 109, 101, 110, 116, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 6, 103, 111, 108, 97, 110, 103, 3, 111, 114, 103, 0, 0, 0, 0, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of \n%v (%d) did not match \n%v (%d)", fixture, len(fixture), marshal, len(marshal))
	}

	descfix = "dnssl option (31), length 48 (6): lifetime 10s, domain(s) basement.golang.org., golang.org."
	desc = option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionMTU(t *testing.T) {
	option := &ICMPOptionMTU{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeMTU,
		},
		MTU: 1500,
	}

	if option.Type() != ICMPOptionTypeMTU {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeMTU)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// mtu option (5), length 8 (1):  1500
	fixture := []byte{5, 1, 0, 0, 0, 0, 5, 220}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "mtu option (5), length 8 (1): 1500"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionSourceLinkLayerAddress(t *testing.T) {
	var err error
	option := &ICMPOptionSourceLinkLayerAddress{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeSourceLinkLayerAddress,
		},
	}
	option.LinkLayerAddress, err = net.ParseMAC("a1:b2:c3:d4:e6:f7")
	if err != nil {
		t.Error(err)
	}

	if option.Type() != ICMPOptionTypeSourceLinkLayerAddress {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeSourceLinkLayerAddress)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// source link-address option (1), length 8 (1): a1:b2:c3:d4:e6:f7
	fixture := []byte{1, 1, 161, 178, 195, 212, 230, 247}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "source link-layer address option (1), length 8 (1): a1:b2:c3:d4:e6:f7"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionTargetLinkLayerAddress(t *testing.T) {
	var err error
	option := &ICMPOptionTargetLinkLayerAddress{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeTargetLinkLayerAddress,
		},
	}
	option.LinkLayerAddress, err = net.ParseMAC("a1:b2:c3:d4:e6:f7")
	if err != nil {
		t.Error(err)
	}

	if option.Type() != ICMPOptionTypeTargetLinkLayerAddress {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeTargetLinkLayerAddress)
	}

	if option.Len() != 1 {
		t.Errorf("wrong length, %d != 1", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// target link-address option (1), length 8 (1): a1:b2:c3:d4:e6:f7
	fixture := []byte{2, 1, 161, 178, 195, 212, 230, 247}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "target link-layer Address option (2), length 8 (1): a1:b2:c3:d4:e6:f7"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionPrefixInformation(t *testing.T) {
	option := &ICMPOptionPrefixInformation{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypePrefixInformation,
		},
		PrefixLength:      64,
		OnLink:            true,
		Auto:              true,
		ValidLifetime:     2592000,
		PreferredLifetime: 604800,
		Prefix:            net.ParseIP("2a00:1450:400e:802::"),
	}

	if option.Type() != ICMPOptionTypePrefixInformation {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypePrefixInformation)
	}

	if option.Len() != 4 {
		t.Errorf("wrong length, %d != 4", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// prefix info option (3), length 32 (4): 2a00:1450:400e:802::/64, Flags [onlink, auto], valid time 2592000s, pref. time 604800s
	fixture := []byte{3, 4, 64, 192, 0, 39, 141, 0, 0, 9, 58, 128, 0, 0, 0, 0, 42, 0, 20, 80, 64, 14, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "prefix info option (3), length 32 (4): 2a00:1450:400e:802::/64, Flags [onlink auto], valid time 2592000s, pref. time 604800s"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}

func TestICMPOptionRecursiveDNSServer(t *testing.T) {
	option := &ICMPOptionRecursiveDNSServer{
		ICMPOptionBase: &ICMPOptionBase{
			optionType: ICMPOptionTypeRecursiveDNSServer,
		},
		Lifetime: 300,
		Servers:  []net.IP{net.ParseIP("2001:4860:4860::8844")},
	}

	if option.Type() != ICMPOptionTypeRecursiveDNSServer {
		t.Errorf("wrong type: %d instead of %d", option.Type(), ICMPOptionTypeRecursiveDNSServer)
	}

	if option.Len() != 3 {
		t.Errorf("wrong length, %d != 3", option.Len())
	}

	marshal, err := option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// rdnss option (25), length 40 (5):  lifetime 300s, addr: 2001:4860:4860::8844
	fixture := []byte{25, 3, 0, 0, 0, 0, 1, 44, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 68}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix := "rdnss option (25), length 24 (3): lifetime 300s, addr: 2001:4860:4860::8844"
	desc := option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}

	// check with multiple nameserver IPs
	option.Servers = []net.IP{net.ParseIP("2001:4860:4860::8844"), net.ParseIP("2001:4860:4860::8888")}

	if option.Len() != 5 {
		t.Errorf("wrong length, %d != 5", option.Len())
	}

	marshal, err = option.Marshal()
	if err != nil {
		t.Error(err)
	}

	// fixture describes
	// rdnss option (25), length 40 (5):  lifetime 300s, addr: 2001:4860:4860::8844 addr: 2001:4860:4860::8888
	fixture = []byte{25, 5, 0, 0, 0, 0, 1, 44, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 68, 32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136}
	if bytes.Compare(marshal, fixture) != 0 {
		t.Errorf("fixture of %v did not match %v", fixture, marshal)
	}

	descfix = "rdnss option (25), length 40 (5): lifetime 300s, addr: 2001:4860:4860::8844 addr: 2001:4860:4860::8888"
	desc = option.String()
	if strings.Compare(desc, descfix) != 0 {
		t.Errorf("fixture of '%s' did not match '%s'", descfix, desc)
	}
}
<|endoftext|>


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

package ec2

import (
	"fmt"
	"strconv"
	"time"

	"github.com/tsuru/tsuru/iaas"
	"github.com/tsuru/tsuru/log"
	"gopkg.in/amz.v2/aws"
	"gopkg.in/amz.v2/ec2"
)

const (
	defaultRegion = "us-east-1"
)

func init() {
	iaas.RegisterIaasProvider("ec2", NewEC2IaaS())
}

type EC2IaaS struct {
	base iaas.UserDataIaaS
}

func NewEC2IaaS() *EC2IaaS {
	return &EC2IaaS{base: iaas.UserDataIaaS{NamedIaaS: iaas.NamedIaaS{BaseIaaSName: "ec2"}}}
}

func (i *EC2IaaS) createEC2Handler(region aws.Region) (*ec2.EC2, error) {
	keyId, err := i.base.GetConfigString("key-id")
	if err != nil {
		return nil, err
	}
	secretKey, err := i.base.GetConfigString("secret-key")
	if err != nil {
		return nil, err
	}
	auth := aws.Auth{AccessKey: keyId, SecretKey: secretKey}
	return ec2.New(auth, region), nil
}

func (i *EC2IaaS) waitForDnsName(ec2Inst *ec2.EC2, instance *ec2.Instance) (*ec2.Instance, error) {
	t0 := time.Now()
	for instance.DNSName == "" {
		rawWait, _ := i.base.GetConfigString("wait-timeout")
		maxWaitTime, _ := strconv.Atoi(rawWait)
		if maxWaitTime == 0 {
			maxWaitTime = 300
		}
		instId := instance.InstanceId
		if time.Now().Sub(t0) > time.Duration(maxWaitTime)*time.Second {
			return nil, fmt.Errorf("ec2: time out waiting for instance %s to start", instId)
		}
		log.Debugf("ec2: waiting for dnsname for instance %s", instId)
		time.Sleep(500 * time.Millisecond)
		resp, err := ec2Inst.Instances([]string{instance.InstanceId}, ec2.NewFilter())
		if err != nil {
			return nil, err
		}
		if len(resp.Reservations) == 0 || len(resp.Reservations[0].Instances) == 0 {
			return nil, fmt.Errorf("No instances returned")
		}
		instance = &resp.Reservations[0].Instances[0]
	}
	return instance, nil
}

func (i *EC2IaaS) Describe() string {
	return `EC2 IaaS required params:
  image=<image id>         Image AMI ID
  type=<instance type>     Your template uuid

Optional params:
  region=<region>          Chosen region, defaults to us-east-1
  securityGroup=<group>    Chosen security group
  keyName=<key name>       Key name for machine
`
}

func (i *EC2IaaS) Clone(name string) iaas.IaaS {
	clone := *i
	clone.base.IaaSName = name
	return &clone
}

func (i *EC2IaaS) DeleteMachine(m *iaas.Machine) error {
	regionName, ok := m.CreationParams["region"]
	if !ok {
		return fmt.Errorf("region creation param required")
	}
	region, ok := aws.Regions[regionName]
	if !ok {
		return fmt.Errorf("region %q not found", regionName)
	}
	ec2Inst, err := i.createEC2Handler(region)
	if err != nil {
		return err
	}
	_, err = ec2Inst.TerminateInstances([]string{m.Id})
	return err
}

func (i *EC2IaaS) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	if _, ok := params["region"]; !ok {
		params["region"] = defaultRegion
	}
	regionName := params["region"]
	region, ok := aws.Regions[regionName]
	if !ok {
		return nil, fmt.Errorf("region %q not found", regionName)
	}
	imageId, ok := params["image"]
	if !ok {
		return nil, fmt.Errorf("image param required")
	}
	instanceType, ok := params["type"]
	if !ok {
		return nil, fmt.Errorf("type param required")
	}
	optimized, _ := params["ebs-optimized"]
	ebsOptimized, _ := strconv.ParseBool(optimized)
	userData, err := i.base.ReadUserData()
	if err != nil {
		return nil, err
	}
	keyName, _ := params["keyName"]
	options := ec2.RunInstances{
		ImageId:      imageId,
		InstanceType: instanceType,
		UserData:     []byte(userData),
		MinCount:     1,
		MaxCount:     1,
		KeyName:      keyName,
		EBSOptimized: ebsOptimized,
	}
	securityGroup, ok := params["securityGroup"]
	if ok {
		options.SecurityGroups = []ec2.SecurityGroup{
			{Name: securityGroup},
		}
	}
	ec2Inst, err := i.createEC2Handler(region)
	if err != nil {
		return nil, err
	}
	resp, err := ec2Inst.RunInstances(&options)
	if err != nil {
		return nil, err
	}
	if len(resp.Instances) == 0 {
		return nil, fmt.Errorf("no instance created")
	}
	runInst := &resp.Instances[0]
	instance, err := i.waitForDnsName(ec2Inst, runInst)
	if err != nil {
		ec2Inst.TerminateInstances([]string{runInst.InstanceId})
		return nil, err
	}
	machine := iaas.Machine{
		Id:      instance.InstanceId,
		Status:  instance.State.Name,
		Address: instance.DNSName,
	}
	return &machine, nil
}
<commit_msg>iaas/ec2: simplify const declaration<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ec2

import (
	"fmt"
	"strconv"
	"time"

	"github.com/tsuru/tsuru/iaas"
	"github.com/tsuru/tsuru/log"
	"gopkg.in/amz.v2/aws"
	"gopkg.in/amz.v2/ec2"
)

const defaultRegion = "us-east-1"

func init() {
	iaas.RegisterIaasProvider("ec2", NewEC2IaaS())
}

type EC2IaaS struct {
	base iaas.UserDataIaaS
}

func NewEC2IaaS() *EC2IaaS {
	return &EC2IaaS{base: iaas.UserDataIaaS{NamedIaaS: iaas.NamedIaaS{BaseIaaSName: "ec2"}}}
}

func (i *EC2IaaS) createEC2Handler(region aws.Region) (*ec2.EC2, error) {
	keyId, err := i.base.GetConfigString("key-id")
	if err != nil {
		return nil, err
	}
	secretKey, err := i.base.GetConfigString("secret-key")
	if err != nil {
		return nil, err
	}
	auth := aws.Auth{AccessKey: keyId, SecretKey: secretKey}
	return ec2.New(auth, region), nil
}

func (i *EC2IaaS) waitForDnsName(ec2Inst *ec2.EC2, instance *ec2.Instance) (*ec2.Instance, error) {
	t0 := time.Now()
	for instance.DNSName == "" {
		rawWait, _ := i.base.GetConfigString("wait-timeout")
		maxWaitTime, _ := strconv.Atoi(rawWait)
		if maxWaitTime == 0 {
			maxWaitTime = 300
		}
		instId := instance.InstanceId
		if time.Now().Sub(t0) > time.Duration(maxWaitTime)*time.Second {
			return nil, fmt.Errorf("ec2: time out waiting for instance %s to start", instId)
		}
		log.Debugf("ec2: waiting for dnsname for instance %s", instId)
		time.Sleep(500 * time.Millisecond)
		resp, err := ec2Inst.Instances([]string{instance.InstanceId}, ec2.NewFilter())
		if err != nil {
			return nil, err
		}
		if len(resp.Reservations) == 0 || len(resp.Reservations[0].Instances) == 0 {
			return nil, fmt.Errorf("No instances returned")
		}
		instance = &resp.Reservations[0].Instances[0]
	}
	return instance, nil
}

func (i *EC2IaaS) Describe() string {
	return `EC2 IaaS required params:
  image=<image id>         Image AMI ID
  type=<instance type>     Your template uuid

Optional params:
  region=<region>          Chosen region, defaults to us-east-1
  securityGroup=<group>    Chosen security group
  keyName=<key name>       Key name for machine
`
}

func (i *EC2IaaS) Clone(name string) iaas.IaaS {
	clone := *i
	clone.base.IaaSName = name
	return &clone
}

func (i *EC2IaaS) DeleteMachine(m *iaas.Machine) error {
	regionName, ok := m.CreationParams["region"]
	if !ok {
		return fmt.Errorf("region creation param required")
	}
	region, ok := aws.Regions[regionName]
	if !ok {
		return fmt.Errorf("region %q not found", regionName)
	}
	ec2Inst, err := i.createEC2Handler(region)
	if err != nil {
		return err
	}
	_, err = ec2Inst.TerminateInstances([]string{m.Id})
	return err
}

func (i *EC2IaaS) CreateMachine(params map[string]string) (*iaas.Machine, error) {
	if _, ok := params["region"]; !ok {
		params["region"] = defaultRegion
	}
	regionName := params["region"]
	region, ok := aws.Regions[regionName]
	if !ok {
		return nil, fmt.Errorf("region %q not found", regionName)
	}
	imageId, ok := params["image"]
	if !ok {
		return nil, fmt.Errorf("image param required")
	}
	instanceType, ok := params["type"]
	if !ok {
		return nil, fmt.Errorf("type param required")
	}
	optimized, _ := params["ebs-optimized"]
	ebsOptimized, _ := strconv.ParseBool(optimized)
	userData, err := i.base.ReadUserData()
	if err != nil {
		return nil, err
	}
	keyName, _ := params["keyName"]
	options := ec2.RunInstances{
		ImageId:      imageId,
		InstanceType: instanceType,
		UserData:     []byte(userData),
		MinCount:     1,
		MaxCount:     1,
		KeyName:      keyName,
		EBSOptimized: ebsOptimized,
	}
	securityGroup, ok := params["securityGroup"]
	if ok {
		options.SecurityGroups = []ec2.SecurityGroup{
			{Name: securityGroup},
		}
	}
	ec2Inst, err := i.createEC2Handler(region)
	if err != nil {
		return nil, err
	}
	resp, err := ec2Inst.RunInstances(&options)
	if err != nil {
		return nil, err
	}
	if len(resp.Instances) == 0 {
		return nil, fmt.Errorf("no instance created")
	}
	runInst := &resp.Instances[0]
	instance, err := i.waitForDnsName(ec2Inst, runInst)
	if err != nil {
		ec2Inst.TerminateInstances([]string{runInst.InstanceId})
		return nil, err
	}
	machine := iaas.Machine{
		Id:      instance.InstanceId,
		Status:  instance.State.Name,
		Address: instance.DNSName,
	}
	return &machine, nil
}
<|endoftext|>


<commit_before>package iban

import (
	"strconv"

	"github.com/jbub/banking/bban"
)

const (
	// minIbanSize represents minimal length of iban.
	minIbanSize = 15

	// modCheck represents value used in mod check.
	modCheck = 98

	// modValue represents value used in mod check.
	modValue = 97

	// modMax is the maximum value allowed in mod check.
	modMax = 999999999

	// defaultCheckDigit is digit used in digit check.
	defaultCheckDigit = "00"
)

func validateMinLength(value string) error {
	if len(value) < minIbanSize {
		return ErrIbanTooShort
	}
	return nil
}

func validateCountryCode(code string) error {
	for _, r := range code {
		if 'a' <= r && r <= 'z' {
			return ErrCountryCodeNotUpper
		}
		if 'A' > r && r > 'Z' {
			return ErrCountryCodeNotAlpha
		}
	}
	return nil
}

func validateCheckDigit(value string, code string) error {
	calc, err := calculateCheckDigit(value, code)
	if err != nil {
		return err
	}

	if digit := extractCheckDigit(value); digit != calc {
		return ErrInvalidCheckDigit
	}
	return nil
}

func validateBban(bbn string, struc bban.Structure) error {
	if len(bbn) != struc.Length() {
		return ErrInvalidBbanLength
	}

	var offset int
	for _, part := range struc.Parts() {
		if value := bbn[offset : offset+part.Length]; !part.Validate(value) {
			return ErrInvalidBbanPart
		}
		offset += part.Length
	}
	return nil
}

func calculateCheckDigit(value string, code string) (string, error) {
	replaced := replaceCheckDigit(value, code)
	mod, err := calculateMod(replaced, code)
	if err != nil {
		return "", err
	}

	check := modCheck - mod
	if check > 9 {
		return strconv.Itoa(check), nil
	}
	return "0" + strconv.Itoa(check), nil
}

// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Modulo_operation_on_IBAN
func calculateMod(value string, code string) (int, error) {
	var total int
	for _, c := range reformatIban(value, code) {
		n := codepointToNum(int(c))
		if n < 0 || n > 35 {
			return 0, ErrInvalidIbanModulo
		}

		if n > 9 {
			total = total*100 + n
		} else {
			total = total*10 + n
		}

		if total > modMax {
			total %= modValue
		}
	}
	return total % modValue, nil
}

func codepointToNum(c int) int {
	if c >= '0' && c <= '9' {
		return c - '0'
	}
	return c - ('A' - 10)
}

func reformatIban(value string, code string) string {
	return extractBban(value) + code + extractCheckDigit(value)
}

func replaceCheckDigit(value string, code string) string {
	return code + defaultCheckDigit + extractBban(value)
}

func extractCountryCode(value string) string {
	return value[0:2]
}

func extractCheckDigit(value string) string {
	return value[2:4]
}

func extractBban(value string) string {
	return value[4:]
}

func extractBbanPart(value string, struc bban.Structure, entryType bban.EntryType) string {
	bbn := extractBban(value)
	var offset int
	for _, part := range struc.Parts() {
		value := bbn[offset : offset+part.Length]
		if part.EntryType == entryType {
			return value
		}
		offset += part.Length
	}
	return ""
}

func extractBankCode(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.BankCode)
}

func extractBranchCode(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.BranchCode)
}

func extractAccountNumber(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.AccountNumber)
}

func extractNationalCheckDigit(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.NationalCheckDigit)
}

func extractAccountType(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.AccountType)
}

func extractOwnerAccountType(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.OwnerAccountType)
}

func extractIdentificationNumber(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.IdentificationNumber)
}

func extractCurrency(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.Currency)
}
<commit_msg>calculateMod now works on 32 bit systems; for #8 (#9)<commit_after>package iban

import (
	"strconv"

	"github.com/jbub/banking/bban"
)

const (
	// minIbanSize represents minimal length of iban.
	minIbanSize = 15

	// modCheck represents value used in mod check.
	modCheck = 98

	// modValue represents value used in mod check.
	modValue = 97

	// modMax is the maximum value allowed in mod check.
	modMax = 999999999

	// defaultCheckDigit is digit used in digit check.
	defaultCheckDigit = "00"
)

func validateMinLength(value string) error {
	if len(value) < minIbanSize {
		return ErrIbanTooShort
	}
	return nil
}

func validateCountryCode(code string) error {
	for _, r := range code {
		if 'a' <= r && r <= 'z' {
			return ErrCountryCodeNotUpper
		}
		if 'A' > r && r > 'Z' {
			return ErrCountryCodeNotAlpha
		}
	}
	return nil
}

func validateCheckDigit(value string, code string) error {
	calc, err := calculateCheckDigit(value, code)
	if err != nil {
		return err
	}

	if digit := extractCheckDigit(value); digit != calc {
		return ErrInvalidCheckDigit
	}
	return nil
}

func validateBban(bbn string, struc bban.Structure) error {
	if len(bbn) != struc.Length() {
		return ErrInvalidBbanLength
	}

	var offset int
	for _, part := range struc.Parts() {
		if value := bbn[offset : offset+part.Length]; !part.Validate(value) {
			return ErrInvalidBbanPart
		}
		offset += part.Length
	}
	return nil
}

func calculateCheckDigit(value string, code string) (string, error) {
	replaced := replaceCheckDigit(value, code)
	mod, err := calculateMod(replaced, code)
	if err != nil {
		return "", err
	}

	check := modCheck - mod
	if check > 9 {
		return strconv.Itoa(check), nil
	}
	return "0" + strconv.Itoa(check), nil
}

// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Modulo_operation_on_IBAN
func calculateMod(value string, code string) (int, error) {
	var total int64
	for _, c := range reformatIban(value, code) {
		n := int64(codepointToNum(int(c)))
		if n < 0 || n > 35 {
			return 0, ErrInvalidIbanModulo
		}

		if n > 9 {
			total = total*100 + n
		} else {
			total = total*10 + n
		}

		if total > modMax {
			total %= modValue
		}
	}
	return int(total % modValue), nil
}

func codepointToNum(c int) int {
	if c >= '0' && c <= '9' {
		return c - '0'
	}
	return c - ('A' - 10)
}

func reformatIban(value string, code string) string {
	return extractBban(value) + code + extractCheckDigit(value)
}

func replaceCheckDigit(value string, code string) string {
	return code + defaultCheckDigit + extractBban(value)
}

func extractCountryCode(value string) string {
	return value[0:2]
}

func extractCheckDigit(value string) string {
	return value[2:4]
}

func extractBban(value string) string {
	return value[4:]
}

func extractBbanPart(value string, struc bban.Structure, entryType bban.EntryType) string {
	bbn := extractBban(value)
	var offset int
	for _, part := range struc.Parts() {
		value := bbn[offset : offset+part.Length]
		if part.EntryType == entryType {
			return value
		}
		offset += part.Length
	}
	return ""
}

func extractBankCode(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.BankCode)
}

func extractBranchCode(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.BranchCode)
}

func extractAccountNumber(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.AccountNumber)
}

func extractNationalCheckDigit(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.NationalCheckDigit)
}

func extractAccountType(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.AccountType)
}

func extractOwnerAccountType(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.OwnerAccountType)
}

func extractIdentificationNumber(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.IdentificationNumber)
}

func extractCurrency(value string, struc bban.Structure) string {
	return extractBbanPart(value, struc, bban.Currency)
}
<|endoftext|>


<commit_before>package image_resizer

import (
	"appengine"
	"appengine/memcache"
	"appengine/urlfetch"
	"bytes"
	"github.com/nfnt/resize"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"net/http"
	"strconv"

	"blobcache"
)

func init() {
	http.HandleFunc("/", serveHTTP)
}

func serveHTTP(w http.ResponseWriter, r *http.Request) {
	if r.RequestURI == "/favicon.ico" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	c := appengine.NewContext(r)
	imageUrl, width, height, resizeQuality := getImageParams(c, r)
	if len(imageUrl) == 0 || width < 0 || height < 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	img, format := loadImage(c, imageUrl)
	if img == nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	if width > 0 || height > 0 {
		if width == 0 {
			width = height
		} else if height == 0 {
			height = width
		}
		img = resize.Thumbnail(uint(width), uint(height), img, resizeQuality)
	}

	if !sendResponse(w, c, img, format, imageUrl) {
		// w.WriteHeader() is skipped intentionally here, since the response may be already partially created.
		return
	}
}

func sendResponse(w http.ResponseWriter, c appengine.Context, img image.Image, format, imageUrl string) bool {
	h := w.Header()
	switch format {
	case "gif":
		h.Set("Content-Type", "image/gif")
		if err := gif.Encode(w, img, nil); err != nil {
			c.Errorf("Cannot encode gif image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	case "jpeg":
		h.Set("Content-Type", "image/jpeg")
		if err := jpeg.Encode(w, img, nil); err != nil {
			c.Errorf("Cannot encode jpeg image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	case "png":
		h.Set("Content-Type", "image/png")
		if err := png.Encode(w, img); err != nil {
			c.Errorf("Cannot encode png image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	default:
		c.Errorf("Unsupported image format=%v for imageUrl=%v", format, imageUrl)
		return false
	}
	return true
}

func getImageParams(c appengine.Context, r *http.Request) (imageUrl string, width, height int, resizeQuality resize.InterpolationFunction) {
	imageUrl = r.FormValue("imageUrl")
	if len(imageUrl) == 0 {
		c.Errorf("Missing imageUrl request parameter")
		return
	}

	width = getImageDimension(c, r, "width")
	height = getImageDimension(c, r, "height")

	switch r.FormValue("resizeQuality") {
	case "0":
		resizeQuality = resize.NearestNeighbor
	case "1":
		resizeQuality = resize.Bilinear
	case "2":
		resizeQuality = resize.Bicubic
	case "3":
		resizeQuality = resize.MitchellNetravali
	case "4":
		resizeQuality = resize.Lanczos2
	case "5":
		resizeQuality = resize.Lanczos3
	default:
		resizeQuality = resize.Bilinear
	}

	return
}

func getImageDimension(c appengine.Context, r *http.Request, dimension string) int {
	v := r.FormValue(dimension)
	if len(v) == 0 {
		return 0
	}
	n, err := strconv.Atoi(v)
	if err != nil {
		c.Errorf("Cannot parse %s=%v: %v", dimension, v, err)
		return -1
	}
	if n < 0 {
		c.Errorf("%s=%v must be positive", dimension, v)
		return -1
	}
	return n
}

func loadImage(c appengine.Context, imageUrl string) (img image.Image, format string) {
	item, err := blobcache.Get(c, imageUrl)
	if err == nil {
		if img, format, err = image.Decode(bytes.NewReader(item.Value)); err != nil {
			c.Errorf("Cannot parse image with imageUrl=%v obtained from memcache: %v. Fetching the image again from imageUrl", imageUrl, err)
			// return skipped intentionally
		} else {
			return
		}
	}

	client := urlfetch.Client(c)
	resp, err := client.Get(imageUrl)
	if err != nil {
		c.Errorf("Cannot load image from imageUrl=%v: %v", imageUrl, err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		c.Errorf("Unexpected StatusCode=%d returned from imageUrl=%v", resp.StatusCode, imageUrl)
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		c.Errorf("Error when reading image body from imageUrl=%v: %v", imageUrl, err)
		return
	}
	if img, format, err = image.Decode(bytes.NewReader(body)); err != nil {
		c.Errorf("Cannot parse image from imageUrl=%v: %v", imageUrl, err)
		return
	}

	item = &memcache.Item{
		Key:   imageUrl,
		Value: body,
	}
	blobcache.Set(c, item)

	return img, format
}
<commit_msg>Close response body obtained from the client before decoding the image, so the client can be re-used for loading the next image from concurrent requests<commit_after>package image_resizer

import (
	"appengine"
	"appengine/memcache"
	"appengine/urlfetch"
	"bytes"
	"github.com/nfnt/resize"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"net/http"
	"strconv"

	"blobcache"
)

func init() {
	http.HandleFunc("/", serveHTTP)
}

func serveHTTP(w http.ResponseWriter, r *http.Request) {
	if r.RequestURI == "/favicon.ico" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	c := appengine.NewContext(r)
	imageUrl, width, height, resizeQuality := getImageParams(c, r)
	if len(imageUrl) == 0 || width < 0 || height < 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	img, format := loadImage(c, imageUrl)
	if img == nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	if width > 0 || height > 0 {
		if width == 0 {
			width = height
		} else if height == 0 {
			height = width
		}
		img = resize.Thumbnail(uint(width), uint(height), img, resizeQuality)
	}

	if !sendResponse(w, c, img, format, imageUrl) {
		// w.WriteHeader() is skipped intentionally here, since the response may be already partially created.
		return
	}
}

func sendResponse(w http.ResponseWriter, c appengine.Context, img image.Image, format, imageUrl string) bool {
	h := w.Header()
	switch format {
	case "gif":
		h.Set("Content-Type", "image/gif")
		if err := gif.Encode(w, img, nil); err != nil {
			c.Errorf("Cannot encode gif image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	case "jpeg":
		h.Set("Content-Type", "image/jpeg")
		if err := jpeg.Encode(w, img, nil); err != nil {
			c.Errorf("Cannot encode jpeg image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	case "png":
		h.Set("Content-Type", "image/png")
		if err := png.Encode(w, img); err != nil {
			c.Errorf("Cannot encode png image from imageUrl=%v: %v", imageUrl, err)
			return false
		}
	default:
		c.Errorf("Unsupported image format=%v for imageUrl=%v", format, imageUrl)
		return false
	}
	return true
}

func getImageParams(c appengine.Context, r *http.Request) (imageUrl string, width, height int, resizeQuality resize.InterpolationFunction) {
	imageUrl = r.FormValue("imageUrl")
	if len(imageUrl) == 0 {
		c.Errorf("Missing imageUrl request parameter")
		return
	}

	width = getImageDimension(c, r, "width")
	height = getImageDimension(c, r, "height")

	switch r.FormValue("resizeQuality") {
	case "0":
		resizeQuality = resize.NearestNeighbor
	case "1":
		resizeQuality = resize.Bilinear
	case "2":
		resizeQuality = resize.Bicubic
	case "3":
		resizeQuality = resize.MitchellNetravali
	case "4":
		resizeQuality = resize.Lanczos2
	case "5":
		resizeQuality = resize.Lanczos3
	default:
		resizeQuality = resize.Bilinear
	}

	return
}

func getImageDimension(c appengine.Context, r *http.Request, dimension string) int {
	v := r.FormValue(dimension)
	if len(v) == 0 {
		return 0
	}
	n, err := strconv.Atoi(v)
	if err != nil {
		c.Errorf("Cannot parse %s=%v: %v", dimension, v, err)
		return -1
	}
	if n < 0 {
		c.Errorf("%s=%v must be positive", dimension, v)
		return -1
	}
	return n
}

func loadImage(c appengine.Context, imageUrl string) (img image.Image, format string) {
	item, err := blobcache.Get(c, imageUrl)
	if err == nil {
		if img, format, err = image.Decode(bytes.NewReader(item.Value)); err != nil {
			c.Errorf("Cannot parse image with imageUrl=%v obtained from memcache: %v. Fetching the image again from imageUrl", imageUrl, err)
			// return skipped intentionally
		} else {
			return
		}
	}

	blob := getImageBlob(c, imageUrl)
	if blob == nil {
		return
	}

	if img, format, err = image.Decode(bytes.NewReader(blob)); err != nil {
		c.Errorf("Cannot parse image from imageUrl=%v: %v", imageUrl, err)
		return
	}

	item = &memcache.Item{
		Key:   imageUrl,
		Value: blob,
	}
	blobcache.Set(c, item)

	return img, format
}

func getImageBlob(c appengine.Context, imageUrl string) []byte {
	client := urlfetch.Client(c)
	resp, err := client.Get(imageUrl)
	if err != nil {
		c.Errorf("Cannot load image from imageUrl=%v: %v", imageUrl, err)
		return nil
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		c.Errorf("Unexpected StatusCode=%d returned from imageUrl=%v", resp.StatusCode, imageUrl)
		return nil
	}
	blob, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		c.Errorf("Error when reading image body from imageUrl=%v: %v", imageUrl, err)
		return nil
	}
	return blob
}
<|endoftext|>


<commit_before>package controllers

import (
	"chant/app/factory"
	"chant/app/infrastructure"
	"fmt"
	"github.com/revel/revel"
)

type Preview struct {
	*revel.Controller
}

type WebOGDetail struct {
	Title       string
	Description string
	Image       string
}

// さいしょのページレンダリングだけー
func (c Preview) Index(url string) revel.Result {
	// TODO?: session check
	fmt.Println(url)
	client := &infrastructure.MyHttpClient{}
	og, e := factory.CreateOGDetailFromResponse(client.Request(url))
	if e != nil {
		revel.ERROR.Println(e)
	}
	return c.RenderJson(og)
}
<commit_msg>Remove unnecessary log<commit_after>package controllers

import (
	"chant/app/factory"
	"chant/app/infrastructure"
	"fmt"
	"github.com/revel/revel"
)

type Preview struct {
	*revel.Controller
}

type WebOGDetail struct {
	Title       string
	Description string
	Image       string
}

// さいしょのページレンダリングだけー
func (c Preview) Index(url string) revel.Result {
	// TODO?: session check
	// fmt.Println(url)
	client := &infrastructure.MyHttpClient{}
	og, e := factory.CreateOGDetailFromResponse(client.Request(url))
	if e != nil {
		revel.ERROR.Println(e)
	}
	return c.RenderJson(og)
}
<|endoftext|>