<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	buildError error
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.IntFlag{"port,p", 3000, "port for the proxy server"},
		cli.IntFlag{"appPort,a", 3001, "port for the Go web server"},
		cli.StringFlag{"bin,b", "gin-bin", "name of generated binary file"},
		cli.StringFlag{"path,t", ".", "Path to watch files from"},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	port := c.GlobalInt("port")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(".", c.GlobalString("bin"))
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Port:    port,
		ProxyTo: "http://localhost:" + appPort,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	logger.Printf("listening on port %d\n", port)

	shutdown(runner)

	// build right now
	build(builder, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), func(path string) {
		runner.Kill()
		build(builder, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Println("ERROR! Build failed.")
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Println("Build Successful")
		}
		buildError = nil
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" {
				return filepath.SkipDir
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if filepath.Ext(path) == ".go" && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<commit_msg>Fix breaking changes from cli flags<commit_after>package main

import (
	"errors"
	"fmt"

	"github.com/codegangsta/cli"
	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	buildError error
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "port,p",
			Value: 3000,
			Usage: "port for the proxy server",
		},
		cli.IntFlag{
			Name:  "appPort,a",
			Value: 3001,
			Usage: "port for the Go web server",
		},
		cli.StringFlag{
			Name:  "bin,b",
			Value: "gin-bin",
			Usage: "name of generated binary file",
		},
		cli.StringFlag{
			Name:  "path,t",
			Value: ".",
			Usage: "Path to watch files from",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	port := c.GlobalInt("port")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(".", c.GlobalString("bin"))
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Port:    port,
		ProxyTo: "http://localhost:" + appPort,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	logger.Printf("listening on port %d\n", port)

	shutdown(runner)

	// build right now
	build(builder, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), func(path string) {
		runner.Kill()
		build(builder, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Println("ERROR! Build failed.")
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Println("Build Successful")
		}
		buildError = nil
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" {
				return filepath.SkipDir
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if filepath.Ext(path) == ".go" && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"github.com/vokalinteractive/go-loggly"
	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/ec2"
	"launchpad.net/goamz/s3"
	"log"
	"net/http"
	"os"
	"vip/fetch"
	"vip/peer"
	"vip/store"
)

var (
	cache     *groupcache.Group
	peers     peer.CachePool
	storage   store.ImageStore
	authToken string

	httpport *string = flag.String("httpport", "8080", "target port")
)

func listenHttp() {
	log.Printf("Listening on port :%s\n", *httpport)
	cert := os.Getenv("SSL_CERT")
	key := os.Getenv("SSL_KEY")

	port := fmt.Sprintf(":%s", *httpport)

	if cert != "" && key != "" {
		log.Println("Serving via SSL")
		if err := http.ListenAndServeTLS(port, cert, key, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	} else {
		if err := http.ListenAndServe(port, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	}
}

func init() {
	flag.Parse()

	loggly_key := os.Getenv("LOGGLY_KEY")
	if loggly_key != "" {
		log.SetOutput(loggly.New(loggly_key, "vip"))
	}

	r := mux.NewRouter()

	authToken = os.Getenv("AUTH_TOKEN")
	if authToken == "" {
		log.Println("No AUTH_TOKEN parameter provided, uploads are insecure")
	}

	r.Handle("/upload/{bucket_id}", verifyAuth(handleUpload))
	r.HandleFunc("/{bucket_id}/{image_id}", handleImageRequest)
	r.HandleFunc("/ping", handlePing)
	http.Handle("/", r)
}

func main() {
	awsAuth, err := aws.EnvAuth()
	if err != nil {
		log.Fatalf(err.Error())
	}

	s3conn := s3.New(awsAuth, aws.USEast)
	storage = store.NewS3Store(s3conn)

	if os.Getenv("DEBUG") == "True" {
		peers = peer.DebugPool()
	} else {
		peers = peer.Pool(ec2.New(awsAuth, aws.USEast))
	}

	peers.SetContext(func(r *http.Request) groupcache.Context {
		return fetch.RequestContext(r)
	})

	cache = groupcache.NewGroup("ImageProxyCache", 64<<20, groupcache.GetterFunc(
		func(c groupcache.Context, key string, dest groupcache.Sink) error {
			log.Printf("Cache MISS for key -> %s", key)
			// Get image data from S3
			b, err := fetch.ImageData(storage, c)
			if err != nil {
				return err
			}

			return dest.SetBytes(b)
		}))

	go peers.Listen()
	go listenHttp()

	log.Println("Cache listening on port :" + peers.Port())
	s := &http.Server{
		Addr:    ":" + peers.Port(),
		Handler: peers,
	}
	s.ListenAndServe()
}
<commit_msg>Make AWS region variable, default to us-east-1<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/golang/groupcache"
	"github.com/gorilla/mux"
	"github.com/vokalinteractive/go-loggly"
	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/ec2"
	"launchpad.net/goamz/s3"
	"log"
	"net/http"
	"os"
	"vip/fetch"
	"vip/peer"
	"vip/store"
)

var (
	cache     *groupcache.Group
	peers     peer.CachePool
	storage   store.ImageStore
	authToken string

	httpport *string = flag.String("httpport", "8080", "target port")
)

func listenHttp() {
	log.Printf("Listening on port :%s\n", *httpport)
	cert := os.Getenv("SSL_CERT")
	key := os.Getenv("SSL_KEY")

	port := fmt.Sprintf(":%s", *httpport)

	if cert != "" && key != "" {
		log.Println("Serving via SSL")
		if err := http.ListenAndServeTLS(port, cert, key, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	} else {
		if err := http.ListenAndServe(port, nil); err != nil {
			log.Fatalf("Error starting server: %s\n", err.Error())
		}
	}
}

func getRegion() aws.Region {
	region := os.Getenv("AWS_REGION")

	switch region {
	case "us-west-1":
		return aws.USWest
	case "us-west-2":
		return aws.USWest2
	case "us-east-1":
		return aws.USEast
	default:
		return aws.USEast
	}
}

func init() {
	flag.Parse()

	loggly_key := os.Getenv("LOGGLY_KEY")
	if loggly_key != "" {
		log.SetOutput(loggly.New(loggly_key, "vip"))
	}

	r := mux.NewRouter()

	authToken = os.Getenv("AUTH_TOKEN")
	if authToken == "" {
		log.Println("No AUTH_TOKEN parameter provided, uploads are insecure")
	}

	r.Handle("/upload/{bucket_id}", verifyAuth(handleUpload))
	r.HandleFunc("/{bucket_id}/{image_id}", handleImageRequest)
	r.HandleFunc("/ping", handlePing)
	http.Handle("/", r)
}

func main() {
	awsAuth, err := aws.EnvAuth()
	if err != nil {
		log.Fatalf(err.Error())
	}

	s3conn := s3.New(awsAuth, getRegion())
	storage = store.NewS3Store(s3conn)

	if os.Getenv("DEBUG") == "True" {
		peers = peer.DebugPool()
	} else {
		peers = peer.Pool(ec2.New(awsAuth, aws.USEast))
	}

	peers.SetContext(func(r *http.Request) groupcache.Context {
		return fetch.RequestContext(r)
	})

	cache = groupcache.NewGroup("ImageProxyCache", 64<<20, groupcache.GetterFunc(
		func(c groupcache.Context, key string, dest groupcache.Sink) error {
			log.Printf("Cache MISS for key -> %s", key)
			// Get image data from S3
			b, err := fetch.ImageData(storage, c)
			if err != nil {
				return err
			}

			return dest.SetBytes(b)
		}))

	go peers.Listen()
	go listenHttp()

	log.Println("Cache listening on port :" + peers.Port())
	s := &http.Server{
		Addr:    ":" + peers.Port(),
		Handler: peers,
	}
	s.ListenAndServe()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"runtime"
	"time"
)

const (
	Version         = "0.1.0"
	multicastAddr   = "225.0.0.1:5000"
	maxDatagramSize = 8192
)

var isLeader bool = false

func main() {
	leaderFlagPtr := flag.Bool("leader", false, "join as leader")
	versionFlagPtr := flag.Bool("version", false, "print version")

	flag.Parse()

	if *versionFlagPtr {
		fmt.Printf("temposyncd version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)
		os.Exit(1)
	}

	isLeader = *leaderFlagPtr

	// Resolve multicast addr
	addr, err := net.ResolveUDPAddr("udp4", multicastAddr)
	if err != nil {
		log.Fatal(err)
	}

	if isLeader {
		log.Println("Joined as leader")

		// Start ticker
		go tickTime(addr)
	} else {
		log.Println("Joined as follower")
	}

	fmt.Println("temposyncd started")
	listenMulticast(addr)
}

func tickTime(addr *net.UDPAddr) {
	c, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		log.Fatal(err)
	}

	t := time.Tick(1000 * time.Millisecond)
	for now := range t {
		log.Printf("TICK %v\n", now)
		c.Write([]byte("hello!\n"))
	}
}

func listenMulticast(addr *net.UDPAddr) {
	l, err := net.ListenMulticastUDP("udp4", nil, addr)
	if err != nil {
		log.Fatal(err)
	}
	l.SetReadBuffer(maxDatagramSize)

	for {
		b := make([]byte, maxDatagramSize)
		n, src, err := l.ReadFromUDP(b)
		if err != nil {
			log.Fatal("ReadFromUDP failed:", err)
		}
		msgHandler(src, n, b)
	}
}

func msgHandler(src *net.UDPAddr, n int, b []byte) {
	log.Println(n, "bytes read from", src)
	log.Println(hex.Dump(b[:n]))
}
<commit_msg>Be quiet by default, add --verbose option<commit_after>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"runtime"
	"time"
)

const (
	Version         = "0.1.0"
	multicastAddr   = "225.0.0.1:5000"
	maxDatagramSize = 8192
)

var isLeader bool = false

func main() {
	leaderFlagPtr := flag.Bool("leader", false, "join as leader")
	versionFlagPtr := flag.Bool("version", false, "print version")
	verboseFlagPtr := flag.Bool("verbose", false, "print debugging information")

	flag.Parse()

	if *versionFlagPtr {
		fmt.Printf("temposyncd version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)
		os.Exit(1)
	}

	if !*verboseFlagPtr {
		log.SetFlags(0)
		log.SetOutput(ioutil.Discard)
	}

	isLeader = *leaderFlagPtr

	// Resolve multicast addr
	addr, err := net.ResolveUDPAddr("udp4", multicastAddr)
	if err != nil {
		log.Fatal("ResolveUDPAddr failed:", err)
	}

	if isLeader {
		log.Println("Joined as leader")

		// Start ticker
		go tickTime(addr)
	} else {
		log.Println("Joined as follower")
	}

	fmt.Println("temposyncd started")
	listenMulticast(addr)
}

func tickTime(addr *net.UDPAddr) {
	c, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		log.Fatal("DialUDP failed:", err)
	}

	t := time.Tick(1000 * time.Millisecond)
	for now := range t {
		log.Printf("TICK %v\n", now)
		c.Write([]byte("hello!\n"))
	}
}

func listenMulticast(addr *net.UDPAddr) {
	l, err := net.ListenMulticastUDP("udp4", nil, addr)
	if err != nil {
		log.Fatal("ListenMulticastUDP failed:", err)
	}
	l.SetReadBuffer(maxDatagramSize)

	for {
		b := make([]byte, maxDatagramSize)
		n, src, err := l.ReadFromUDP(b)
		if err != nil {
			log.Fatal("ReadFromUDP failed:", err)
		}
		msgHandler(src, n, b)
	}
}

func msgHandler(src *net.UDPAddr, n int, b []byte) {
	log.Println(n, "bytes read from", src)
	log.Println(hex.Dump(b[:n]))
}
<|endoftext|>


<commit_before>package main

import (
  "crypto"
  "encoding/base64"
  "fmt"
  "io"
  "io/ioutil"
  "math/big"
  "os"
  "path/filepath"

  "github.com/gibheer/pki"
)

var (
  EmptyByteArray = make([]byte, 0)
)

func main() {
  if len(os.Args) == 1 {
    crash_with_help(1, "No module selected!")
  }
  switch os.Args[1] {
  case "create-private":   create_private_key()
  case "create-public":    create_public_key()
  case "sign-input":       sign_input()
  case "verify-signature": verify_input()
  case "create-cert-sign": create_sign_request()
  case "create-cert":      create_cert()
  case "help":             print_modules()
//  case "info":             info_on_file()
  default: crash_with_help(1, "Command not supported!")
  }
}

// create a private key
func create_private_key() {
  fs := NewFlags("create-private")
  fs.AddOutput()
  fs.AddPrivateKeyGenerationFlags()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  var pk pki.Pemmer
  switch fs.Flags.PrivateKeyGenerationFlags.Type {
    case "ecdsa": pk, err = pki.NewPrivateKeyEcdsa(fs.Flags.PrivateKeyGenerationFlags.Curve)
    case "rsa":   pk, err = pki.NewPrivateKeyRsa(fs.Flags.PrivateKeyGenerationFlags.Size)
  }
  if err != nil { os.Exit(2) }
  marsh_pem, err := pk.MarshalPem()
  if err != nil { os.Exit(2) }
  _, err = marsh_pem.WriteTo(fs.Flags.Output)
  if err != nil { os.Exit(2) }
}

// create a public key derived from a private key
func create_public_key() {
  fs := NewFlags("create-public")
  fs.AddPrivateKey()
  fs.AddOutput()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  var pub_key pki.Pemmer
  pub_key = fs.Flags.PrivateKey.Public()
  marsh_pem, err := pub_key.MarshalPem()
  if err != nil { os.Exit(2) }
  _, err = marsh_pem.WriteTo(fs.Flags.Output)
  if err != nil { os.Exit(2) }
}

// sign a message using he private key
func sign_input() {
  fs := NewFlags("sign-input")
  fs.AddPrivateKey()
  fs.AddInput()
  fs.AddOutput()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  message, err := ioutil.ReadAll(fs.Flags.Input)
  if err != nil { crash_with_help(2, "Error reading input: %s", err) }
  signature, err := fs.Flags.PrivateKey.Sign(message, crypto.SHA256)
  if err != nil { crash_with_help(2, "Could not compute signature: %s", err) }
  _, err = io.WriteString(fs.Flags.Output, base64.StdEncoding.EncodeToString(signature))
  if err != nil { crash_with_help(2, "Could not write to output: %s", err) }

  // if we print to stderr, send a final line break to make the output nice
  if fs.Flags.Output == os.Stdout {
    // we can ignore the result, as either Stdout did work or not
    _, _ = io.WriteString(fs.Flags.Output, "\n")
  }
}

// verify a message using a signature and a public key
func verify_input() {
  fs := NewFlags("sign-input")
  fs.AddPublicKey()
  fs.AddInput()
  fs.AddOutput()
  fs.AddSignature()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  signature := fs.Flags.Signature
  message, err := ioutil.ReadAll(fs.Flags.Input)
  if err != nil { crash_with_help(2, "Error reading input: %s", err) }
  valid, err := fs.Flags.PublicKey.Verify(message, signature, crypto.SHA256)
  if err != nil { crash_with_help(2, "Could not verify message with signature: %s", err) }
  if valid {
    fmt.Println("valid")
    os.Exit(0)
  }
  fmt.Println("invalid")
  os.Exit(1)
}

// create a certificate sign request
func create_sign_request() {
  fs := NewFlags("create-cert-sign")
  fs.AddPrivateKey()
  fs.AddOutput()
  fs.AddCertificateFields()
  fs.Parse(program_args())

  csr, err := fs.Flags.CertificateData.ToCertificateRequest(fs.Flags.PrivateKey)
  if err != nil { crash_with_help(2, "Could not create certificate sign request: %s", err) }
  pem_block, err := csr.MarshalPem()
  if err != nil { crash_with_help(2, "Could not covnert to pem: %s", err) }
  _, err = pem_block.WriteTo(fs.Flags.Output)
  if err != nil { crash_with_help(2, "Encoding didn't work: %s", err) }
}

func create_cert() {
  fs := NewFlags("create-cert")
  fs.AddPrivateKey()
  fs.AddCSR()
  fs.AddOutput()
  fs.Parse(program_args())

  // TODO implement flags for all certificate options
  cert_opts := pki.CertificateOptions{}
  cert_opts.SerialNumber = big.NewInt(1)
  cert, err := fs.Flags.CertificateSignRequest.ToCertificate(
    fs.Flags.PrivateKey,
    cert_opts,
    nil,
  )
  if err != nil { crash_with_help(2, "Error generating certificate: %s", err) }
  pem_block, err := cert.MarshalPem()
  if err != nil { crash_with_help(2, "Error converting to pem: %s", err) }
  _, err = pem_block.WriteTo(fs.Flags.Output)
  if err != nil { crash_with_help(2, "Output didn't work: %s", err) }
}

// print the module help
func print_modules() {
  fmt.Printf(`Usage: %s command args
where 'command' is one of:
    create-private    create a new private key
    create-public     create a public key from a private one
    sign-input        sign a message with a private key
    verify-signature  verify a signature
    create-cert-sign  create a new certificate sign request
    create-cert       sign a certificate request
    help              show this help
    info              get info on a file
`, filepath.Base(os.Args[0]))
  fmt.Println()
}

// crash and provide a helpful message
func crash_with_help(code int, message string, args ...interface{}) {
  fmt.Fprintf(os.Stderr, message + "\n", args...)
  print_modules()
  os.Exit(code)
}

// return the arguments to the program
func program_args() []string {
  return os.Args[2:]
}
<commit_msg>add a --help option to avoid an error message<commit_after>package main

import (
  "crypto"
  "encoding/base64"
  "fmt"
  "io"
  "io/ioutil"
  "math/big"
  "os"
  "path/filepath"

  "github.com/gibheer/pki"
)

var (
  EmptyByteArray = make([]byte, 0)
)

func main() {
  if len(os.Args) == 1 {
    crash_with_help(1, "No module selected!")
  }
  switch os.Args[1] {
  case "create-private":   create_private_key()
  case "create-public":    create_public_key()
  case "sign-input":       sign_input()
  case "verify-signature": verify_input()
  case "create-cert-sign": create_sign_request()
  case "create-cert":      create_cert()
  case "help":             print_modules()
  case "--help":             print_modules()
//  case "info":             info_on_file()
  default: crash_with_help(1, "Command not supported!")
  }
}

// create a private key
func create_private_key() {
  fs := NewFlags("create-private")
  fs.AddOutput()
  fs.AddPrivateKeyGenerationFlags()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  var pk pki.Pemmer
  switch fs.Flags.PrivateKeyGenerationFlags.Type {
    case "ecdsa": pk, err = pki.NewPrivateKeyEcdsa(fs.Flags.PrivateKeyGenerationFlags.Curve)
    case "rsa":   pk, err = pki.NewPrivateKeyRsa(fs.Flags.PrivateKeyGenerationFlags.Size)
  }
  if err != nil { os.Exit(2) }
  marsh_pem, err := pk.MarshalPem()
  if err != nil { os.Exit(2) }
  _, err = marsh_pem.WriteTo(fs.Flags.Output)
  if err != nil { os.Exit(2) }
}

// create a public key derived from a private key
func create_public_key() {
  fs := NewFlags("create-public")
  fs.AddPrivateKey()
  fs.AddOutput()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  var pub_key pki.Pemmer
  pub_key = fs.Flags.PrivateKey.Public()
  marsh_pem, err := pub_key.MarshalPem()
  if err != nil { os.Exit(2) }
  _, err = marsh_pem.WriteTo(fs.Flags.Output)
  if err != nil { os.Exit(2) }
}

// sign a message using he private key
func sign_input() {
  fs := NewFlags("sign-input")
  fs.AddPrivateKey()
  fs.AddInput()
  fs.AddOutput()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  message, err := ioutil.ReadAll(fs.Flags.Input)
  if err != nil { crash_with_help(2, "Error reading input: %s", err) }
  signature, err := fs.Flags.PrivateKey.Sign(message, crypto.SHA256)
  if err != nil { crash_with_help(2, "Could not compute signature: %s", err) }
  _, err = io.WriteString(fs.Flags.Output, base64.StdEncoding.EncodeToString(signature))
  if err != nil { crash_with_help(2, "Could not write to output: %s", err) }

  // if we print to stderr, send a final line break to make the output nice
  if fs.Flags.Output == os.Stdout {
    // we can ignore the result, as either Stdout did work or not
    _, _ = io.WriteString(fs.Flags.Output, "\n")
  }
}

// verify a message using a signature and a public key
func verify_input() {
  fs := NewFlags("sign-input")
  fs.AddPublicKey()
  fs.AddInput()
  fs.AddOutput()
  fs.AddSignature()
  err := fs.Parse(program_args())
  if err != nil { os.Exit(2) }

  signature := fs.Flags.Signature
  message, err := ioutil.ReadAll(fs.Flags.Input)
  if err != nil { crash_with_help(2, "Error reading input: %s", err) }
  valid, err := fs.Flags.PublicKey.Verify(message, signature, crypto.SHA256)
  if err != nil { crash_with_help(2, "Could not verify message with signature: %s", err) }
  if valid {
    fmt.Println("valid")
    os.Exit(0)
  }
  fmt.Println("invalid")
  os.Exit(1)
}

// create a certificate sign request
func create_sign_request() {
  fs := NewFlags("create-cert-sign")
  fs.AddPrivateKey()
  fs.AddOutput()
  fs.AddCertificateFields()
  fs.Parse(program_args())

  csr, err := fs.Flags.CertificateData.ToCertificateRequest(fs.Flags.PrivateKey)
  if err != nil { crash_with_help(2, "Could not create certificate sign request: %s", err) }
  pem_block, err := csr.MarshalPem()
  if err != nil { crash_with_help(2, "Could not covnert to pem: %s", err) }
  _, err = pem_block.WriteTo(fs.Flags.Output)
  if err != nil { crash_with_help(2, "Encoding didn't work: %s", err) }
}

func create_cert() {
  fs := NewFlags("create-cert")
  fs.AddPrivateKey()
  fs.AddCSR()
  fs.AddOutput()
  fs.Parse(program_args())

  // TODO implement flags for all certificate options
  cert_opts := pki.CertificateOptions{}
  cert_opts.SerialNumber = big.NewInt(1)
  cert, err := fs.Flags.CertificateSignRequest.ToCertificate(
    fs.Flags.PrivateKey,
    cert_opts,
    nil,
  )
  if err != nil { crash_with_help(2, "Error generating certificate: %s", err) }
  pem_block, err := cert.MarshalPem()
  if err != nil { crash_with_help(2, "Error converting to pem: %s", err) }
  _, err = pem_block.WriteTo(fs.Flags.Output)
  if err != nil { crash_with_help(2, "Output didn't work: %s", err) }
}

// print the module help
func print_modules() {
  fmt.Printf(`Usage: %s command args
where 'command' is one of:
    create-private    create a new private key
    create-public     create a public key from a private one
    sign-input        sign a message with a private key
    verify-signature  verify a signature
    create-cert-sign  create a new certificate sign request
    create-cert       sign a certificate request
    help              show this help
    info              get info on a file
`, filepath.Base(os.Args[0]))
  fmt.Println()
}

// crash and provide a helpful message
func crash_with_help(code int, message string, args ...interface{}) {
  fmt.Fprintf(os.Stderr, message + "\n", args...)
  print_modules()
  os.Exit(code)
}

// return the arguments to the program
func program_args() []string {
  return os.Args[2:]
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"gopkg.in/cheggaaa/pb.v1"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"os/signal"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	MAX_VALUE  int64 = 1679616 // 36^4
	MAX_RETRY        = 10
	RETRY_TIME       = 5 * time.Second
	TIMEOUT          = 20 * time.Second
)

var (
	link        = kingpin.Arg("link", "URL of BaiduYun file you want to get.").Required().String()
	preset      = kingpin.Flag("preset", "The preset start of key to brute.").Short('p').Default("0000").String()
	thread      = kingpin.Flag("thread", "Number of thread.").Short('t').Default("10").Int64()
	resolver    []*Resolve
	bar         *pb.ProgressBar
	shareid, uk string
	start       int64
	refer       string
	wg          sync.WaitGroup
	proxies     map[Proxy]int
	updater     []*Proxies
	mapLocker   *sync.Mutex
	useable     *AtomBool
	nullP       Proxy
)

type Info struct {
	Errno  int    `json:"errno"`
	ErrMsg string `json:"err_msg"`
}

type Proxy struct {
	typ, addr, port string
}

type Resolve struct {
	re  *regexp.Regexp
	fun func(*regexp.Regexp, string)
}

type Proxies struct {
	update func()
}

type AtomBool struct {
	flag bool
	lock *sync.Mutex
}

func (b *AtomBool) Set(value bool) {
	b.lock.Lock()
	defer b.lock.Unlock()
	b.flag = value
}

func (b *AtomBool) Get() bool {
	b.lock.Lock()
	defer b.lock.Unlock()
	if b.flag {
		b.flag = false
		return true
	}
	return false
}

func getProxy() (Proxy, bool) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	for {
		if len(proxies) <= 0 {
			return nullP, false
		}
		ran := rand.Intn(len(proxies))
		cnt := 0
		for i, k := range proxies {
			if k >= MAX_RETRY {
				delete(proxies, i)
				break
			}
			if cnt == ran {
				return i, true
			}
			cnt++
		}
	}
}

func addProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	proxies[in] = 0
}

func deleteProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	delete(proxies, in)
}

func increProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	proxies[in]++
}

func saveProxies() {
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://api.xicidaili.com/free2016.txt")
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					sca := bufio.NewScanner(resp.Body)
					for sca.Scan() {
						spl := strings.Split(sca.Text(), ":")
						if len(spl) != 2 {
							log.Fatal("WTF??")
						}
						ne := Proxy{"http", spl[0], spl[1]}
						addProxy(ne)
					}
					resp.Body.Close()
					time.Sleep(15 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://proxy.tekbreak.com/1000/json")
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					var sca []struct {
						IP   string `json:"ip"`
						Port string `json:"port"`
						Type string `json:"type"`
					}
					if err := json.NewDecoder(resp.Body).Decode(&sca); err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					for _, i := range sca {
						ne := Proxy{addr: i.IP, port: i.Port}
						ignore := false
						switch i.Type {
						case "HTTP":
							ne.typ = "http"
						case "HTTPS":
							ne.typ = "https"
						default:
							ignore = true
						}
						if !ignore {
							addProxy(ne)
						}
					}
					resp.Body.Close()
					time.Sleep(5 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://free-proxy-list.net/")
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					conte, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					re, _ := regexp.Compile(`<tr><td>(\d+\.\d+\.\d+\.\d+)</td><td>(\d+)</td><td>.*</td><td>.*</td><td>.*</td><td>.*</td><td>(yes|no)</td><td>.*</td></tr>`)
					sca := re.FindAllStringSubmatch(string(conte), -1)
					for _, i := range sca {
						if len(i) != 4 {
							log.Fatal("WTF??")
						}
						if i[3] == "yes" {
							i[3] = "https"
						} else if i[3] == "no" {
							i[3] = "http"
						}
						ne := Proxy{i[3], i[1], i[2]}
						addProxy(ne)
					}
					time.Sleep(5 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("https://www.sslproxies.org/")
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					conte, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					re, _ := regexp.Compile(`<tr><td>(\d+\.\d+\.\d+\.\d+)</td><td>(\d+)</td>.*</tr>`)
					sca := re.FindAllStringSubmatch(string(conte), -1)
					for _, i := range sca {
						if len(i) != 3 {
							log.Fatal("WTF??")
						}
						ne := Proxy{"https", i[1], i[2]}
						addProxy(ne)
					}
					time.Sleep(5 * time.Minute)
				}
			},
		})
}

func next(now string, count int64) int64 {
	num, err := strconv.ParseInt(now, 36, 64)
	if err != nil || num < 0 || num > MAX_VALUE {
		log.Fatal("Not a valid number!")
	}
	return num + count
}

func saveResolver() {
	re1, _ := regexp.Compile(`//pan\.baidu\.com/share/init\?shareid=(\d+)&uk=(\d+)`)
	resolver = append(resolver,
		&Resolve{
			re1,
			func(re *regexp.Regexp, ori string) {
				ret := re.FindStringSubmatch(ori)
				if len(ret) != 3 {
					log.Fatal("WTF??", ori)
				}
				shareid = ret[1]
				uk = ret[2]
				refer = ori
			},
		})
	re2, _ := regexp.Compile(`//pan\.baidu\.com/s/([a-zA-Z0-9]+)`)
	resolver = append(resolver,
		&Resolve{
			re2,
			func(re *regexp.Regexp, ori string) {
				jar, _ := cookiejar.New(nil)
				session := &http.Client{
					Jar: jar,
					CheckRedirect: func(req *http.Request, via []*http.Request) error {
						return http.ErrUseLastResponse
					},
				}
				for {
					resp, err := session.Get(ori)
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
						continue
					}
					if resp.StatusCode == 200 {
						log.Fatal("Link seems password-less!")
					} else if resp.StatusCode == 302 {
						if resolver[0].re.MatchString(resp.Header.Get("Location")) {
							resolver[0].fun(resolver[0].re, resp.Header.Get("Location"))
						} else {
							log.Fatal("WTF??", ori, resp.Header.Get("Location"))
						}
						break
					}
				}
			},
		})
}

func builder(now string) (*http.Response, Proxy, error) {
	var pro Proxy
	for {
		var ok bool
		if pro, ok = getProxy(); ok {
			useable.Set(true)
			break
		}
		if useable.Get() {
			log.Println("No proxies left! Threads will hang up...")
		}
		time.Sleep(RETRY_TIME)
	}
	par, _ := url.Parse(fmt.Sprintf("%s://%s:%s", pro.typ, pro.addr, pro.port))
	session := &http.Client{
		Timeout:   TIMEOUT,
		Transport: &http.Transport{Proxy: http.ProxyURL(par)},
	}
	req, err := http.NewRequest("POST", fmt.Sprintf("https://pan.baidu.com/share/verify?shareid=%s&uk=%s", shareid, uk), strings.NewReader(fmt.Sprintf("pwd=%04s&vcode=&vcode_str=", now)))
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36")
	req.Header.Set("Origin", "https://pan.baidu.com")
	req.Header.Set("Referer", refer)
	resp, err := session.Do(req)
	if err != nil && strings.Contains(err.Error(), "error connecting to proxy") { // ugly way
		increProxy(pro)
	}
	return resp, pro, err
}

func tester(work int64) {
	for work < MAX_VALUE {
		now := strconv.FormatInt(work, 36)
		info := new(Info)
		for {
			if resp, pro, err := builder(now); err == nil {
				if resp.StatusCode == 200 {
					if err = json.NewDecoder(resp.Body).Decode(info); err == nil {
						if info.Errno == 0 {
							log.Println("Key found!", now)
							os.Exit(0)
						} else if info.Errno != -9 {
							log.Println("Unknown error! Service returned", info.Errno, "with message:", info.ErrMsg)
						} else {
							break
						}
					}
				} else if resp.StatusCode == 404 {
					deleteProxy(pro)
				} else {
					log.Println("Unknown error! Server returned", resp.StatusCode)
				}
				resp.Body.Close()
			}
			time.Sleep(RETRY_TIME)
		}
		bar.Increment()
		work += *thread
	}
	wg.Done()
}

func init() {
	kingpin.CommandLine.HelpFlag.Short('h')
	kingpin.Parse()
	saveResolver() // For future expansion of resolver
	mapLocker = new(sync.Mutex)
	useable = new(AtomBool)
	useable.lock = new(sync.Mutex)
	useable.Set(true)
	proxies = make(map[Proxy]int)
	saveProxies() // For future expansion of proxy
	var indi int
	for indi = 0; indi < len(resolver); indi++ {
		if resolver[indi].re.MatchString(*link) {
			resolver[indi].fun(resolver[indi].re, *link)
			break
		}
	}
	if indi == len(resolver) {
		log.Fatal("No proper resolver found!")
	}
	for _, i := range updater {
		go i.update()
	}
	start = next(*preset, 0)
	bar = pb.New64(MAX_VALUE)
	bar.SetMaxWidth(70)
	bar.ShowCounters = false
	bar.ShowSpeed = true
	bar.ShowTimeLeft = true
	bar.ShowFinalTime = true
	bar.Set64(start)
	bar.Start()
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			log.Printf("Terminating program, current progress: %04s", strconv.FormatInt(bar.Get(), 36))
			os.Exit(1)
		}
	}()
}

func main() {
	//go func() {
	//	for {
	//		log.Println(len(proxies))
	//		for i, k := range proxies {
	//			log.Println(i, k)
	//			break
	//		}
	//		time.Sleep(RETRY_TIME)
	//	}
	//}() // DEBUG
	log.SetPrefix("\n")
	wg.Add(int(*thread))
	for i := int64(0); i < *thread; i++ {
		go tester(start + i)
	}
	wg.Wait()
	log.Fatal("No key found!")
}
<commit_msg>Yep, few bugs during test<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"gopkg.in/alecthomas/kingpin.v2"
	"gopkg.in/cheggaaa/pb.v1"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"os/signal"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	MAX_VALUE  int64 = 1679616 // 36^4
	MAX_RETRY        = 10
	RETRY_TIME       = 5 * time.Second
	TIMEOUT          = 20 * time.Second
)

var (
	link        = kingpin.Arg("link", "URL of BaiduYun file you want to get.").Required().String()
	preset      = kingpin.Flag("preset", "The preset start of key to brute.").Short('p').Default("0000").String()
	thread      = kingpin.Flag("thread", "Number of thread.").Short('t').Default("10").Int64()
	resolver    []*Resolve
	bar         *pb.ProgressBar
	shareid, uk string
	start       int64
	refer       string
	wg          sync.WaitGroup
	proxies     map[Proxy]int
	updater     []*Proxies
	mapLocker   *sync.Mutex
	useable     *AtomBool
	nullP       Proxy
)

type Info struct {
	Errno  int    `json:"errno"`
	ErrMsg string `json:"err_msg"`
}

type Proxy struct {
	typ, addr, port string
}

type Resolve struct {
	re  *regexp.Regexp
	fun func(*regexp.Regexp, string)
}

type Proxies struct {
	update func()
}

type AtomBool struct {
	flag bool
	lock *sync.Mutex
}

func (b *AtomBool) Set(value bool) {
	b.lock.Lock()
	defer b.lock.Unlock()
	b.flag = value
}

func (b *AtomBool) Get() bool {
	b.lock.Lock()
	defer b.lock.Unlock()
	if b.flag {
		b.flag = false
		return true
	}
	return false
}

func getProxy() (Proxy, bool) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	for {
		if len(proxies) <= 0 {
			return nullP, false
		}
		ran := rand.Intn(len(proxies))
		cnt := 0
		for i, k := range proxies {
			if k >= MAX_RETRY {
				delete(proxies, i)
				break
			}
			if cnt == ran {
				return i, true
			}
			cnt++
		}
	}
}

func addProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	proxies[in] = 0
}

func deleteProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	delete(proxies, in)
}

func increProxy(in Proxy) {
	mapLocker.Lock()
	defer mapLocker.Unlock()
	proxies[in]++
}

func saveProxies() {
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://api.xicidaili.com/free2016.txt")
					if err != nil || resp.Body == nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					sca := bufio.NewScanner(resp.Body)
					for sca.Scan() {
						spl := strings.Split(sca.Text(), ":")
						if len(spl) != 2 {
							log.Fatal("WTF??")
						}
						ne := Proxy{"http", spl[0], spl[1]}
						addProxy(ne)
					}
					resp.Body.Close()
					time.Sleep(15 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://proxy.tekbreak.com/1000/json")
					if err != nil || resp.Body == nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					var sca []struct {
						IP   string `json:"ip"`
						Port string `json:"port"`
						Type string `json:"type"`
					}
					if err := json.NewDecoder(resp.Body).Decode(&sca); err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					for _, i := range sca {
						ne := Proxy{addr: i.IP, port: i.Port}
						ignore := false
						switch i.Type {
						case "HTTP":
							ne.typ = "http"
						case "HTTPS":
							ne.typ = "https"
						default:
							ignore = true
						}
						if !ignore {
							addProxy(ne)
						}
					}
					resp.Body.Close()
					time.Sleep(5 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("http://free-proxy-list.net/")
					if err != nil || resp.Body == nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					conte, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					re, _ := regexp.Compile(`<tr><td>(\d+\.\d+\.\d+\.\d+)</td><td>(\d+)</td><td>.*</td><td>.*</td><td>.*</td><td>.*</td><td>(yes|no)</td><td>.*</td></tr>`)
					sca := re.FindAllStringSubmatch(string(conte), -1)
					for _, i := range sca {
						if len(i) != 4 {
							log.Fatal("WTF??")
						}
						if i[3] == "yes" {
							i[3] = "https"
						} else if i[3] == "no" {
							i[3] = "http"
						}
						ne := Proxy{i[3], i[1], i[2]}
						addProxy(ne)
					}
					time.Sleep(5 * time.Minute)
				}
			},
		})
	updater = append(updater,
		&Proxies{
			func() {
				for {
					resp, err := http.Get("https://www.sslproxies.org/")
					if err != nil || resp.Body == nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					conte, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
					}
					re, _ := regexp.Compile(`<tr><td>(\d+\.\d+\.\d+\.\d+)</td><td>(\d+)</td>.*</tr>`)
					sca := re.FindAllStringSubmatch(string(conte), -1)
					for _, i := range sca {
						if len(i) != 3 {
							log.Fatal("WTF??")
						}
						ne := Proxy{"https", i[1], i[2]}
						addProxy(ne)
					}
					time.Sleep(5 * time.Minute)
				}
			},
		})
}

func next(now string, count int64) int64 {
	num, err := strconv.ParseInt(now, 36, 64)
	if err != nil || num < 0 || num > MAX_VALUE {
		log.Fatal("Not a valid number!")
	}
	return num + count
}

func saveResolver() {
	re1, _ := regexp.Compile(`//pan\.baidu\.com/share/init\?shareid=(\d+)&uk=(\d+)`)
	resolver = append(resolver,
		&Resolve{
			re1,
			func(re *regexp.Regexp, ori string) {
				ret := re.FindStringSubmatch(ori)
				if len(ret) != 3 {
					log.Fatal("WTF??", ori)
				}
				shareid = ret[1]
				uk = ret[2]
				refer = ori
			},
		})
	re2, _ := regexp.Compile(`//pan\.baidu\.com/s/([a-zA-Z0-9]+)`)
	resolver = append(resolver,
		&Resolve{
			re2,
			func(re *regexp.Regexp, ori string) {
				jar, _ := cookiejar.New(nil)
				session := &http.Client{
					Jar: jar,
					CheckRedirect: func(req *http.Request, via []*http.Request) error {
						return http.ErrUseLastResponse
					},
				}
				for {
					resp, err := session.Get(ori)
					if err != nil {
						log.Println(err)
						time.Sleep(RETRY_TIME)
						continue
					}
					if resp.StatusCode == 200 {
						log.Fatal("Link seems password-less!")
					} else if resp.StatusCode == 302 {
						if resolver[0].re.MatchString(resp.Header.Get("Location")) {
							resolver[0].fun(resolver[0].re, resp.Header.Get("Location"))
						} else {
							log.Fatal("WTF??", ori, resp.Header.Get("Location"))
						}
						break
					}
				}
			},
		})
}

func builder(now string) (*http.Response, Proxy, error) {
	var pro Proxy
	for {
		var ok bool
		if pro, ok = getProxy(); ok {
			useable.Set(true)
			break
		}
		if useable.Get() {
			log.Println("No proxies left! Threads will hang up...")
		}
		time.Sleep(RETRY_TIME)
	}
	par, _ := url.Parse(fmt.Sprintf("%s://%s:%s", pro.typ, pro.addr, pro.port))
	session := &http.Client{
		Timeout:   TIMEOUT,
		Transport: &http.Transport{Proxy: http.ProxyURL(par)},
	}
	req, err := http.NewRequest("POST", fmt.Sprintf("https://pan.baidu.com/share/verify?shareid=%s&uk=%s", shareid, uk), strings.NewReader(fmt.Sprintf("pwd=%04s&vcode=&vcode_str=", now)))
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36")
	req.Header.Set("Origin", "https://pan.baidu.com")
	req.Header.Set("Referer", refer)
	resp, err := session.Do(req)
	return resp, pro, err
}

func tester(work int64) {
	for work < MAX_VALUE {
		now := strconv.FormatInt(work, 36)
		info := new(Info)
		for {
			if resp, pro, err := builder(now); err == nil {
				if resp.StatusCode == 200 {
					if err = json.NewDecoder(resp.Body).Decode(info); err == nil {
						if info.Errno == 0 {
							log.Println("Key found!", now)
							os.Exit(0)
						} else if info.Errno != -9 {
							log.Println("Unknown error! Service returned", info.Errno, "with message:", info.ErrMsg)
						} else {
							break
						}
					}
				} else if resp.StatusCode == 404 {
					deleteProxy(pro)
				} else {
					log.Println("Unknown error! Server returned", resp.StatusCode)
				}
				resp.Body.Close()
			} else if strings.Contains(err.Error(), "error connecting to proxy") {
				increProxy(pro)
			}
			time.Sleep(RETRY_TIME)
		}
		bar.Increment()
		work += *thread
	}
	wg.Done()
}

func init() {
	kingpin.CommandLine.HelpFlag.Short('h')
	kingpin.Parse()
	saveResolver() // For future expansion of resolver
	mapLocker = new(sync.Mutex)
	useable = new(AtomBool)
	useable.lock = new(sync.Mutex)
	proxies = make(map[Proxy]int)
	saveProxies() // For future expansion of proxy
	var indi int
	for indi = 0; indi < len(resolver); indi++ {
		if resolver[indi].re.MatchString(*link) {
			resolver[indi].fun(resolver[indi].re, *link)
			break
		}
	}
	if indi == len(resolver) {
		log.Fatal("No proper resolver found!")
	}
	for _, i := range updater {
		go i.update()
	}
	start = next(*preset, 0)
	bar = pb.New64(MAX_VALUE)
	bar.SetMaxWidth(70)
	bar.ShowCounters = false
	bar.ShowSpeed = true
	bar.ShowTimeLeft = true
	bar.ShowFinalTime = true
	bar.Set64(start)
	bar.Start()
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			log.Printf("Terminating program, current progress: %04s", strconv.FormatInt(bar.Get(), 36))
			os.Exit(1)
		}
	}()
}

func main() {
	//go func() {
	//	for {
	//		log.Println(len(proxies))
	//		for i, k := range proxies {
	//			log.Println(i, k)
	//			break
	//		}
	//		time.Sleep(RETRY_TIME)
	//	}
	//}() // DEBUG
	log.SetPrefix("\n")
	wg.Add(int(*thread))
	for i := int64(0); i < *thread; i++ {
		go tester(start + i)
	}
	wg.Wait()
	log.Fatal("No key found!")
}
<|endoftext|>


<commit_before>// 4 march 2014
package main

import (
	"fmt"
	"os"
//	"os/exec"
	"time"
	"github.com/andlabs/ui"
)

const (
	defCmdLine = "mpv -loop inf ~/ring.wav"
	defTime = "10:00 AM"
	timeFmt = "3:04 PM"
)

// If later hasn't happened yet, make it happen on the day of now; if not, the day after.
func bestTime(now time.Time, later time.Time) time.Time {
	now = now.Local()		// use local time to make things make sense
	nowh, nowm, nows := now.Clock()
	laterh, laterm, laters := later.Clock()
	add := false
	if nowh > laterh {
		add = true
	} else if (nowh == laterh) && (nowm > laterm) {
		add = true
	} else if (nowh == laterh) && (nowm == laterm) && (nows >= laters) {
		// >= in the case we're on the exact second; add a day because the alarm should have gone off by now otherwise!
		add = true
	}
println(nowh,nowm,nows,add,laterh,laterm,laters)
	if add {
		now = now.AddDate(0, 0, 1)
	}
	return time.Date(now.Year(), now.Month(), now.Day(),
		laterh, laterm, laters, 0,
		now.Location())
}

func myMain() {
	w := ui.NewWindow("wakeup", 400, 100)
	w.Closing = ui.Event()
	cmdbox := ui.NewLineEdit(defCmdLine)
	timebox := ui.NewLineEdit(defTime)
	bStart := ui.NewButton("Start")
	bStop := ui.NewButton("Stop")

	// a Stack to keep both buttons at the same size
	btnbox := ui.NewStack(ui.Horizontal, bStart, bStop)
	btnbox.SetStretchy(0)
	btnbox.SetStretchy(1)
	// and a Stack around that Stack to keep them at a reasonable size
	btnbox = ui.NewStack(ui.Horizontal, btnbox)

	// the main layout
	grid := ui.NewGrid(2,
		ui.NewLabel("Command"), cmdbox,
		ui.NewLabel("Time"), timebox,
		ui.Space(), ui.Space(),		// the Space on the right will consume the window blank space
		ui.Space(), btnbox)
	grid.SetStretchy(2, 1)			// make the Space noted above consume
	grid.SetFilling(0, 1)				// make the two textboxes grow horizontally
	grid.SetFilling(1, 1)

	err := w.Open(grid)
	if err != nil {
		ui.MsgBoxError("wakeup", "Error opening window: %v", err)
		os.Exit(1)
	}

mainloop:
	for {
		select {
		case <-w.Closing:
			break mainloop
		case <-bStart.Clicked:
			alarmTime, err := time.Parse(timeFmt, timebox.Text())
			if err != nil {
				ui.MsgBoxError("wakeup",
					"Error parsing time %q: %v\nMake sure your time is in the form %q (without quotes.",
					timebox.Text(), err, timeFmt)
				continue
			}
			now := time.Now()
			later := bestTime(now, alarmTime)
			fmt.Println(later, later.Sub(now))
			// TODO
		case <-bStop.Clicked:
			// TODO
		}
	}
}

func main() {
	err := ui.Go(myMain)
	if err != nil {
		panic(fmt.Errorf("error initializing UI library: %v", err))
	}
}
<commit_msg>Added the code to run the timer and removed a stray debugging print line.<commit_after>// 4 march 2014
package main

import (
	"fmt"
	"os"
//	"os/exec"
	"time"
	"github.com/andlabs/ui"
)

const (
	defCmdLine = "mpv -loop inf ~/ring.wav"
	defTime = "10:00 AM"
	timeFmt = "3:04 PM"
)

// If later hasn't happened yet, make it happen on the day of now; if not, the day after.
func bestTime(now time.Time, later time.Time) time.Time {
	now = now.Local()		// use local time to make things make sense
	nowh, nowm, nows := now.Clock()
	laterh, laterm, laters := later.Clock()
	add := false
	if nowh > laterh {
		add = true
	} else if (nowh == laterh) && (nowm > laterm) {
		add = true
	} else if (nowh == laterh) && (nowm == laterm) && (nows >= laters) {
		// >= in the case we're on the exact second; add a day because the alarm should have gone off by now otherwise!
		add = true
	}
	if add {
		now = now.AddDate(0, 0, 1)
	}
	return time.Date(now.Year(), now.Month(), now.Day(),
		laterh, laterm, laters, 0,
		now.Location())
}

func myMain() {
	var timer *time.Timer
	var timerChan <-chan time.Time

	stop := func() {
		// TODO stop process
		if timer != nil {		// stop the timer if we started it
			timer.Stop()
			timer = nil
			timerChan = nil
		}
	}

	w := ui.NewWindow("wakeup", 400, 100)
	w.Closing = ui.Event()
	cmdbox := ui.NewLineEdit(defCmdLine)
	timebox := ui.NewLineEdit(defTime)
	bStart := ui.NewButton("Start")
	bStop := ui.NewButton("Stop")

	// a Stack to keep both buttons at the same size
	btnbox := ui.NewStack(ui.Horizontal, bStart, bStop)
	btnbox.SetStretchy(0)
	btnbox.SetStretchy(1)
	// and a Stack around that Stack to keep them at a reasonable size
	btnbox = ui.NewStack(ui.Horizontal, btnbox)

	// the main layout
	grid := ui.NewGrid(2,
		ui.NewLabel("Command"), cmdbox,
		ui.NewLabel("Time"), timebox,
		ui.Space(), ui.Space(),		// the Space on the right will consume the window blank space
		ui.Space(), btnbox)
	grid.SetStretchy(2, 1)			// make the Space noted above consume
	grid.SetFilling(0, 1)				// make the two textboxes grow horizontally
	grid.SetFilling(1, 1)

	err := w.Open(grid)
	if err != nil {
		ui.MsgBoxError("wakeup", "Error opening window: %v", err)
		os.Exit(1)
	}

mainloop:
	for {
		select {
		case <-w.Closing:
			break mainloop
		case <-bStart.Clicked:
			stop()		// only one alarm at a time
			alarmTime, err := time.Parse(timeFmt, timebox.Text())
			if err != nil {
				ui.MsgBoxError("wakeup",
					"Error parsing time %q: %v\nMake sure your time is in the form %q (without quotes.",
					timebox.Text(), err, timeFmt)
				continue
			}
			now := time.Now()
			later := bestTime(now, alarmTime)
			timer = time.NewTimer(later.Sub(now))
			timerChan = timer.C
		case <-timerChan:
			ui.MsgBox("wakeup", "alarm")
			timer = nil
			timerChan = nil
		case <-bStop.Clicked:
			stop()
			ui.MsgBox("wakeup", "abort")
		}
	}

	// clean up
	stop()
}

func main() {
	err := ui.Go(myMain)
	if err != nil {
		panic(fmt.Errorf("error initializing UI library: %v", err))
	}
}
<|endoftext|>


<commit_before>package main

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

type weatherData struct{
	Name string `json:"name"`
	Main struct{
		Kelvin float64 `json:"temp"`
	} `json:"main"`
}

func query(city string) (weatherData, error) {
	resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?q=" + city)
	if err != nil{
		return weatherData{}, err
	}

	defer resp.Body.Close()

	var d weatherData

	if err := json.NewDecoder(resp.Body).Decode(&d); err != nil{
		return weatherData{}, err
	}

	return d, nil
}

func main() {
	http.HandleFunc("/hello", hello)

	http.HandleFunc("/weather/", func (w http.ResponseWriter, r *http.Request) {
		city := strings.SplitN(r.URL.Path, "/", 3)[2]

		data, err := query(city)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(data)
	})

	http.ListenAndServe(":9999", nil)
}

func hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello!"))
}
<commit_msg>Multisource weather service.<commit_after>package main

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

type weatherProvider interface{
	temperature(city string) (float64, error)
}

type openWeatherMap struct{}

func (w openWeatherMap) temperature(city string) (float64, error) {
	resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?q=" + city)
	if err != nil{
		return 0, err
	}

	defer resp.Body.Close()

	var d struct {
		Main struct{
			Kelvin float64 `json:"temp"`
		} `json:"main"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&d); err != nil{
		return 0, err
	}

	log.Printf("openWeatherMap: %s: %.2f", city, d.Main.Kelvin)
	return d.Main.Kelvin, nil

}

type weatherUnderground struct {
	apiKey string
}

func (w weatherUnderground) temperature(city string) (float64, error) {
	resp, err := http.Get("http://api.wunderground.com/api/" + w.apiKey + "/conditions/q/" + city + ".json")
	if err != nil{
		return 0, err
	}

	defer resp.Body.Close()

	var d struct {
		Observation struct{
			Celsius float64 `json:"temp_c"`
		} `json:"current_observation"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&d); err != nil{
		return 0, err
	}
	kelvin := d.Observation.Celsius + 273.15
	log.Printf("weatherUnderground: %s: %.2f", city, kelvin)
	return kelvin, nil

}

func temperature(city string, providers ...weatherProvider) (float64,error) {
	sum := 0.0
	for _, provider := range providers{
		k, err := provider.temperature(city)
		if err != nil{
			return 0 , err
		}

		sum += k
	}
	return sum / float64(len(providers)), nil
}

type multiWeatherProvider []weatherProvider

func (w multiWeatherProvider) temperature(city string) (float64, error) {
	sum := 0.0
	for _, provider := range w{
		k, err := provider.temperature(city)
		if err != nil{
			return 0 , err
		}

		sum += k
	}
	return sum / float64(len(w)), nil
}

func main() {
	mw := multiWeatherProvider{
		openWeatherMap{},
		weatherUnderground{apiKey: "api______key"},
	}

	http.HandleFunc("/weather/", func (w http.ResponseWriter, r *http.Request) {
		begin := time.Now()
		city := strings.SplitN(r.URL.Path, "/", 3)[2]

		temp, err := mw.temperature(city)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(map[string]interface{}{
			"city": city,
			"temp": temp,
			"took": time.Since(begin).String(),
			})
	})

	http.ListenAndServe(":9999", nil)
}

func hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello!"))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"

	cli "github.com/codegangsta/cli"
	rw "github.com/whyrusleeping/gx-go/rewrite"
	gx "github.com/whyrusleeping/gx/gxutil"
	. "github.com/whyrusleeping/stump"
)

func main() {
	app := cli.NewApp()
	app.Name = "gx-go-tool"
	app.Author = "whyrusleeping"
	app.Usage = "gx extensions for golang"
	app.Version = "0.2.0"

	var UpdateCommand = cli.Command{
		Name:      "update",
		Usage:     "update a packages imports to a new path",
		ArgsUsage: "[old import] [new import]",
		Action: func(c *cli.Context) {
			if len(c.Args()) < 2 {
				fmt.Println("must specify current and new import names")
				return
			}

			oldimp := c.Args()[0]
			newimp := c.Args()[1]

			err := doUpdate(oldimp, newimp)
			if err != nil {
				Fatal(err)
			}
		},
	}

	var ImportCommand = cli.Command{
		Name:  "import",
		Usage: "import a go package and all its depencies into gx",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "rewrite",
				Usage: "rewrite import paths to use vendored packages",
			},
			cli.BoolFlag{
				Name:  "yesall",
				Usage: "assume defaults for all options",
			},
		},
		Action: func(c *cli.Context) {
			importer, err := NewImporter(c.Bool("rewrite"))
			if err != nil {
				Fatal(err)
			}

			importer.yesall = c.Bool("yesall")

			if !c.Args().Present() {
				Fatal("must specify a package name")
			}

			pkg := c.Args().First()
			Log("vendoring package %s", pkg)

			_, err = importer.GxPublishGoPackage(pkg)
			if err != nil {
				Fatal(err)
			}
		},
	}

	var PathCommand = cli.Command{
		Name:  "path",
		Usage: "prints the import path of the current package within GOPATH",
		Action: func(c *cli.Context) {
			gopath := os.Getenv("GOPATH")
			if gopath == "" {
				Fatal("GOPATH not set, cannot derive import path")
			}

			cwd, err := os.Getwd()
			if err != nil {
				Fatal(err)
			}

			srcdir := path.Join(gopath, "src")
			srcdir += "/"

			if !strings.HasPrefix(cwd, srcdir) {
				Fatal("package not within GOPATH/src")
			}

			rel := cwd[len(srcdir):]
			fmt.Println(rel)
		},
	}

	var HookCommand = cli.Command{
		Name:  "hook",
		Usage: "go specific hooks to be called by the gx tool",
		Action: func(c *cli.Context) {
			if !c.Args().Present() {
				Fatal("no hook specified!")
			}
			sub := c.Args().First()

			pkg, err := gx.LoadPackageFile(gx.PkgFileName)
			if err != nil {
				Fatal(err)
			}

			switch sub {
			case "post-import":
				err := postImportHook(pkg, c.Args().Tail())
				if err != nil {
					Fatal(err)
				}
			}
		},
	}

	app.Commands = []cli.Command{
		UpdateCommand,
		ImportCommand,
		PathCommand,
		HookCommand,
	}

	app.Run(os.Args)
}

func doUpdate(oldimp, newimp string) error {
	curpath, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("error getting working dir: ", err)
	}

	rwf := func(in string) string {
		if in == oldimp {
			return newimp
		}
		return in
	}

	filter := func(in string) bool {
		return strings.HasSuffix(in, ".go")
	}

	return rw.RewriteImports(curpath, rwf, filter)
}

func pathIsNotStdlib(path string) bool {
	first := strings.Split(path, "/")[0]

	if len(strings.Split(first, ".")) > 1 {
		return true
	}
	return false
}

type Importer struct {
	pkgs    map[string]*gx.Dependency
	gopath  string
	pm      *gx.PM
	rewrite bool
	yesall  bool
}

func NewImporter(rw bool) (*Importer, error) {
	gp, err := getGoPath()
	if err != nil {
		return nil, err
	}

	cfg, err := gx.LoadConfig()
	if err != nil {
		return nil, err
	}

	return &Importer{
		pkgs:    make(map[string]*gx.Dependency),
		gopath:  gp,
		pm:      gx.NewPM(cfg),
		rewrite: rw,
	}, nil
}

func getGoPath() (string, error) {
	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return "", errors.New("gopath not set")
	}
	return gopath, nil
}

func (i *Importer) GxPublishGoPackage(imppath string) (*gx.Dependency, error) {
	if d, ok := i.pkgs[imppath]; ok {
		return d, nil
	}

	// make sure its local
	err := GoGet(imppath)
	if err != nil {
		return nil, err
	}

	pkgpath := path.Join(i.gopath, "src", imppath)
	pkgFilePath := path.Join(pkgpath, gx.PkgFileName)
	pkg, err := gx.LoadPackageFile(pkgFilePath)
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, err
		}

		// init as gx package
		parts := strings.Split(imppath, "/")
		pkgname := parts[len(parts)-1]
		if !i.yesall {
			p := fmt.Sprintf("enter name for import '%s'", imppath)
			nname, err := prompt(p, pkgname)
			if err != nil {
				return nil, err
			}

			pkgname = nname
		}

		err = i.pm.InitPkg(pkgpath, pkgname, "go")
		if err != nil {
			return nil, err
		}

		pkg, err = gx.LoadPackageFile(pkgFilePath)
		if err != nil {
			return nil, err
		}
	}

	// recurse!
	gopkg, err := build.Import(imppath, "", 0)
	if err != nil {
		return nil, err
	}

	var depsToVendor []string

	for _, child := range gopkg.Imports {
		if pathIsNotStdlib(child) {
			depsToVendor = append(depsToVendor, child)
		}
	}

	for n, child := range depsToVendor {
		Log("- processing dep %s for %s [%d / %d]", child, imppath, n+1, len(depsToVendor))
		childdep, err := i.GxPublishGoPackage(child)
		if err != nil {
			return nil, err
		}

		pkg.Dependencies = append(pkg.Dependencies, childdep)
	}

	err = gx.SavePackageFile(pkg, pkgFilePath)
	if err != nil {
		return nil, err
	}

	if i.rewrite {
		fullpkgpath, err := filepath.Abs(pkgpath)
		if err != nil {
			return nil, err
		}

		err = i.rewriteImports(fullpkgpath)
		if err != nil {
			return nil, err
		}
	}

	hash, err := i.pm.PublishPackage(pkgpath, pkg)
	if err != nil {
		return nil, err
	}

	Log("published %s as %s", imppath, hash)

	dep := &gx.Dependency{
		Hash:    hash,
		Name:    pkg.Name,
		Version: pkg.Version,
	}
	i.pkgs[imppath] = dep
	return dep, nil
}

func (i *Importer) rewriteImports(pkgpath string) error {

	filter := func(p string) bool {
		return !strings.HasPrefix(p, "vendor") &&
			!strings.HasPrefix(p, ".git") &&
			strings.HasSuffix(p, ".go")
	}

	rwf := func(in string) string {
		dep, ok := i.pkgs[in]
		if !ok {
			return in
		}

		return dep.Hash + "/" + dep.Name
	}

	return rw.RewriteImports(pkgpath, rwf, filter)
}

// TODO: take an option to grab packages from local GOPATH
func GoGet(path string) error {
	out, err := exec.Command("go", "get", path).CombinedOutput()
	if err != nil {
		return fmt.Errorf("go get failed: %s - %s", string(out), err)
	}
	return nil
}

func prompt(text, def string) (string, error) {
	scan := bufio.NewScanner(os.Stdin)
	fmt.Printf("%s (default: '%s') ", text, def)
	for scan.Scan() {
		if scan.Text() != "" {
			return scan.Text(), nil
		}
		return def, nil
	}

	return "", scan.Err()
}

func yesNoPrompt(prompt string, def bool) bool {
	opts := "[y/N]"
	if def {
		opts = "[Y/n]"
	}

	fmt.Printf("%s %s ", prompt, opts)
	scan := bufio.NewScanner(os.Stdin)
	for scan.Scan() {
		val := strings.ToLower(scan.Text())
		switch val {
		case "":
			return def
		case "y":
			return true
		case "n":
			return false
		default:
			fmt.Println("please type 'y' or 'n'")
		}
	}

	panic("unexpected termination of stdin")
}

func postImportHook(pkg *gx.Package, args []string) error {
	if len(args) == 0 {
		return fmt.Errorf("post-import hook: argument expected")
	}

	npkgHash := args[0]
	npkgPath := filepath.Join("vendor", npkgHash)

	npkg, err := gx.LoadPackageFile(npkgPath)
	if err != nil {
		return err
	}

	if npkg.Go != nil && npkg.Go.DvcsImport != "" {
		q := fmt.Sprintf("update imports of %s to the newly imported package?", npkg.Go.DvcsImport)
		if yesNoPrompt(q, false) {
			nimp := fmt.Sprintf("%s/%s", npkgHash, npkg.Name)
			err := doUpdate(npkg.Go.DvcsImport, nimp)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>fix post import hook<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"

	cli "github.com/codegangsta/cli"
	rw "github.com/whyrusleeping/gx-go/rewrite"
	gx "github.com/whyrusleeping/gx/gxutil"
	. "github.com/whyrusleeping/stump"
)

func main() {
	app := cli.NewApp()
	app.Name = "gx-go-tool"
	app.Author = "whyrusleeping"
	app.Usage = "gx extensions for golang"
	app.Version = "0.2.0"

	var UpdateCommand = cli.Command{
		Name:      "update",
		Usage:     "update a packages imports to a new path",
		ArgsUsage: "[old import] [new import]",
		Action: func(c *cli.Context) {
			if len(c.Args()) < 2 {
				fmt.Println("must specify current and new import names")
				return
			}

			oldimp := c.Args()[0]
			newimp := c.Args()[1]

			err := doUpdate(oldimp, newimp)
			if err != nil {
				Fatal(err)
			}
		},
	}

	var ImportCommand = cli.Command{
		Name:  "import",
		Usage: "import a go package and all its depencies into gx",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "rewrite",
				Usage: "rewrite import paths to use vendored packages",
			},
			cli.BoolFlag{
				Name:  "yesall",
				Usage: "assume defaults for all options",
			},
		},
		Action: func(c *cli.Context) {
			importer, err := NewImporter(c.Bool("rewrite"))
			if err != nil {
				Fatal(err)
			}

			importer.yesall = c.Bool("yesall")

			if !c.Args().Present() {
				Fatal("must specify a package name")
			}

			pkg := c.Args().First()
			Log("vendoring package %s", pkg)

			_, err = importer.GxPublishGoPackage(pkg)
			if err != nil {
				Fatal(err)
			}
		},
	}

	var PathCommand = cli.Command{
		Name:  "path",
		Usage: "prints the import path of the current package within GOPATH",
		Action: func(c *cli.Context) {
			gopath := os.Getenv("GOPATH")
			if gopath == "" {
				Fatal("GOPATH not set, cannot derive import path")
			}

			cwd, err := os.Getwd()
			if err != nil {
				Fatal(err)
			}

			srcdir := path.Join(gopath, "src")
			srcdir += "/"

			if !strings.HasPrefix(cwd, srcdir) {
				Fatal("package not within GOPATH/src")
			}

			rel := cwd[len(srcdir):]
			fmt.Println(rel)
		},
	}

	var HookCommand = cli.Command{
		Name:  "hook",
		Usage: "go specific hooks to be called by the gx tool",
		Action: func(c *cli.Context) {
			if !c.Args().Present() {
				Fatal("no hook specified!")
			}
			sub := c.Args().First()

			pkg, err := gx.LoadPackageFile(gx.PkgFileName)
			if err != nil {
				Fatal(err)
			}

			switch sub {
			case "post-import":
				err := postImportHook(pkg, c.Args().Tail())
				if err != nil {
					Fatal(err)
				}
			}
		},
	}

	app.Commands = []cli.Command{
		UpdateCommand,
		ImportCommand,
		PathCommand,
		HookCommand,
	}

	app.Run(os.Args)
}

func doUpdate(oldimp, newimp string) error {
	curpath, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("error getting working dir: ", err)
	}

	rwf := func(in string) string {
		if in == oldimp {
			return newimp
		}
		return in
	}

	filter := func(in string) bool {
		return strings.HasSuffix(in, ".go")
	}

	return rw.RewriteImports(curpath, rwf, filter)
}

func pathIsNotStdlib(path string) bool {
	first := strings.Split(path, "/")[0]

	if len(strings.Split(first, ".")) > 1 {
		return true
	}
	return false
}

type Importer struct {
	pkgs    map[string]*gx.Dependency
	gopath  string
	pm      *gx.PM
	rewrite bool
	yesall  bool
}

func NewImporter(rw bool) (*Importer, error) {
	gp, err := getGoPath()
	if err != nil {
		return nil, err
	}

	cfg, err := gx.LoadConfig()
	if err != nil {
		return nil, err
	}

	return &Importer{
		pkgs:    make(map[string]*gx.Dependency),
		gopath:  gp,
		pm:      gx.NewPM(cfg),
		rewrite: rw,
	}, nil
}

func getGoPath() (string, error) {
	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return "", errors.New("gopath not set")
	}
	return gopath, nil
}

func (i *Importer) GxPublishGoPackage(imppath string) (*gx.Dependency, error) {
	if d, ok := i.pkgs[imppath]; ok {
		return d, nil
	}

	// make sure its local
	err := GoGet(imppath)
	if err != nil {
		return nil, err
	}

	pkgpath := path.Join(i.gopath, "src", imppath)
	pkgFilePath := path.Join(pkgpath, gx.PkgFileName)
	pkg, err := gx.LoadPackageFile(pkgFilePath)
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, err
		}

		// init as gx package
		parts := strings.Split(imppath, "/")
		pkgname := parts[len(parts)-1]
		if !i.yesall {
			p := fmt.Sprintf("enter name for import '%s'", imppath)
			nname, err := prompt(p, pkgname)
			if err != nil {
				return nil, err
			}

			pkgname = nname
		}

		err = i.pm.InitPkg(pkgpath, pkgname, "go")
		if err != nil {
			return nil, err
		}

		pkg, err = gx.LoadPackageFile(pkgFilePath)
		if err != nil {
			return nil, err
		}
	}

	// recurse!
	gopkg, err := build.Import(imppath, "", 0)
	if err != nil {
		return nil, err
	}

	var depsToVendor []string

	for _, child := range gopkg.Imports {
		if pathIsNotStdlib(child) {
			depsToVendor = append(depsToVendor, child)
		}
	}

	for n, child := range depsToVendor {
		Log("- processing dep %s for %s [%d / %d]", child, imppath, n+1, len(depsToVendor))
		childdep, err := i.GxPublishGoPackage(child)
		if err != nil {
			return nil, err
		}

		pkg.Dependencies = append(pkg.Dependencies, childdep)
	}

	err = gx.SavePackageFile(pkg, pkgFilePath)
	if err != nil {
		return nil, err
	}

	if i.rewrite {
		fullpkgpath, err := filepath.Abs(pkgpath)
		if err != nil {
			return nil, err
		}

		err = i.rewriteImports(fullpkgpath)
		if err != nil {
			return nil, err
		}
	}

	hash, err := i.pm.PublishPackage(pkgpath, pkg)
	if err != nil {
		return nil, err
	}

	Log("published %s as %s", imppath, hash)

	dep := &gx.Dependency{
		Hash:    hash,
		Name:    pkg.Name,
		Version: pkg.Version,
	}
	i.pkgs[imppath] = dep
	return dep, nil
}

func (i *Importer) rewriteImports(pkgpath string) error {

	filter := func(p string) bool {
		return !strings.HasPrefix(p, "vendor") &&
			!strings.HasPrefix(p, ".git") &&
			strings.HasSuffix(p, ".go")
	}

	rwf := func(in string) string {
		dep, ok := i.pkgs[in]
		if !ok {
			return in
		}

		return dep.Hash + "/" + dep.Name
	}

	return rw.RewriteImports(pkgpath, rwf, filter)
}

// TODO: take an option to grab packages from local GOPATH
func GoGet(path string) error {
	out, err := exec.Command("go", "get", path).CombinedOutput()
	if err != nil {
		return fmt.Errorf("go get failed: %s - %s", string(out), err)
	}
	return nil
}

func prompt(text, def string) (string, error) {
	scan := bufio.NewScanner(os.Stdin)
	fmt.Printf("%s (default: '%s') ", text, def)
	for scan.Scan() {
		if scan.Text() != "" {
			return scan.Text(), nil
		}
		return def, nil
	}

	return "", scan.Err()
}

func yesNoPrompt(prompt string, def bool) bool {
	opts := "[y/N]"
	if def {
		opts = "[Y/n]"
	}

	fmt.Printf("%s %s ", prompt, opts)
	scan := bufio.NewScanner(os.Stdin)
	for scan.Scan() {
		val := strings.ToLower(scan.Text())
		switch val {
		case "":
			return def
		case "y":
			return true
		case "n":
			return false
		default:
			fmt.Println("please type 'y' or 'n'")
		}
	}

	panic("unexpected termination of stdin")
}

func postImportHook(pkg *gx.Package, args []string) error {
	if len(args) == 0 {
		return fmt.Errorf("post-import hook: argument expected")
	}

	npkgHash := args[0]
	npkgPath := filepath.Join("vendor", npkgHash)

	npkg, err := gx.FindPackageInDir(npkgPath)
	if err != nil {
		return err
	}

	if npkg.Go != nil && npkg.Go.DvcsImport != "" {
		q := fmt.Sprintf("update imports of %s to the newly imported package?", npkg.Go.DvcsImport)
		if yesNoPrompt(q, false) {
			nimp := fmt.Sprintf("%s/%s", npkgHash, npkg.Name)
			err := doUpdate(npkg.Go.DvcsImport, nimp)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 realglobe, Inc.
//
// 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 main

import (
	"github.com/realglobe-Inc/edo-id-provider/database/account"
	"github.com/realglobe-Inc/edo-id-provider/database/authcode"
	"github.com/realglobe-Inc/edo-id-provider/database/consent"
	"github.com/realglobe-Inc/edo-id-provider/database/coopcode"
	jtidb "github.com/realglobe-Inc/edo-id-provider/database/jti"
	keydb "github.com/realglobe-Inc/edo-id-provider/database/key"
	"github.com/realglobe-Inc/edo-id-provider/database/pairwise"
	"github.com/realglobe-Inc/edo-id-provider/database/sector"
	"github.com/realglobe-Inc/edo-id-provider/database/session"
	"github.com/realglobe-Inc/edo-id-provider/database/token"
	idpdb "github.com/realglobe-Inc/edo-idp-selector/database/idp"
	tadb "github.com/realglobe-Inc/edo-idp-selector/database/ta"
	webdb "github.com/realglobe-Inc/edo-idp-selector/database/web"
	idperr "github.com/realglobe-Inc/edo-idp-selector/error"
	"github.com/realglobe-Inc/edo-lib/driver"
	logutil "github.com/realglobe-Inc/edo-lib/log"
	"github.com/realglobe-Inc/edo-lib/server"
	"github.com/realglobe-Inc/go-lib/erro"
	"github.com/realglobe-Inc/go-lib/rglog"
	"net/http"
	"os"
	"strings"
)

func main() {
	var exitCode = 0
	defer func() {
		if exitCode != 0 {
			os.Exit(exitCode)
		}
	}()

	defer rglog.Flush()

	logutil.InitConsole("github.com/realglobe-Inc")

	param, err := parseParameters(os.Args...)
	if err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	logutil.SetupConsole("github.com/realglobe-Inc", param.consLv)
	if err := logutil.Setup("github.com/realglobe-Inc", param.logType, param.logLv, param); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	if err := serve(param); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	log.Info("Shut down")
}

func serve(param *parameters) (err error) {

	// バックエンドの準備。

	redPools := driver.NewRedisPoolSet(param.redTimeout, param.redPoolSize, param.redPoolExpIn)
	defer redPools.Close()
	monPools := driver.NewMongoPoolSet(param.monTimeout)
	defer monPools.Close()

	// 鍵。
	var keyDb keydb.Db
	switch param.keyDbType {
	case "file":
		keyDb = keydb.NewFileDb(param.keyDbPath)
		log.Info("Use keys in directory " + param.keyDbPath)
	case "redis":
		keyDb = keydb.NewRedisCache(keydb.NewFileDb(param.keyDbPath), redPools.Get(param.keyDbAddr), param.keyDbTag+"."+param.selfId, param.keyDbExpIn)
		log.Info("Use keys in directory " + param.keyDbPath + " with redis " + param.keyDbAddr + ": " + param.keyDbTag + "." + param.selfId)
	default:
		return erro.New("invalid key DB type " + param.keyDbType)
	}

	// アカウント情報。
	var acntDb account.Db
	switch param.acntDbType {
	case "mongo":
		pool, err := monPools.Get(param.acntDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		acntDb = account.NewMongoDb(pool, param.acntDbTag, param.acntDbTag2)
		log.Info("Use account info in mongodb " + param.acntDbAddr + ": " + param.acntDbTag + "." + param.acntDbTag2)
	default:
		return erro.New("invalid account DB type " + param.acntDbType)
	}

	// スコープ・属性許可情報。
	var consDb consent.Db
	switch param.consDbType {
	case "memory":
		consDb = consent.NewMemoryDb()
		log.Info("Save consent info in memory")
	case "mongo":
		pool, err := monPools.Get(param.consDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		consDb = consent.NewMongoDb(pool, param.consDbTag, param.consDbTag2)
		log.Info("Save consent info in mongodb " + param.consDbAddr + ": " + param.consDbTag + "." + param.consDbTag2)
	default:
		return erro.New("invalid consent DB type " + param.consDbType)
	}

	// web データ。
	var webDb webdb.Db
	switch param.webDbType {
	case "direct":
		webDb = webdb.NewDirectDb()
		log.Info("Get web data directly")
	case "redis":
		webDb = webdb.NewRedisCache(webdb.NewDirectDb(), redPools.Get(param.webDbAddr), param.webDbTag, param.webDbExpIn)
		log.Info("Get web data with redis " + param.webDbAddr + ": " + param.webDbTag)
	default:
		return erro.New("invalid web data DB type " + param.webDbType)
	}

	// TA 情報。
	var taDb tadb.Db
	switch param.taDbType {
	case "mongo":
		pool, err := monPools.Get(param.taDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		taDb = tadb.NewMongoDb(pool, param.taDbTag, param.taDbTag2, webDb)
		log.Info("Use TA info in mongodb " + param.taDbAddr + ": " + param.taDbTag + "." + param.taDbTag2)
	default:
		return erro.New("invalid TA DB type " + param.taDbType)
	}

	// セクタ固有のアカウント ID の計算に使う情報。
	var sectDb sector.Db
	switch param.sectDbType {
	case "memory":
		sectDb = sector.NewMemoryDb()
		log.Info("Save pairwise account ID calculation info in memory")
	case "mongo":
		pool, err := monPools.Get(param.sectDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		sectDb = sector.NewMongoDb(pool, param.sectDbTag, param.sectDbTag2)
		log.Info("Save pairwise account ID calculation info in mongodb " + param.sectDbAddr + ": " + param.sectDbTag + "." + param.sectDbTag2)
	default:
		return erro.New("invalid pairwise account ID calculation info DB type " + param.sectDbType)
	}

	// セクタ固有のアカウント ID 情報。
	var pwDb pairwise.Db
	switch param.pwDbType {
	case "memory":
		pwDb = pairwise.NewMemoryDb()
		log.Info("Save pairwise account IDs in memory")
	case "mongo":
		pool, err := monPools.Get(param.pwDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		pwDb = pairwise.NewMongoDb(pool, param.pwDbTag, param.pwDbTag2)
		log.Info("Save pairwise account IDs in mongodb " + param.pwDbAddr + ": " + param.pwDbTag + "." + param.pwDbTag2)
	default:
		return erro.New("invalid pairwise account ID DB type " + param.pwDbType)
	}

	// IdP 情報。
	var idpDb idpdb.Db
	switch param.idpDbType {
	case "mongo":
		pool, err := monPools.Get(param.idpDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		idpDb = idpdb.NewMongoDb(pool, param.idpDbTag, param.idpDbTag2, webDb)
		log.Info("Use IdP info in mongodb " + param.idpDbAddr + ": " + param.idpDbTag + "." + param.idpDbTag2)
	default:
		return erro.New("invalid IdP DB type " + param.idpDbType)
	}

	// セッション。
	var sessDb session.Db
	switch param.sessDbType {
	case "memory":
		sessDb = session.NewMemoryDb()
		log.Info("Save sessions in memory")
	case "redis":
		sessDb = session.NewRedisDb(redPools.Get(param.sessDbAddr), param.sessDbTag)
		log.Info("Save sessions in redis " + param.sessDbAddr + ": " + param.sessDbTag)
	default:
		return erro.New("invalid session DB type " + param.sessDbType)
	}

	// 認可コード。
	var acodDb authcode.Db
	switch param.acodDbType {
	case "memory":
		acodDb = authcode.NewMemoryDb()
		log.Info("Save authorization codes in memory")
	case "redis":
		acodDb = authcode.NewRedisDb(redPools.Get(param.acodDbAddr), param.acodDbTag)
		log.Info("Save authorization codes in redis " + param.acodDbAddr + ": " + param.acodDbTag)
	default:
		return erro.New("invalid authorization code DB type " + param.acodDbType)
	}

	// アクセストークン。
	var tokDb token.Db
	switch param.tokDbType {
	case "memory":
		tokDb = token.NewMemoryDb()
		log.Info("Save access tokens in memory")
	case "redis":
		tokDb = token.NewRedisDb(redPools.Get(param.tokDbAddr), param.tokDbTag)
		log.Info("Save access tokens in redis " + param.tokDbAddr + ": " + param.tokDbTag)
	default:
		return erro.New("invalid access token DB type " + param.tokDbType)
	}

	// 仲介コード。
	var ccodDb coopcode.Db
	switch param.ccodDbType {
	case "memory":
		ccodDb = coopcode.NewMemoryDb()
		log.Info("Save cooperation codes in memory")
	case "redis":
		ccodDb = coopcode.NewRedisDb(redPools.Get(param.ccodDbAddr), param.ccodDbTag)
		log.Info("Save cooperation codes in redis " + param.ccodDbAddr + ": " + param.ccodDbTag)
	default:
		return erro.New("invalid cooperation code DB type " + param.ccodDbType)
	}

	// JWT の ID。
	var jtiDb jtidb.Db
	switch param.jtiDbType {
	case "memory":
		jtiDb = jtidb.NewMemoryDb()
		log.Info("Save JWT IDs in memory")
	case "redis":
		jtiDb = jtidb.NewRedisDb(redPools.Get(param.jtiDbAddr), param.jtiDbTag)
		log.Info("Save JWT IDs in redis " + param.jtiDbAddr + ": " + param.jtiDbTag)
	default:
		return erro.New("invalid JWT ID DB type " + param.jtiDbType)
	}

	sys := &system{
		param.selfId,
		param.sigAlg,
		param.sigKid,

		param.pathTok,
		param.pathTa,
		param.pathSelUi,
		param.pathLginUi,
		param.pathConsUi,
		param.pathErrUi,

		param.pwSaltLen,
		param.sessLen,
		param.sessExpIn,
		param.sessRefDelay,
		param.sessDbExpIn,
		param.acodLen,
		param.acodExpIn,
		param.acodDbExpIn,
		param.tokLen,
		param.tokExpIn,
		param.tokDbExpIn,
		param.ccodLen,
		param.ccodExpIn,
		param.ccodDbExpIn,
		param.jtiLen,
		param.jtiExpIn,
		param.jtiDbExpIn,
		param.ticLen,

		keyDb,
		webDb,
		acntDb,
		consDb,
		taDb,
		sectDb,
		pwDb,
		idpDb,
		sessDb,
		acodDb,
		tokDb,
		ccodDb,
		jtiDb,

		param.cookPath,
		param.cookSec,
	}

	// バックエンドの準備完了。

	s := server.NewStopper()
	defer func() {
		// 処理の終了待ち。
		s.Lock()
		defer s.Unlock()
		for s.Stopped() {
			s.Wait()
		}
	}()

	mux := http.NewServeMux()

	mux.HandleFunc("/", panicErrorWrapper(s, func(w http.ResponseWriter, r *http.Request) error {
		return erro.Wrap(idperr.New(idperr.Invalid_request, "invalid endpoint", http.StatusNotFound, nil))
	}))
	mux.HandleFunc(param.pathOk, panicErrorWrapper(s, func(w http.ResponseWriter, r *http.Request) error {
		return nil
	}))
	mux.HandleFunc(param.pathAuth, panicErrorWrapper(s, sys.authPage))
	mux.HandleFunc(param.pathSel, panicErrorWrapper(s, sys.selectPage))
	mux.HandleFunc(param.pathLgin, panicErrorWrapper(s, sys.lginPage))
	mux.HandleFunc(param.pathCons, panicErrorWrapper(s, sys.consentPage))
	mux.HandleFunc(param.pathTa, panicErrorWrapper(s, sys.taApiHandler().ServeHTTP))
	mux.HandleFunc(param.pathTok, panicErrorWrapper(s, sys.tokenApi))
	mux.HandleFunc(param.pathAcnt, panicErrorWrapper(s, sys.accountApi))
	mux.HandleFunc(param.pathCoopFr, panicErrorWrapper(s, sys.cooperateFromApi))
	mux.HandleFunc(param.pathCoopTo, panicErrorWrapper(s, sys.cooperateToApi))
	if param.uiDir != "" {
		// ファイル配信も自前でやる。
		pathUi := strings.TrimRight(param.pathUi, "/") + "/"
		filer := http.StripPrefix(pathUi, http.FileServer(http.Dir(param.uiDir)))
		mux.Handle(pathUi, filer)
	}

	return server.Serve(param, mux)
}
<commit_msg>不要な変数を削除<commit_after>// Copyright 2015 realglobe, Inc.
//
// 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 main

import (
	"github.com/realglobe-Inc/edo-id-provider/database/account"
	"github.com/realglobe-Inc/edo-id-provider/database/authcode"
	"github.com/realglobe-Inc/edo-id-provider/database/consent"
	"github.com/realglobe-Inc/edo-id-provider/database/coopcode"
	jtidb "github.com/realglobe-Inc/edo-id-provider/database/jti"
	keydb "github.com/realglobe-Inc/edo-id-provider/database/key"
	"github.com/realglobe-Inc/edo-id-provider/database/pairwise"
	"github.com/realglobe-Inc/edo-id-provider/database/sector"
	"github.com/realglobe-Inc/edo-id-provider/database/session"
	"github.com/realglobe-Inc/edo-id-provider/database/token"
	idpdb "github.com/realglobe-Inc/edo-idp-selector/database/idp"
	tadb "github.com/realglobe-Inc/edo-idp-selector/database/ta"
	webdb "github.com/realglobe-Inc/edo-idp-selector/database/web"
	idperr "github.com/realglobe-Inc/edo-idp-selector/error"
	"github.com/realglobe-Inc/edo-lib/driver"
	logutil "github.com/realglobe-Inc/edo-lib/log"
	"github.com/realglobe-Inc/edo-lib/server"
	"github.com/realglobe-Inc/go-lib/erro"
	"github.com/realglobe-Inc/go-lib/rglog"
	"net/http"
	"os"
	"strings"
)

func main() {
	var exitCode = 0
	defer func() {
		if exitCode != 0 {
			os.Exit(exitCode)
		}
	}()

	defer rglog.Flush()

	logutil.InitConsole("github.com/realglobe-Inc")

	param, err := parseParameters(os.Args...)
	if err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	logutil.SetupConsole("github.com/realglobe-Inc", param.consLv)
	if err := logutil.Setup("github.com/realglobe-Inc", param.logType, param.logLv, param); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	if err := serve(param); err != nil {
		log.Err(erro.Unwrap(err))
		log.Debug(erro.Wrap(err))
		exitCode = 1
		return
	}

	log.Info("Shut down")
}

func serve(param *parameters) (err error) {

	// バックエンドの準備。

	redPools := driver.NewRedisPoolSet(param.redTimeout, param.redPoolSize, param.redPoolExpIn)
	defer redPools.Close()
	monPools := driver.NewMongoPoolSet(param.monTimeout)
	defer monPools.Close()

	// 鍵。
	var keyDb keydb.Db
	switch param.keyDbType {
	case "file":
		keyDb = keydb.NewFileDb(param.keyDbPath)
		log.Info("Use keys in directory " + param.keyDbPath)
	case "redis":
		keyDb = keydb.NewRedisCache(keydb.NewFileDb(param.keyDbPath), redPools.Get(param.keyDbAddr), param.keyDbTag+"."+param.selfId, param.keyDbExpIn)
		log.Info("Use keys in directory " + param.keyDbPath + " with redis " + param.keyDbAddr + ": " + param.keyDbTag + "." + param.selfId)
	default:
		return erro.New("invalid key DB type " + param.keyDbType)
	}

	// アカウント情報。
	var acntDb account.Db
	switch param.acntDbType {
	case "mongo":
		pool, err := monPools.Get(param.acntDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		acntDb = account.NewMongoDb(pool, param.acntDbTag, param.acntDbTag2)
		log.Info("Use account info in mongodb " + param.acntDbAddr + ": " + param.acntDbTag + "." + param.acntDbTag2)
	default:
		return erro.New("invalid account DB type " + param.acntDbType)
	}

	// スコープ・属性許可情報。
	var consDb consent.Db
	switch param.consDbType {
	case "memory":
		consDb = consent.NewMemoryDb()
		log.Info("Save consent info in memory")
	case "mongo":
		pool, err := monPools.Get(param.consDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		consDb = consent.NewMongoDb(pool, param.consDbTag, param.consDbTag2)
		log.Info("Save consent info in mongodb " + param.consDbAddr + ": " + param.consDbTag + "." + param.consDbTag2)
	default:
		return erro.New("invalid consent DB type " + param.consDbType)
	}

	// web データ。
	var webDb webdb.Db
	switch param.webDbType {
	case "direct":
		webDb = webdb.NewDirectDb()
		log.Info("Get web data directly")
	case "redis":
		webDb = webdb.NewRedisCache(webdb.NewDirectDb(), redPools.Get(param.webDbAddr), param.webDbTag, param.webDbExpIn)
		log.Info("Get web data with redis " + param.webDbAddr + ": " + param.webDbTag)
	default:
		return erro.New("invalid web data DB type " + param.webDbType)
	}

	// TA 情報。
	var taDb tadb.Db
	switch param.taDbType {
	case "mongo":
		pool, err := monPools.Get(param.taDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		taDb = tadb.NewMongoDb(pool, param.taDbTag, param.taDbTag2, webDb)
		log.Info("Use TA info in mongodb " + param.taDbAddr + ": " + param.taDbTag + "." + param.taDbTag2)
	default:
		return erro.New("invalid TA DB type " + param.taDbType)
	}

	// セクタ固有のアカウント ID の計算に使う情報。
	var sectDb sector.Db
	switch param.sectDbType {
	case "memory":
		sectDb = sector.NewMemoryDb()
		log.Info("Save pairwise account ID calculation info in memory")
	case "mongo":
		pool, err := monPools.Get(param.sectDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		sectDb = sector.NewMongoDb(pool, param.sectDbTag, param.sectDbTag2)
		log.Info("Save pairwise account ID calculation info in mongodb " + param.sectDbAddr + ": " + param.sectDbTag + "." + param.sectDbTag2)
	default:
		return erro.New("invalid pairwise account ID calculation info DB type " + param.sectDbType)
	}

	// セクタ固有のアカウント ID 情報。
	var pwDb pairwise.Db
	switch param.pwDbType {
	case "memory":
		pwDb = pairwise.NewMemoryDb()
		log.Info("Save pairwise account IDs in memory")
	case "mongo":
		pool, err := monPools.Get(param.pwDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		pwDb = pairwise.NewMongoDb(pool, param.pwDbTag, param.pwDbTag2)
		log.Info("Save pairwise account IDs in mongodb " + param.pwDbAddr + ": " + param.pwDbTag + "." + param.pwDbTag2)
	default:
		return erro.New("invalid pairwise account ID DB type " + param.pwDbType)
	}

	// IdP 情報。
	var idpDb idpdb.Db
	switch param.idpDbType {
	case "mongo":
		pool, err := monPools.Get(param.idpDbAddr)
		if err != nil {
			return erro.Wrap(err)
		}
		idpDb = idpdb.NewMongoDb(pool, param.idpDbTag, param.idpDbTag2, webDb)
		log.Info("Use IdP info in mongodb " + param.idpDbAddr + ": " + param.idpDbTag + "." + param.idpDbTag2)
	default:
		return erro.New("invalid IdP DB type " + param.idpDbType)
	}

	// セッション。
	var sessDb session.Db
	switch param.sessDbType {
	case "memory":
		sessDb = session.NewMemoryDb()
		log.Info("Save sessions in memory")
	case "redis":
		sessDb = session.NewRedisDb(redPools.Get(param.sessDbAddr), param.sessDbTag)
		log.Info("Save sessions in redis " + param.sessDbAddr + ": " + param.sessDbTag)
	default:
		return erro.New("invalid session DB type " + param.sessDbType)
	}

	// 認可コード。
	var acodDb authcode.Db
	switch param.acodDbType {
	case "memory":
		acodDb = authcode.NewMemoryDb()
		log.Info("Save authorization codes in memory")
	case "redis":
		acodDb = authcode.NewRedisDb(redPools.Get(param.acodDbAddr), param.acodDbTag)
		log.Info("Save authorization codes in redis " + param.acodDbAddr + ": " + param.acodDbTag)
	default:
		return erro.New("invalid authorization code DB type " + param.acodDbType)
	}

	// アクセストークン。
	var tokDb token.Db
	switch param.tokDbType {
	case "memory":
		tokDb = token.NewMemoryDb()
		log.Info("Save access tokens in memory")
	case "redis":
		tokDb = token.NewRedisDb(redPools.Get(param.tokDbAddr), param.tokDbTag)
		log.Info("Save access tokens in redis " + param.tokDbAddr + ": " + param.tokDbTag)
	default:
		return erro.New("invalid access token DB type " + param.tokDbType)
	}

	// 仲介コード。
	var ccodDb coopcode.Db
	switch param.ccodDbType {
	case "memory":
		ccodDb = coopcode.NewMemoryDb()
		log.Info("Save cooperation codes in memory")
	case "redis":
		ccodDb = coopcode.NewRedisDb(redPools.Get(param.ccodDbAddr), param.ccodDbTag)
		log.Info("Save cooperation codes in redis " + param.ccodDbAddr + ": " + param.ccodDbTag)
	default:
		return erro.New("invalid cooperation code DB type " + param.ccodDbType)
	}

	// JWT の ID。
	var jtiDb jtidb.Db
	switch param.jtiDbType {
	case "memory":
		jtiDb = jtidb.NewMemoryDb()
		log.Info("Save JWT IDs in memory")
	case "redis":
		jtiDb = jtidb.NewRedisDb(redPools.Get(param.jtiDbAddr), param.jtiDbTag)
		log.Info("Save JWT IDs in redis " + param.jtiDbAddr + ": " + param.jtiDbTag)
	default:
		return erro.New("invalid JWT ID DB type " + param.jtiDbType)
	}

	sys := &system{
		param.selfId,
		param.sigAlg,
		param.sigKid,

		param.pathTok,
		param.pathTa,
		param.pathSelUi,
		param.pathLginUi,
		param.pathConsUi,
		param.pathErrUi,

		param.pwSaltLen,
		param.sessLen,
		param.sessExpIn,
		param.sessRefDelay,
		param.sessDbExpIn,
		param.acodLen,
		param.acodExpIn,
		param.acodDbExpIn,
		param.tokLen,
		param.tokExpIn,
		param.tokDbExpIn,
		param.ccodLen,
		param.ccodExpIn,
		param.ccodDbExpIn,
		param.jtiLen,
		param.jtiExpIn,
		param.jtiDbExpIn,
		param.ticLen,

		keyDb,
		webDb,
		acntDb,
		consDb,
		taDb,
		sectDb,
		pwDb,
		idpDb,
		sessDb,
		acodDb,
		tokDb,
		ccodDb,
		jtiDb,

		param.cookPath,
		param.cookSec,
	}

	// バックエンドの準備完了。

	s := server.NewStopper()
	defer func() {
		// 処理の終了待ち。
		s.Lock()
		defer s.Unlock()
		for s.Stopped() {
			s.Wait()
		}
	}()

	mux := http.NewServeMux()

	mux.HandleFunc("/", panicErrorWrapper(s, func(w http.ResponseWriter, r *http.Request) error {
		return erro.Wrap(idperr.New(idperr.Invalid_request, "invalid endpoint", http.StatusNotFound, nil))
	}))
	mux.HandleFunc(param.pathOk, panicErrorWrapper(s, func(w http.ResponseWriter, r *http.Request) error {
		return nil
	}))
	mux.HandleFunc(param.pathAuth, panicErrorWrapper(s, sys.authPage))
	mux.HandleFunc(param.pathSel, panicErrorWrapper(s, sys.selectPage))
	mux.HandleFunc(param.pathLgin, panicErrorWrapper(s, sys.lginPage))
	mux.HandleFunc(param.pathCons, panicErrorWrapper(s, sys.consentPage))
	mux.HandleFunc(param.pathTa, panicErrorWrapper(s, sys.taApiHandler().ServeHTTP))
	mux.HandleFunc(param.pathTok, panicErrorWrapper(s, sys.tokenApi))
	mux.HandleFunc(param.pathAcnt, panicErrorWrapper(s, sys.accountApi))
	mux.HandleFunc(param.pathCoopFr, panicErrorWrapper(s, sys.cooperateFromApi))
	mux.HandleFunc(param.pathCoopTo, panicErrorWrapper(s, sys.cooperateToApi))
	if param.uiDir != "" {
		// ファイル配信も自前でやる。
		pathUi := strings.TrimRight(param.pathUi, "/") + "/"
		mux.Handle(pathUi, http.StripPrefix(pathUi, http.FileServer(http.Dir(param.uiDir))))
	}

	return server.Serve(param, mux)
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"fmt"

	"github.com/rafaeljusto/cctldstats/config"
)

// Connection database connection.
var Connection *sql.DB

// Connect performs the database connection. Today the following databases are supported: mysql and postgres
func Connect() (err error) {
	var connParams string
	switch config.CCTLDStats.Database.Kind {
	case "mysql":
		connParams = fmt.Sprintf("%s:%s@tcp(%s)/%s",
			config.CCTLDStats.Database.Username,
			config.CCTLDStats.Database.Password,
			config.CCTLDStats.Database.Host,
			config.CCTLDStats.Database.Name,
		)
	case "postgres":
		connParams = fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=verify-full",
			config.CCTLDStats.Database.Username,
			config.CCTLDStats.Database.Password,
			config.CCTLDStats.Database.Host,
			config.CCTLDStats.Database.Name,
		)
	}

	Connection, err = sql.Open(config.CCTLDStats.Database.Kind, connParams)
	return
}
<commit_msg>Disable SSL mode in DB connection for now<commit_after>package db

import (
	"database/sql"
	"fmt"

	"github.com/rafaeljusto/cctldstats/config"
)

// Connection database connection.
var Connection *sql.DB

// Connect performs the database connection. Today the following databases are supported: mysql and postgres
func Connect() (err error) {
	var connParams string
	switch config.CCTLDStats.Database.Kind {
	case "mysql":
		connParams = fmt.Sprintf("%s:%s@tcp(%s)/%s",
			config.CCTLDStats.Database.Username,
			config.CCTLDStats.Database.Password,
			config.CCTLDStats.Database.Host,
			config.CCTLDStats.Database.Name,
		)
	case "postgres":
		connParams = fmt.Sprintf("postgres://%s:%s@%s/%s",
			config.CCTLDStats.Database.Username,
			config.CCTLDStats.Database.Password,
			config.CCTLDStats.Database.Host,
			config.CCTLDStats.Database.Name,
		)
	}

	Connection, err = sql.Open(config.CCTLDStats.Database.Kind, connParams)
	return
}
<|endoftext|>