<commit_before>// Package main defines a command line interface for the sqlboiler package
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/kat-co/vala"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/volatiletech/sqlboiler/boilingcore"
	"github.com/volatiletech/sqlboiler/drivers"
	"github.com/volatiletech/sqlboiler/importers"
)

const sqlBoilerVersion = "2.6.0"

var (
	flagConfigFile string
	cmdState       *boilingcore.State
	cmdConfig      *boilingcore.Config
)

func initConfig() {
	if len(flagConfigFile) == 0 {
		viper.SetConfigFile(flagConfigFile)
		if err := viper.ReadInConfig(); err != nil {
			fmt.Println("Can't read config:", err)
			os.Exit(1)
		}
		return
	}

	var err error
	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Ignore errors here, fallback to other validation methods.
	// Users can use environment variables if a config is not found.
	_ = viper.ReadInConfig()
}

func main() {
	// Too much happens between here and cobra's argument handling, for
	// something so simple just do it immediately.
	for _, arg := range os.Args {
		if arg == "--version" {
			fmt.Println("SQLBoiler v" + sqlBoilerVersion)
			return
		}
	}

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler [flags] <driver>",
		Short: "SQL Boiler generates an ORM tailored to your database schema.",
		Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" +
			`Complete documentation is available at http://github.com/volatiletech/sqlboiler`,
		Example:       `sqlboiler psql`,
		PreRunE:       preRun,
		RunE:          run,
		PostRunE:      postRun,
		SilenceErrors: true,
		SilenceUsage:  true,
	}

	cobra.OnInitialize(initConfig)

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringVar(&flagConfigFile, "config", "Supply the name of the config file to override the default lookup", "config file")
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
	rootCmd.PersistentFlags().StringP("basedir", "", "", "The base directory has the templates and templates_test folders")
	rootCmd.PersistentFlags().StringSliceP("tag", "t", nil, "Struct tags to be included on your models in addition to json, yaml, toml")
	rootCmd.PersistentFlags().StringSliceP("replace", "", nil, "Replace templates by directory: relpath/to_file.tpl:relpath/to_replacement.tpl")
	rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
	rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
	rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
	rootCmd.PersistentFlags().BoolP("no-auto-timestamps", "", false, "Disable automatic timestamps for created_at/updated_at")
	rootCmd.PersistentFlags().BoolP("version", "", false, "Print the version")
	rootCmd.PersistentFlags().BoolP("wipe", "", false, "Delete the output folder (rm -rf) before generation to ensure sanity")
	rootCmd.PersistentFlags().StringP("struct-tag-casing", "", "snake", "Decides the casing for go structure tag names. camel or snake (default snake)")

	// hide flags not recommended for use
	rootCmd.PersistentFlags().MarkHidden("replace")

	viper.BindPFlags(rootCmd.PersistentFlags())
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	viper.AutomaticEnv()

	if err := rootCmd.Execute(); err != nil {
		if e, ok := err.(commandFailure); ok {
			fmt.Printf("Error: %v\n\n", string(e))
			rootCmd.Help()
		} else if !viper.GetBool("debug") {
			fmt.Printf("Error: %v\n", err)
		} else {
			fmt.Printf("Error: %+v\n", err)
		}

		os.Exit(1)
	}
}

type commandFailure string

func (c commandFailure) Error() string {
	return string(c)
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return commandFailure("must provide a driver name")
	}

	driverName := args[0]
	driverPath := args[0]
	if strings.ContainsRune(driverName, os.PathSeparator) {
		driverName = strings.Replace(filepath.Base(driverName), "sqlboiler-", "", 1)
	} else {
		driverPath = "sqlboiler-" + driverPath
	}

	driverPath, err = filepath.Abs(driverPath)
	if err != nil {
		return errors.Wrap(err, "could not find absolute path to driver")
	}
	drivers.RegisterBinary(driverName, driverPath)

	cmdConfig = &boilingcore.Config{
		DriverName:       driverName,
		OutFolder:        viper.GetString("output"),
		PkgName:          viper.GetString("pkgname"),
		BaseDir:          viper.GetString("basedir"),
		Debug:            viper.GetBool("debug"),
		NoTests:          viper.GetBool("no-tests"),
		NoHooks:          viper.GetBool("no-hooks"),
		NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
		Wipe:             viper.GetBool("wipe"),
		StructTagCasing:  strings.ToLower(viper.GetString("struct-tag-casing")), // camel | snake
		Tags:             viper.GetStringSlice("tag"),
		Replacements:     viper.GetStringSlice("replace"),
	}

	// Configure the driver
	cmdConfig.DriverConfig = map[string]interface{}{
		"whitelist": viper.GetStringSlice(driverName + ".whitelist"),
		"blacklist": viper.GetStringSlice(driverName + ".blacklist"),
	}

	var validationRules []vala.Checker
	required := []string{"user", "host", "port", "dbname", "sslmode"}

	//TODO(aarondl): Move these defaults into the drivers themselves, why are they here again? :D
	switch driverName {
	case "psql":
		viper.SetDefault("psql.schema", "public")
		viper.SetDefault("psql.port", 5432)
		viper.SetDefault("psql.sslmode", "require")
		required = append(required, "schema")
	case "mysql":
		viper.Set("mysql.schema", viper.GetString("mysql.dbname"))
		viper.SetDefault("mysql.sslmode", "true")
		viper.SetDefault("mysql.port", 3306)
	case "mssql":
		viper.SetDefault("mssql.schema", "dbo")
		viper.SetDefault("mssql.sslmode", "true")
		viper.SetDefault("mssql.port", 1433)
		required = append(required, "schema")
	}

	if validationRules == nil {
		for _, r := range required {
			key := fmt.Sprintf("%s.%s", driverName, r)
			switch r {
			case "port":
				validationRules = append(validationRules, vala.Not(vala.Equals(viper.GetInt(key), 0, key)))
			default:
				validationRules = append(validationRules, vala.StringNotEmpty(viper.GetString(key), key))
			}
		}
	}

	if err := vala.BeginValidation().Validate(validationRules...).Check(); err != nil {
		return commandFailure(err.Error())
	}

	keys := allKeys(driverName)
	for _, key := range keys {
		prefixedKey := fmt.Sprintf("%s.%s", driverName, key)
		cmdConfig.DriverConfig[key] = viper.Get(prefixedKey)
	}

	cmdConfig.Imports = configureImports()

	cmdState, err = boilingcore.New(cmdConfig)
	return err
}

func configureImports() importers.Collection {
	imports := importers.NewDefaultImports()

	mustMap := func(m importers.Map, err error) importers.Map {
		if err != nil {
			panic("failed to change viper interface into importers.Map: " + err.Error())
		}

		return m
	}

	if viper.IsSet("imports.all.standard") {
		imports.All.Standard = viper.GetStringSlice("imports.all.standard")
	}
	if viper.IsSet("imports.all.third_party") {
		imports.All.ThirdParty = viper.GetStringSlice("imports.all.third_party")
	}
	if viper.IsSet("imports.test.standard") {
		imports.Test.Standard = viper.GetStringSlice("imports.test.standard")
	}
	if viper.IsSet("imports.test.third_party") {
		imports.Test.ThirdParty = viper.GetStringSlice("imports.test.third_party")
	}
	if viper.IsSet("imports.singleton") {
		imports.Singleton = mustMap(importers.MapFromInterface(viper.Get("imports.singleton")))
	}
	if viper.IsSet("imports.test_singleton") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.test_singleton")))
	}
	if viper.IsSet("imports.test_main") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.test_main")))
	}
	if viper.IsSet("imports.based_on_type") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.based_on_type")))
	}

	return imports
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}

func allKeys(prefix string) []string {
	keys := make(map[string]bool)

	prefix = prefix + "."

	for _, e := range os.Environ() {
		splits := strings.SplitN(e, "=", 2)
		key := strings.Replace(strings.ToLower(splits[0]), "_", ".", -1)

		if strings.HasPrefix(key, prefix) {
			keys[strings.Replace(key, prefix, "", -1)] = true
		}
	}

	for _, key := range viper.AllKeys() {
		if strings.HasPrefix(key, prefix) {
			keys[strings.Replace(key, prefix, "", -1)] = true
		}
	}

	keySlice := make([]string, 0, len(keys))
	for k := range keys {
		keySlice = append(keySlice, k)
	}
	return keySlice
}
<commit_msg>Bump version to 3.0.0-pre<commit_after>// Package main defines a command line interface for the sqlboiler package
package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/kat-co/vala"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/volatiletech/sqlboiler/boilingcore"
	"github.com/volatiletech/sqlboiler/drivers"
	"github.com/volatiletech/sqlboiler/importers"
)

const sqlBoilerVersion = "3.0.0-pre"

var (
	flagConfigFile string
	cmdState       *boilingcore.State
	cmdConfig      *boilingcore.Config
)

func initConfig() {
	if len(flagConfigFile) == 0 {
		viper.SetConfigFile(flagConfigFile)
		if err := viper.ReadInConfig(); err != nil {
			fmt.Println("Can't read config:", err)
			os.Exit(1)
		}
		return
	}

	var err error
	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Ignore errors here, fallback to other validation methods.
	// Users can use environment variables if a config is not found.
	_ = viper.ReadInConfig()
}

func main() {
	// Too much happens between here and cobra's argument handling, for
	// something so simple just do it immediately.
	for _, arg := range os.Args {
		if arg == "--version" {
			fmt.Println("SQLBoiler v" + sqlBoilerVersion)
			return
		}
	}

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler [flags] <driver>",
		Short: "SQL Boiler generates an ORM tailored to your database schema.",
		Long: "SQL Boiler generates a Go ORM from template files, tailored to your database schema.\n" +
			`Complete documentation is available at http://github.com/volatiletech/sqlboiler`,
		Example:       `sqlboiler psql`,
		PreRunE:       preRun,
		RunE:          run,
		PostRunE:      postRun,
		SilenceErrors: true,
		SilenceUsage:  true,
	}

	cobra.OnInitialize(initConfig)

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringVarP(&flagConfigFile, "config", "c", "", "Filename of config file to override default lookup")
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
	rootCmd.PersistentFlags().StringP("basedir", "", "", "The base directory has the templates and templates_test folders")
	rootCmd.PersistentFlags().StringSliceP("tag", "t", nil, "Struct tags to be included on your models in addition to json, yaml, toml")
	rootCmd.PersistentFlags().StringSliceP("replace", "", nil, "Replace templates by directory: relpath/to_file.tpl:relpath/to_replacement.tpl")
	rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
	rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
	rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
	rootCmd.PersistentFlags().BoolP("no-auto-timestamps", "", false, "Disable automatic timestamps for created_at/updated_at")
	rootCmd.PersistentFlags().BoolP("version", "", false, "Print the version")
	rootCmd.PersistentFlags().BoolP("wipe", "", false, "Delete the output folder (rm -rf) before generation to ensure sanity")
	rootCmd.PersistentFlags().StringP("struct-tag-casing", "", "snake", "Decides the casing for go structure tag names. camel or snake (default snake)")

	// hide flags not recommended for use
	rootCmd.PersistentFlags().MarkHidden("replace")

	viper.BindPFlags(rootCmd.PersistentFlags())
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	viper.AutomaticEnv()

	if err := rootCmd.Execute(); err != nil {
		if e, ok := err.(commandFailure); ok {
			fmt.Printf("Error: %v\n\n", string(e))
			rootCmd.Help()
		} else if !viper.GetBool("debug") {
			fmt.Printf("Error: %v\n", err)
		} else {
			fmt.Printf("Error: %+v\n", err)
		}

		os.Exit(1)
	}
}

type commandFailure string

func (c commandFailure) Error() string {
	return string(c)
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return commandFailure("must provide a driver name")
	}

	driverName := args[0]
	driverPath := args[0]
	if strings.ContainsRune(driverName, os.PathSeparator) {
		driverName = strings.Replace(filepath.Base(driverName), "sqlboiler-", "", 1)
	} else {
		driverPath = "sqlboiler-" + driverPath
	}

	driverPath, err = filepath.Abs(driverPath)
	if err != nil {
		return errors.Wrap(err, "could not find absolute path to driver")
	}
	drivers.RegisterBinary(driverName, driverPath)

	cmdConfig = &boilingcore.Config{
		DriverName:       driverName,
		OutFolder:        viper.GetString("output"),
		PkgName:          viper.GetString("pkgname"),
		BaseDir:          viper.GetString("basedir"),
		Debug:            viper.GetBool("debug"),
		NoTests:          viper.GetBool("no-tests"),
		NoHooks:          viper.GetBool("no-hooks"),
		NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
		Wipe:             viper.GetBool("wipe"),
		StructTagCasing:  strings.ToLower(viper.GetString("struct-tag-casing")), // camel | snake
		Tags:             viper.GetStringSlice("tag"),
		Replacements:     viper.GetStringSlice("replace"),
	}

	// Configure the driver
	cmdConfig.DriverConfig = map[string]interface{}{
		"whitelist": viper.GetStringSlice(driverName + ".whitelist"),
		"blacklist": viper.GetStringSlice(driverName + ".blacklist"),
	}

	var validationRules []vala.Checker
	required := []string{"user", "host", "port", "dbname", "sslmode"}

	//TODO(aarondl): Move these defaults into the drivers themselves, why are they here again? :D
	switch driverName {
	case "psql":
		viper.SetDefault("psql.schema", "public")
		viper.SetDefault("psql.port", 5432)
		viper.SetDefault("psql.sslmode", "require")
		required = append(required, "schema")
	case "mysql":
		viper.Set("mysql.schema", viper.GetString("mysql.dbname"))
		viper.SetDefault("mysql.sslmode", "true")
		viper.SetDefault("mysql.port", 3306)
	case "mssql":
		viper.SetDefault("mssql.schema", "dbo")
		viper.SetDefault("mssql.sslmode", "true")
		viper.SetDefault("mssql.port", 1433)
		required = append(required, "schema")
	}

	if validationRules == nil {
		for _, r := range required {
			key := fmt.Sprintf("%s.%s", driverName, r)
			switch r {
			case "port":
				validationRules = append(validationRules, vala.Not(vala.Equals(viper.GetInt(key), 0, key)))
			default:
				validationRules = append(validationRules, vala.StringNotEmpty(viper.GetString(key), key))
			}
		}
	}

	if err := vala.BeginValidation().Validate(validationRules...).Check(); err != nil {
		return commandFailure(err.Error())
	}

	keys := allKeys(driverName)
	for _, key := range keys {
		prefixedKey := fmt.Sprintf("%s.%s", driverName, key)
		cmdConfig.DriverConfig[key] = viper.Get(prefixedKey)
	}

	cmdConfig.Imports = configureImports()

	cmdState, err = boilingcore.New(cmdConfig)
	return err
}

func configureImports() importers.Collection {
	imports := importers.NewDefaultImports()

	mustMap := func(m importers.Map, err error) importers.Map {
		if err != nil {
			panic("failed to change viper interface into importers.Map: " + err.Error())
		}

		return m
	}

	if viper.IsSet("imports.all.standard") {
		imports.All.Standard = viper.GetStringSlice("imports.all.standard")
	}
	if viper.IsSet("imports.all.third_party") {
		imports.All.ThirdParty = viper.GetStringSlice("imports.all.third_party")
	}
	if viper.IsSet("imports.test.standard") {
		imports.Test.Standard = viper.GetStringSlice("imports.test.standard")
	}
	if viper.IsSet("imports.test.third_party") {
		imports.Test.ThirdParty = viper.GetStringSlice("imports.test.third_party")
	}
	if viper.IsSet("imports.singleton") {
		imports.Singleton = mustMap(importers.MapFromInterface(viper.Get("imports.singleton")))
	}
	if viper.IsSet("imports.test_singleton") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.test_singleton")))
	}
	if viper.IsSet("imports.test_main") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.test_main")))
	}
	if viper.IsSet("imports.based_on_type") {
		imports.TestSingleton = mustMap(importers.MapFromInterface(viper.Get("imports.based_on_type")))
	}

	return imports
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}

func allKeys(prefix string) []string {
	keys := make(map[string]bool)

	prefix = prefix + "."

	for _, e := range os.Environ() {
		splits := strings.SplitN(e, "=", 2)
		key := strings.Replace(strings.ToLower(splits[0]), "_", ".", -1)

		if strings.HasPrefix(key, prefix) {
			keys[strings.Replace(key, prefix, "", -1)] = true
		}
	}

	for _, key := range viper.AllKeys() {
		if strings.HasPrefix(key, prefix) {
			keys[strings.Replace(key, prefix, "", -1)] = true
		}
	}

	keySlice := make([]string, 0, len(keys))
	for k := range keys {
		keySlice = append(keySlice, k)
	}
	return keySlice
}
<|endoftext|>


<commit_before>package main

import (
    "errors"
    "log"
    "net"
    "time"

    "github.com/cloudfoundry-incubator/notifications/config"
    "github.com/cloudfoundry-incubator/notifications/mail"
    "github.com/cloudfoundry-incubator/notifications/models"
    "github.com/cloudfoundry-incubator/notifications/web"
    "github.com/pivotal-cf/uaa-sso-golang/uaa"
)

func main() {
    defer crash()

    env := config.NewEnvironment()
    configure(env)

    if !env.TestMode {
        confirmSMTPConfiguration(env)
    }
    retrieveUAAPublicKey()
    migrate()

    server := web.NewServer()
    server.Run()
}

func configure(env config.Environment) {
    log.Println("Booting with configuration:")
    log.Printf("\tUAAHost         -> %+v", env.UAAHost)
    log.Printf("\tUAAClientID     -> %+v", env.UAAClientID)
    log.Printf("\tUAAClientSecret -> %+v", env.UAAClientSecret)
    log.Printf("\tSMTPUser        -> %+v", env.SMTPUser)
    log.Printf("\tSMTPPass        -> %+v", env.SMTPPass)
    log.Printf("\tSMTPHost        -> %+v", env.SMTPHost)
    log.Printf("\tSMTPPort        -> %+v", env.SMTPPort)
    log.Printf("\tSMTPTLS         -> %+v", env.SMTPTLS)
    log.Printf("\tSender          -> %+v", env.Sender)
    log.Printf("\tCCHost          -> %+v", env.CCHost)
    log.Printf("\tVerifySSL       -> %+v", env.VerifySSL)
    log.Printf("\tTest mode       -> %+v", env.TestMode)
}

func confirmSMTPConfiguration(env config.Environment) {
    mailClient, err := mail.NewClient(env.SMTPUser, env.SMTPPass, net.JoinHostPort(env.SMTPHost, env.SMTPPort))
    if err != nil {
        panic(err)
    }

    err = mailClient.Connect()
    if err != nil {
        panic(err)
    }

    err = mailClient.Hello()
    if err != nil {
        panic(err)
    }

    startTLSSupported, _ := mailClient.Extension("STARTTLS")

    mailClient.Quit()

    if !startTLSSupported && env.SMTPTLS {
        panic(errors.New(`SMTP TLS configuration mismatch: Configured to use TLS over SMTP, but the mail server does not support the "STARTTLS" extension.`))
    }

    if startTLSSupported && !env.SMTPTLS {
        panic(errors.New(`SMTP TLS configuration mismatch: Not configured to use TLS over SMTP, but the mail server does support the "STARTTLS" extension.`))
    }
}

func retrieveUAAPublicKey() {
    env := config.NewEnvironment()
    auth := uaa.NewUAA("", env.UAAHost, env.UAAClientID, env.UAAClientSecret, "")
    auth.VerifySSL = env.VerifySSL

    key, err := uaa.GetTokenKey(auth)
    if err != nil {
        panic(err)
    }

    config.UAAPublicKey = key
    log.Printf("UAA Public Key: %s", config.UAAPublicKey)
}

func migrate() {
    models.Database()
}

// This is a hack to get the logs to output to the loggregator before the process exits
func crash() {
    err := recover()
    if err != nil {
        time.Sleep(5 * time.Second)
        panic(err)
    }
}
<commit_msg>Prints DatabaseURL when booting<commit_after>package main

import (
    "errors"
    "log"
    "net"
    "time"

    "github.com/cloudfoundry-incubator/notifications/config"
    "github.com/cloudfoundry-incubator/notifications/mail"
    "github.com/cloudfoundry-incubator/notifications/models"
    "github.com/cloudfoundry-incubator/notifications/web"
    "github.com/pivotal-cf/uaa-sso-golang/uaa"
)

func main() {
    defer crash()

    env := config.NewEnvironment()
    configure(env)

    if !env.TestMode {
        confirmSMTPConfiguration(env)
    }
    retrieveUAAPublicKey()
    migrate()

    server := web.NewServer()
    server.Run()
}

func configure(env config.Environment) {
    log.Println("Booting with configuration:")
    log.Printf("\tCCHost          -> %+v", env.CCHost)
    log.Printf("\tDatabaseURL     -> %+v", env.DatabaseURL)
    log.Printf("\tSMTPHost        -> %+v", env.SMTPHost)
    log.Printf("\tSMTPPass        -> %+v", env.SMTPPass)
    log.Printf("\tSMTPPort        -> %+v", env.SMTPPort)
    log.Printf("\tSMTPTLS         -> %+v", env.SMTPTLS)
    log.Printf("\tSMTPUser        -> %+v", env.SMTPUser)
    log.Printf("\tSender          -> %+v", env.Sender)
    log.Printf("\tTest mode       -> %+v", env.TestMode)
    log.Printf("\tUAAClientID     -> %+v", env.UAAClientID)
    log.Printf("\tUAAClientSecret -> %+v", env.UAAClientSecret)
    log.Printf("\tUAAHost         -> %+v", env.UAAHost)
    log.Printf("\tVerifySSL       -> %+v", env.VerifySSL)
}

func confirmSMTPConfiguration(env config.Environment) {
    mailClient, err := mail.NewClient(env.SMTPUser, env.SMTPPass, net.JoinHostPort(env.SMTPHost, env.SMTPPort))
    if err != nil {
        panic(err)
    }

    err = mailClient.Connect()
    if err != nil {
        panic(err)
    }

    err = mailClient.Hello()
    if err != nil {
        panic(err)
    }

    startTLSSupported, _ := mailClient.Extension("STARTTLS")

    mailClient.Quit()

    if !startTLSSupported && env.SMTPTLS {
        panic(errors.New(`SMTP TLS configuration mismatch: Configured to use TLS over SMTP, but the mail server does not support the "STARTTLS" extension.`))
    }

    if startTLSSupported && !env.SMTPTLS {
        panic(errors.New(`SMTP TLS configuration mismatch: Not configured to use TLS over SMTP, but the mail server does support the "STARTTLS" extension.`))
    }
}

func retrieveUAAPublicKey() {
    env := config.NewEnvironment()
    auth := uaa.NewUAA("", env.UAAHost, env.UAAClientID, env.UAAClientSecret, "")
    auth.VerifySSL = env.VerifySSL

    key, err := uaa.GetTokenKey(auth)
    if err != nil {
        panic(err)
    }

    config.UAAPublicKey = key
    log.Printf("UAA Public Key: %s", config.UAAPublicKey)
}

func migrate() {
    models.Database()
}

// This is a hack to get the logs to output to the loggregator before the process exits
func crash() {
    err := recover()
    if err != nil {
        time.Sleep(5 * time.Second)
        panic(err)
    }
}
<|endoftext|>


<commit_before>package main

import (
	"expvar"
	"log"
	"net"
	"net/http"
	"os"
	"sync"
	"text/template"
	"time"

	"github.com/go-recaptcha/recaptcha"
	"github.com/gorilla/handlers"
	"github.com/kelseyhightower/envconfig"
	"github.com/nlopes/slack"
	"github.com/oxtoacart/bpool"
	"github.com/paulbellamy/ratecounter"
)

var captcha *recaptcha.Recaptcha
var api *slack.Client
var bufpool *bpool.BufferPool
var indexTemplate = template.Must(template.New("index.tmpl").ParseFiles("templates/index.tmpl"))

// Slack statistics
var userCount int
var activeUserCount int
var statsMutex sync.RWMutex // Guards slack statistics variables

var m = expvar.NewMap("metrics")
var counter *ratecounter.RateCounter
var hitsPerMinute expvar.Int
var requests expvar.Int
var inviteErrors expvar.Int
var missingFirstName expvar.Int
var missingLastName expvar.Int
var missingEmail expvar.Int
var missingCoC expvar.Int
var successfulCaptcha expvar.Int
var failedCaptcha expvar.Int
var invalidCaptcha expvar.Int
var successfulInvites expvar.Int

// config
var c Specification

type Specification struct {
	Port           string `envconfig:"PORT"`
	CaptchaSitekey string `required:"true"`
	CaptchaSecret  string `required:"true"`
	SlackToken     string `required:"true"`
}

func init() {
	err := envconfig.Process("slackinviter", &c)
	if err != nil {
		log.Fatal(err.Error())
	}
	counter = ratecounter.NewRateCounter(1 * time.Minute)
	m.Set("hits_per_minute", &hitsPerMinute)
	m.Set("requests", &requests)
	m.Set("invite_errors", &inviteErrors)
	m.Set("missing_first_name", &missingFirstName)
	m.Set("missing_last_name", &missingLastName)
	m.Set("missing_email", &missingEmail)
	m.Set("missing_coc", &missingCoC)
	m.Set("failed_captcha", &failedCaptcha)
	m.Set("invalid_captcha", &invalidCaptcha)
	m.Set("successful_captcha", &successfulCaptcha)
	m.Set("successful_invites", &successfulInvites)
	// Init stuff
	captcha = recaptcha.New(c.CaptchaSecret)
	api = slack.New(c.SlackToken)
	bufpool = bpool.NewBufferPool(64)
}
func main() {
	go pollSlack()
	mux := http.NewServeMux()
	mux.HandleFunc("/invite/", handleInvite)
	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
	mux.HandleFunc("/", homepage)
	mux.Handle("/debug/vars", http.DefaultServeMux)
	err := http.ListenAndServe(":"+c.Port, handlers.CombinedLoggingHandler(os.Stdout, mux))
	if err != nil {
		log.Fatal(err.Error())
	}
}
func pollSlack() {
	for {
		users, err := api.GetUsers()
		if err != nil {
			log.Println("error polling slack for users:", err)
			continue
		}
		uCount := 0 // users
		aCount := 0 // active users
		for _, u := range users {
			if u.ID != "USLACKBOT" && !u.IsBot && !u.Deleted {
				uCount += 1
				if u.Presence == "active" {
					aCount += 1
				}
			}
		}
		statsMutex.Lock()
		userCount = uCount
		activeUserCount = aCount
		statsMutex.Unlock()
		time.Sleep(10 * time.Minute)
	}
}

// Homepage renders the homepage
func homepage(w http.ResponseWriter, r *http.Request) {
	counter.Incr(1)
	hitsPerMinute.Set(counter.Rate())
	requests.Add(1)
	statsMutex.RLock()
	data := map[string]interface{}{"SiteKey": c.CaptchaSitekey, "UserCount": userCount, "ActiveCount": activeUserCount}
	statsMutex.RUnlock()
	buf := bufpool.Get()
	defer bufpool.Put(buf)
	err := indexTemplate.Execute(buf, data)
	if err != nil {
		log.Println("error rendering template:", err)
		http.Error(w, "error rendering template :-(", http.StatusInternalServerError)
		return
	}
	// Set the header and write the buffer to the http.ResponseWriter
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	buf.WriteTo(w)
}

// ShowPost renders a single post
func handleInvite(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}
	captchaResponse := r.FormValue("g-recaptcha-response")
	remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		failedCaptcha.Add(1)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	valid, err := captcha.Verify(captchaResponse, remoteIP)
	if err != nil {
		failedCaptcha.Add(1)
		http.Error(w, "Error validating recaptcha.. Did you click it?", http.StatusPreconditionFailed)
		return
	}
	if !valid {
		invalidCaptcha.Add(1)
		http.Error(w, "Invalid recaptcha", http.StatusInternalServerError)
		return

	}
	successfulCaptcha.Add(1)
	fname := r.FormValue("fname")
	lname := r.FormValue("lname")
	email := r.FormValue("email")
	coc := r.FormValue("coc")
	if email == "" {
		missingEmail.Add(1)
		http.Error(w, "Missing email", http.StatusPreconditionFailed)
		return
	}
	if fname == "" {
		missingFirstName.Add(1)
		http.Error(w, "Missing first name", http.StatusPreconditionFailed)
		return
	}
	if lname == "" {
		missingLastName.Add(1)
		http.Error(w, "Missing last name", http.StatusPreconditionFailed)
		return
	}
	if coc != "1" {
		missingCoC.Add(1)
		http.Error(w, "You need to accept the code of conduct", http.StatusPreconditionFailed)
		return
	}
	err = api.InviteToTeam("Gophers", fname, lname, email)
	if err != nil {
		log.Println("InviteToTeam error:", err)
		inviteErrors.Add(1)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	successfulInvites.Add(1)
}
<commit_msg>Enforce HTTPS<commit_after>package main

import (
	"expvar"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"sync"
	"text/template"
	"time"

	"github.com/go-recaptcha/recaptcha"
	"github.com/gorilla/handlers"
	"github.com/kelseyhightower/envconfig"
	"github.com/nlopes/slack"
	"github.com/oxtoacart/bpool"
	"github.com/paulbellamy/ratecounter"
)

var captcha *recaptcha.Recaptcha
var api *slack.Client
var bufpool *bpool.BufferPool
var indexTemplate = template.Must(template.New("index.tmpl").ParseFiles("templates/index.tmpl"))

// Slack statistics
var userCount int
var activeUserCount int
var statsMutex sync.RWMutex // Guards slack statistics variables

var m = expvar.NewMap("metrics")
var counter *ratecounter.RateCounter
var hitsPerMinute expvar.Int
var requests expvar.Int
var inviteErrors expvar.Int
var missingFirstName expvar.Int
var missingLastName expvar.Int
var missingEmail expvar.Int
var missingCoC expvar.Int
var successfulCaptcha expvar.Int
var failedCaptcha expvar.Int
var invalidCaptcha expvar.Int
var successfulInvites expvar.Int

// config
var c Specification

type Specification struct {
	Port           string `envconfig:"PORT"`
	CaptchaSitekey string `required:"true"`
	CaptchaSecret  string `required:"true"`
	SlackToken     string `required:"true"`
	EnforceHTTPS   bool
}

func init() {
	err := envconfig.Process("slackinviter", &c)
	if err != nil {
		log.Fatal(err.Error())
	}
	counter = ratecounter.NewRateCounter(1 * time.Minute)
	m.Set("hits_per_minute", &hitsPerMinute)
	m.Set("requests", &requests)
	m.Set("invite_errors", &inviteErrors)
	m.Set("missing_first_name", &missingFirstName)
	m.Set("missing_last_name", &missingLastName)
	m.Set("missing_email", &missingEmail)
	m.Set("missing_coc", &missingCoC)
	m.Set("failed_captcha", &failedCaptcha)
	m.Set("invalid_captcha", &invalidCaptcha)
	m.Set("successful_captcha", &successfulCaptcha)
	m.Set("successful_invites", &successfulInvites)
	// Init stuff
	captcha = recaptcha.New(c.CaptchaSecret)
	api = slack.New(c.SlackToken)
	bufpool = bpool.NewBufferPool(64)
}

func main() {
	go pollSlack()
	mux := http.NewServeMux()
	mux.HandleFunc("/invite/", handleInvite)
	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
	mux.HandleFunc("/", enforceHTTPSFunc(homepage))
	mux.Handle("/debug/vars", http.DefaultServeMux)
	err := http.ListenAndServe(":"+c.Port, handlers.CombinedLoggingHandler(os.Stdout, mux))
	if err != nil {
		log.Fatal(err.Error())
	}
}

func enforceHTTPSFunc(h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if xfp := r.Header.Get("X-Forwarded-Proto"); c.EnforceHTTPS && xfp == "http" {
			u := new(url.URL)
			*u = *r.URL
			u.Scheme = "https"
			if u.Host == "" {
				u.Host = r.Host
			}
			http.Redirect(w, r, u.String(), 301)
			return
		}
		h(w, r)
	}
}

func pollSlack() {
	for {
		users, err := api.GetUsers()
		if err != nil {
			log.Println("error polling slack for users:", err)
			continue
		}
		uCount := 0 // users
		aCount := 0 // active users
		for _, u := range users {
			if u.ID != "USLACKBOT" && !u.IsBot && !u.Deleted {
				uCount += 1
				if u.Presence == "active" {
					aCount++
				}
			}
		}
		statsMutex.Lock()
		userCount = uCount
		activeUserCount = aCount
		statsMutex.Unlock()
		time.Sleep(10 * time.Minute)
	}
}

// Homepage renders the homepage
func homepage(w http.ResponseWriter, r *http.Request) {
	counter.Incr(1)
	hitsPerMinute.Set(counter.Rate())
	requests.Add(1)
	statsMutex.RLock()
	data := map[string]interface{}{"SiteKey": c.CaptchaSitekey, "UserCount": userCount, "ActiveCount": activeUserCount}
	statsMutex.RUnlock()
	buf := bufpool.Get()
	defer bufpool.Put(buf)
	err := indexTemplate.Execute(buf, data)
	if err != nil {
		log.Println("error rendering template:", err)
		http.Error(w, "error rendering template :-(", http.StatusInternalServerError)
		return
	}
	// Set the header and write the buffer to the http.ResponseWriter
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	buf.WriteTo(w)
}

// ShowPost renders a single post
func handleInvite(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}
	captchaResponse := r.FormValue("g-recaptcha-response")
	remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		failedCaptcha.Add(1)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	valid, err := captcha.Verify(captchaResponse, remoteIP)
	if err != nil {
		failedCaptcha.Add(1)
		http.Error(w, "Error validating recaptcha.. Did you click it?", http.StatusPreconditionFailed)
		return
	}
	if !valid {
		invalidCaptcha.Add(1)
		http.Error(w, "Invalid recaptcha", http.StatusInternalServerError)
		return

	}
	successfulCaptcha.Add(1)
	fname := r.FormValue("fname")
	lname := r.FormValue("lname")
	email := r.FormValue("email")
	coc := r.FormValue("coc")
	if email == "" {
		missingEmail.Add(1)
		http.Error(w, "Missing email", http.StatusPreconditionFailed)
		return
	}
	if fname == "" {
		missingFirstName.Add(1)
		http.Error(w, "Missing first name", http.StatusPreconditionFailed)
		return
	}
	if lname == "" {
		missingLastName.Add(1)
		http.Error(w, "Missing last name", http.StatusPreconditionFailed)
		return
	}
	if coc != "1" {
		missingCoC.Add(1)
		http.Error(w, "You need to accept the code of conduct", http.StatusPreconditionFailed)
		return
	}
	err = api.InviteToTeam("Gophers", fname, lname, email)
	if err != nil {
		log.Println("InviteToTeam error:", err)
		inviteErrors.Add(1)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	successfulInvites.Add(1)
}
<|endoftext|>


<commit_before>//
//  telme10
//
// Copyright (c) 2016 Christian Pointner <equinox@realraum.at>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of telgo nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/coreos/go-systemd/activation"
	"github.com/spreadspace/telgo"
)

func wait(length time.Duration, cancel <-chan bool) bool {
	t := time.NewTimer(length)
	defer t.Stop()
	select {
	case <-t.C:
		return false
	case <-cancel:
		return true
	}
}

func printLogo(c *telgo.Client) {
	for _, line := range logoBW72 {
		c.Sayln(" " + line)
	}
}

type Greeter struct {
}

func (g Greeter) Exec(c *telgo.Client, args []string) bool {
	c.Sayln("")
	c.Sayln("")
	printLogo(c)
	c.Sayln("")
	c.Sayln("       Hello!")
	c.Sayln("")

	if wait(1*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     Did you know: realraum will be celebrating its 10th birthday")
	c.Sayln("     on the 18th of March 2017?")
	c.Sayln("")

	if wait(1*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     you should come by!")
	c.Sayln("")

	if wait(3*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     fun fun fun!")
	c.Sayln("")

	if wait(3*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     come to the party ... we mean it!")
	c.Sayln("")
	c.Sayln("     you have now 10s to decide:")

	c.Say("       deciding ...   0.0%%\r")
DECISION:
	for i := uint(0); i < 100; i++ {
		select {
		case <-c.Cancel:
			break DECISION
		default:
		}
		time.Sleep(100 * time.Millisecond)
		c.Say("      deciding ... %5.1f%%\r", (float64(i)/float64(100))*100.0)
	}
	c.Sayln("      deciding ... 100.0%% ... done.")
	c.Sayln("")

	c.Prompt = "     are you coming?  "
	return false
}

func answer(c *telgo.Client, args []string) bool {
	if len(args) > 1 {
		c.Sayln("       yes or no?")
		return false
	}

	switch args[0] {
	case "y":
		fallthrough
	case "yes":
		c.Sayln("")
		c.Sayln("     Great! We'll see you at the party then.")
	case "n":
		fallthrough
	case "no":
		c.Sayln("")
		c.Sayln("     Sorry to hear! You're missing out on a great experience.")
	default:
		c.Sayln("       yes or no?")
		return false
	}

	c.Sayln("")
	c.Sayln("         https://github.com/realraum/telme10")
	c.Sayln("")
	time.Sleep(1 * time.Second)
	return true
}

func main() {
	cmdlist := make(telgo.CmdList)

	listeners, err := activation.Listeners(true)
	if err != nil {
	}

	fmt.Printf("got %d sockets from systemd\n", len(listeners))
	var s *telgo.Server
	if len(listeners) == 0 {
		if len(os.Args) < 2 {
			fmt.Println("please specify a address to listen on")
			os.Exit(2)
		}
		if s, err = telgo.NewServer(os.Args[1], "", cmdlist, nil); err != nil {
			fmt.Println("failed to initialize the server:", err)
			os.Exit(1)
		}
	} else {
		if len(listeners) > 1 {
			fmt.Println("warning got more than one socket from systemd, only using the first", err)
		}
		if s, err = telgo.NewServerFromListener(listeners[0], "", cmdlist, nil); err != nil {
			fmt.Println("failed to initialize the server:", err)
			os.Exit(1)
		}
	}
	if err = s.Run(Greeter{}, answer); err != nil {
		fmt.Println("telnet server returned:", err)
	}
}
<commit_msg>a little more debug output<commit_after>//
//  telme10
//
// Copyright (c) 2016 Christian Pointner <equinox@realraum.at>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of telgo nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/coreos/go-systemd/activation"
	"github.com/spreadspace/telgo"
)

func wait(length time.Duration, cancel <-chan bool) bool {
	t := time.NewTimer(length)
	defer t.Stop()
	select {
	case <-t.C:
		return false
	case <-cancel:
		return true
	}
}

func printLogo(c *telgo.Client) {
	for _, line := range logoBW72 {
		c.Sayln(" " + line)
	}
}

type Greeter struct {
}

func (g Greeter) Exec(c *telgo.Client, args []string) bool {
	fmt.Println("new client from:", c.Conn.RemoteAddr())

	c.Sayln("")
	c.Sayln("")
	printLogo(c)
	c.Sayln("")
	c.Sayln("       Hello!")
	c.Sayln("")

	if wait(1*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     Did you know: realraum will be celebrating its 10th birthday")
	c.Sayln("     on the 18th of March 2017?")
	c.Sayln("")

	if wait(1*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     you should come by!")
	c.Sayln("")

	if wait(3*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     fun fun fun!")
	c.Sayln("")

	if wait(3*time.Second, c.Cancel) {
		return true
	}
	c.Sayln("     come to the party ... we mean it!")
	c.Sayln("")
	c.Sayln("     you have now 10s to decide:")

	c.Say("       deciding ...   0.0%%\r")
DECISION:
	for i := uint(0); i < 100; i++ {
		select {
		case <-c.Cancel:
			break DECISION
		default:
		}
		time.Sleep(100 * time.Millisecond)
		c.Say("      deciding ... %5.1f%%\r", (float64(i)/float64(100))*100.0)
	}
	c.Sayln("      deciding ... 100.0%% ... done.")
	c.Sayln("")

	c.Prompt = "     are you coming?  "
	return false
}

func answer(c *telgo.Client, args []string) bool {
	if len(args) > 1 {
		c.Sayln("       yes or no?")
		return false
	}

	switch args[0] {
	case "y":
		fallthrough
	case "yes":
		c.Sayln("")
		c.Sayln("     Great! We'll see you at the party then.")
	case "n":
		fallthrough
	case "no":
		c.Sayln("")
		c.Sayln("     Sorry to hear! You're missing out on a great experience.")
	default:
		c.Sayln("       yes or no?")
		return false
	}

	c.Sayln("")
	c.Sayln("         https://github.com/realraum/telme10")
	c.Sayln("")
	time.Sleep(1 * time.Second)
	return true
}

func main() {
	cmdlist := make(telgo.CmdList)

	listeners, err := activation.Listeners(true)
	if err != nil {
		fmt.Printf("error while getting socket form systemd", err)
		os.Exit(1)
	}

	var s *telgo.Server
	if len(listeners) == 0 {
		if len(os.Args) < 2 {
			fmt.Println("please specify a address to listen on")
			os.Exit(2)
		}
		if s, err = telgo.NewServer(os.Args[1], "", cmdlist, nil); err != nil {
			fmt.Println("failed to initialize the server:", err)
			os.Exit(1)
		}
		fmt.Println("running telnet server on", os.Args[1])
	} else {
		fmt.Printf("got %d sockets from systemd\n", len(listeners))
		if len(listeners) > 1 {
			fmt.Println("warning got more than one socket from systemd, only using the first", err)
		}
		if s, err = telgo.NewServerFromListener(listeners[0], "", cmdlist, nil); err != nil {
			fmt.Println("failed to initialize the server:", err)
			os.Exit(1)
		}
		fmt.Println("running telnet server on", listeners[0].Addr())
	}
	if err = s.Run(Greeter{}, answer); err != nil {
		fmt.Println("telnet server returned:", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	prgnames := ""
	prgs := ResolveDependencies([]string{prgnames})
	for _, prg := range prgs {
		install(prg)
	}
}

type Prg struct {
	name       string
	extractVer Extractor
	extractUrl Extractor
	folder     string
	cache      CacheGetter
}

type fextract func(str string) string

type Extractor interface {
	ExtractFrom(str string) string
	Extract() string
	Next() Extractor
}

type CacheGetter interface {
	Get(resource string) string
	Next() CacheGetter
}

type Cache struct{}

func (c *Cache) Get(resource string) string {
	return ""
}

func (c *Cache) Next() CacheGetter {
	return nil
}

type Extractable struct {
	data  string
	self  Extractor
	next  Extractor
	cache CacheGetter
}

func (e *Extractable) Next() Extractor {
	return e.next
}

func (e *Extractable) Extract() string {
	res := e.self.ExtractFrom(e.data)
	if e.Next() != nil {
		res = e.Next().ExtractFrom(res)
	}
	return res
}

type ExtractorUrl struct {
	Extractable
}

func (eu *ExtractorUrl) ExtractFrom(url string) string {
	fmt.Println("ok! " + url)

	return ""
}

func NewExtractorUrl(uri string, cache CacheGetter) *ExtractorUrl {
	res := &ExtractorUrl{Extractable{data: uri, cache: cache}}
	res.self = res
	return res
}

func ResolveDependencies(prgnames []string) []*Prg {
	cache := &Cache{}
	dwnl := NewExtractorUrl("http://peazip.sourceforge.net/peazip-portable.html", cache)
	prgPeazip := &Prg{name: "peazip", extractVer: dwnl, cache: cache}
	prgGit := &Prg{name: "git"}
	prgInvalid := &Prg{name: "invalid"}
	return []*Prg{prgPeazip, prgGit, prgInvalid}
}

func install(prg *Prg) {
	folder := prg.GetFolder()
	if hasFolder, err := exists(folder); !hasFolder && err == nil {
		fmt.Printf("Need to install %v in '%v'\n", prg.name, folder)
	}
}

func (prg *Prg) GetFolder() string {
	if prg.folder == "" {
		switch prg.name {
		case "peazip":
			prg.folder = prg.extractVer.Extract() // "pz5.2.2"
		case "git":
			prg.folder = "git1.9"
		case "invalid":
			prg.folder = "invalid<x:y"
		}
	}
	return "test/" + prg.name + "/" + prg.folder
}

// exists returns whether the given file or directory exists or not
// http://stackoverflow.com/questions/10510691/how-to-check-whether-a-file-or-directory-denoted-by-a-path-exists-in-golang
func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<commit_msg>Implements getLastModifiedFile(dir string).<commit_after>package main

import (
	"fmt"
	"os"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	prgnames := ""
	prgs := ResolveDependencies([]string{prgnames})
	for _, prg := range prgs {
		install(prg)
	}
}

type Prg struct {
	name       string
	extractVer Extractor
	extractUrl Extractor
	folder     string
	cache      CacheGetter
}

type fextract func(str string) string

type Extractor interface {
	ExtractFrom(str string) string
	Extract() string
	Next() Extractor
}

type CacheGetter interface {
	Get(resource string) string
	Next() CacheGetter
}

type Cache struct{}

func (c *Cache) Get(resource string) string {
	return ""
}

func (c *Cache) Next() CacheGetter {
	return nil
}

type Extractable struct {
	data  string
	self  Extractor
	next  Extractor
	cache CacheGetter
}

func (e *Extractable) Next() Extractor {
	return e.next
}

func (e *Extractable) Extract() string {
	res := e.self.ExtractFrom(e.data)
	if e.Next() != nil {
		res = e.Next().ExtractFrom(res)
	}
	return res
}

type ExtractorUrl struct {
	Extractable
}

func (eu *ExtractorUrl) ExtractFrom(url string) string {
	fmt.Println("ok! " + url)

	return ""
}

func NewExtractorUrl(uri string, cache CacheGetter) *ExtractorUrl {
	res := &ExtractorUrl{Extractable{data: uri, cache: cache}}
	res.self = res
	return res
}

func ResolveDependencies(prgnames []string) []*Prg {
	cache := &Cache{}
	dwnl := NewExtractorUrl("http://peazip.sourceforge.net/peazip-portable.html", cache)
	prgPeazip := &Prg{name: "peazip", extractVer: dwnl, cache: cache}
	prgGit := &Prg{name: "git"}
	prgInvalid := &Prg{name: "invalid"}
	return []*Prg{prgPeazip, prgGit, prgInvalid}
}

func install(prg *Prg) {
	folder := prg.GetFolder()
	if hasFolder, err := exists(folder); !hasFolder && err == nil {
		fmt.Printf("Need to install %v in '%v'\n", prg.name, folder)
	}
}

func (prg *Prg) GetFolder() string {
	if prg.folder == "" {
		switch prg.name {
		case "peazip":
			prg.folder = prg.extractVer.Extract() // "pz5.2.2"
		case "git":
			prg.folder = "git1.9"
		case "invalid":
			prg.folder = "invalid<x:y"
		}
	}
	return "test/" + prg.name + "/" + prg.folder
}

// exists returns whether the given file or directory exists or not
// http://stackoverflow.com/questions/10510691/how-to-check-whether-a-file-or-directory-denoted-by-a-path-exists-in-golang
func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

// https://groups.google.com/forum/#!topic/golang-nuts/Q7hYQ9GdX9Q

type byDate []os.FileInfo

func (f byDate) Len() int {
	return len(f)
}
func (f byDate) Less(i, j int) bool {
	return f[i].ModTime().Unix() > f[j].ModTime().Unix()
}
func (f byDate) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

func getLastModifiedFile(dir string) string {
	f, err := os.Open(dir)
	if err != nil {
		fmt.Printf("Error while opening dir '%v': '%v'\n", dir, err)
		return ""
	}
	list, err := f.Readdir(-1)
	if err != nil {
		fmt.Printf("Error while reading dir '%v': '%v'\n", dir, err)
		return ""
	}
	if len(list) == 0 {
		return ""
	}
	fmt.Printf("t: '%v' => '%v'\n", list, list[0])
	sort.Sort(byDate(list))
	fmt.Printf("t: '%v' => '%v'\n", list, list[0])
	return list[0].Name()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/ogier/pflag"
	"github.com/yuya-takeyama/argf"
)

var (
	name    = "ltsvp"
	version = "0.3.0"

	flag            = pflag.NewFlagSet(name, pflag.ContinueOnError)
	list            = pflag.StringP("keys", "k", "", "")
	outputDelimiter = pflag.StringP("output-delimiter", "d", "\t", "")
	remainLTSV      = pflag.BoolP("remain-ltsv", "r", false, "")
	isHelp          = pflag.BoolP("help", "h", false, "")
	isVersion       = pflag.BoolP("version", "v", false, "")
)

func printUsage() {
	fmt.Fprintf(os.Stderr, `
Usage: %s OPTION... [FILE]...
Print selected parts of LTSV from each FILE to standard output.

Options:
  -k, --keys=LIST
                 select only these keys (required)
  -D, --output-delimiter=STRING
                 use STRING to separate parts (default: \t)
  -r, --remain-ltsv
                 print selected parts as LTSV
  -h, --help
                 display this help text and exit
  -v, --version
                 output version information and exit

LIST is made up of keys separated by commas.
  host           # Select host
  host,time,ua   # Select host, time, and ua
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func do(l *LTSVScanner) error {
	for l.Scan() {
		fmt.Println(l.Text())
	}
	return l.Err()
}

func printErr(err error) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func guideToHelp() {
	fmt.Fprintf(os.Stderr, "Try '%s --help' for more information.\n", name)
}

func main() {
	flag.SetOutput(ioutil.Discard)
	if err := flag.Parse(os.Args[1:]); err != nil {
		printErr(err)
		guideToHelp()
		os.Exit(2)
	}
	switch {
	case *isHelp:
		printUsage()
		os.Exit(0)
	case *isVersion:
		printVersion()
		os.Exit(0)
	}

	keys := ParseKeysList(*list)
	r, err := argf.From(flag.Args())
	if err != nil {
		printErr(err)
		os.Exit(2)
	}

	l := NewLTSVScanner(keys, r)
	l.OutputDelimiter = *outputDelimiter
	l.RemainLTSV = *remainLTSV
	if err := do(l); err != nil {
		printErr(err)
		os.Exit(1)
	}
	os.Exit(0)
}
<commit_msg>Check if keys specified<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/ogier/pflag"
	"github.com/yuya-takeyama/argf"
)

var (
	name    = "ltsvp"
	version = "0.3.0"

	flag            = pflag.NewFlagSet(name, pflag.ContinueOnError)
	list            = pflag.StringP("keys", "k", "", "")
	outputDelimiter = pflag.StringP("output-delimiter", "d", "\t", "")
	remainLTSV      = pflag.BoolP("remain-ltsv", "r", false, "")
	isHelp          = pflag.BoolP("help", "h", false, "")
	isVersion       = pflag.BoolP("version", "v", false, "")
)

func printUsage() {
	fmt.Fprintf(os.Stderr, `
Usage: %s OPTION... [FILE]...
Print selected parts of LTSV from each FILE to standard output.

Options:
  -k, --keys=LIST
                 select only these keys (required)
  -D, --output-delimiter=STRING
                 use STRING to separate parts (default: \t)
  -r, --remain-ltsv
                 print selected parts as LTSV
  -h, --help
                 display this help text and exit
  -v, --version
                 output version information and exit

LIST is made up of keys separated by commas.
  host           # Select host
  host,time,ua   # Select host, time, and ua
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func do(l *LTSVScanner) error {
	for l.Scan() {
		fmt.Println(l.Text())
	}
	return l.Err()
}

func printErr(err error) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func guideToHelp() {
	fmt.Fprintf(os.Stderr, "Try '%s --help' for more information.\n", name)
}

func main() {
	flag.SetOutput(ioutil.Discard)
	if err := flag.Parse(os.Args[1:]); err != nil {
		printErr(err)
		guideToHelp()
		os.Exit(2)
	}
	switch {
	case *isHelp:
		printUsage()
		os.Exit(0)
	case *isVersion:
		printVersion()
		os.Exit(0)
	}

	keys := ParseKeysList(*list)
	if len(keys) == 0 {
		printErr(fmt.Errorf("no specify LIST"))
		os.Exit(2)
	}

	r, err := argf.From(flag.Args())
	if err != nil {
		printErr(err)
		os.Exit(2)
	}

	l := NewLTSVScanner(keys, r)
	l.OutputDelimiter = *outputDelimiter
	l.RemainLTSV = *remainLTSV
	if err := do(l); err != nil {
		printErr(err)
		os.Exit(1)
	}
	os.Exit(0)
}
<|endoftext|>


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

// udptunnel is a daemon that sets up a point-to-point virtual private network
// between two hosts:
//	* A client host that may be behind an obtrusive NAT that frequently drops
//	TCP connections, but happens to pass UDP traffic reliably.
//	* A server host that is internet-accessible.
//
// Example Setup
//
// The udptunnel is setup by running it on two different hosts, one in a server
// configuration, and the other in client configuration. The difference between
// a server or client is determined by the NetworkAddress field in the
// configuration. If the address has an empty host portion, then the daemon
// operates in server mode. Otherwise, the daemon operates in client mode and
// will use the host to dial the server.
//
// Example server config:
//	{"TunnelAddress": "10.0.0.1", "NetworkAddress": ":8000", "AllowedPorts": [22]}
// Example client config:
//	{"TunnelAddress": "10.0.0.2", "NetworkAddress": "example.com:8000", "AllowedPorts": [22]}
//
// See the TunnelConfig struct for more details.
//
// Security Considerations
//
// TUN traffic is sent ad-verbatim between the two endpoints via unencrypted
// UDP traffic. The intended use case is to run a secure protocol (like SSH;
// see github.com/dsnet/sshtunnel) on top of this simple VPN. In order to
// prevent attackers from connecting to other locally binded sockets on the
// endpoints, a simple port filter is built-in to restrict IP traffic to only
// the specified ports. Users of udptunnel should also setup iptable rules as
// a secondary measure to restrict malicious traffic.
package main

import (
	"bytes"
	"context"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"sync/atomic"
	"syscall"
	"time"

	"github.com/dsnet/golib/jsonutil"
	"github.com/songgao/water"
)

type TunnelConfig struct {
	// LogFile is where the tunnel daemon will direct its output log.
	// If the path is empty, then the server will output to os.Stderr.
	LogFile string

	// TunnelDevice is the name of the TUN device (default: "tunnel").
	TunnelDevice string

	// TunnelAddress is the private IPv4 address for the tunnel.
	// The client and server should have different IP addresses both in the
	// 255.255.255.0 subnet mask.
	// Recommended value is 10.0.0.1 for the server and 10.0.0.2 for the client.
	TunnelAddress string

	// NetworkAddress is the public host and port for UDP traffic.
	// If the host portion is empty, then the daemon is operting operating in
	// server mode and will bind on the specified port (e.g., ":8000").
	// Otherwise, the daemon is operating in client mode and will use the
	// specified host to communicate with the server (e.g., "example.com:8000").
	NetworkAddress string

	// AllowedPorts is a list of allowed UDP and TCP ports.
	// Since udptunnel sends traffic as unencrypted messages,
	// only protocols that provide application-layer security (like SSH)
	// should be used.
	//
	// The set of allowed ports must match on both the client and server.
	AllowedPorts []uint16

	// PacketMagic is used to generate a sequence of bytes that is prepended to
	// every TUN packet sent over UDP. Only inbound messages carrying the
	// magic sequence will be accepted. This mechanism is used as a trivial way
	// to protect against denial-of-service attacks by ensuring the server only
	// responds to remote IP addresses that are validated.
	//
	// This validation mechanism is only intended to protect against adversaries
	// with the ability to create arbitrary spoof UDP packets. It does not
	// protect against man-in-the-middle (MITM) attacks since any attacker with
	// the ability to intercept traffic already has the capability to block
	// communication between the client and server.
	//
	// This value must match on both the client and server.
	PacketMagic string
}

type direction byte

const (
	outbound direction = 'T' // Transmit
	inbound  direction = 'R' // Receive
)

func loadConfig(conf string) (config TunnelConfig, closer func() error) {
	var logBuf bytes.Buffer
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.SetOutput(io.MultiWriter(os.Stderr, &logBuf))

	// Load configuration file.
	c, err := ioutil.ReadFile(conf)
	if err != nil {
		log.Fatalf("unable to read config: %v", err)
	}
	c, _ = jsonutil.Minify(c)
	if err := json.Unmarshal(c, &config); err != nil {
		log.Fatalf("unable to decode config: %v", err)
	}
	if config.TunnelDevice == "" {
		config.TunnelDevice = "tunnel"
	}
	if _, _, err := net.SplitHostPort(config.NetworkAddress); err != nil {
		log.Fatalf("invalid network address: %v", err)
	}
	if net.ParseIP(config.TunnelAddress).To4() == nil {
		log.Fatalf("private tunnel address must be valid IPv4 address")
	}
	if len(config.AllowedPorts) == 0 {
		log.Fatalf("no allowed ports specified")
	}

	// Print the configuration.
	var b bytes.Buffer
	enc := json.NewEncoder(&b)
	enc.SetEscapeHTML(false)
	enc.SetIndent("", "\t")
	enc.Encode(&config)
	log.Printf("loaded config:\n%s", b.String())

	// Setup the log output.
	if config.LogFile == "" {
		log.SetOutput(os.Stderr)
		closer = func() error { return nil }
	} else {
		f, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)
		if err != nil {
			log.Fatalf("error opening log file: %v", err)
		}
		f.Write(logBuf.Bytes()) // Write log output prior to this point
		log.Printf("suppress stderr logging (redirected to %s)", f.Name())
		log.SetOutput(f)
		closer = f.Close
	}

	return config, closer
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage:\n")
		fmt.Fprintf(os.Stderr, "\t%s CONFIG_PATH\n", os.Args[0])
		os.Exit(1)
	}
	config, closer := loadConfig(os.Args[1])
	defer closer()

	// Setup signal handler to initiate shutdown.
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		sigc := make(chan os.Signal, 1)
		signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
		log.Printf("received %v - initiating shutdown", <-sigc)
		cancel()
	}()

	// Create a new tunnel device (requires root privileges).
	iface, err := water.NewTUN(config.TunnelDevice)
	if err != nil {
		log.Fatalf("error creating tun device: %v", err)
	}
	defer iface.Close()
	if err := exec.Command("/sbin/ip", "link", "set", "dev", config.TunnelDevice, "mtu", "1300").Run(); err != nil {
		log.Fatalf("ip link error: %v", err)
	}
	if err := exec.Command("/sbin/ip", "addr", "add", config.TunnelAddress+"/24", "dev", config.TunnelDevice).Run(); err != nil {
		log.Fatalf("ip addr error: %v", err)
	}
	if err := exec.Command("/sbin/ip", "link", "set", "dev", config.TunnelDevice, "up").Run(); err != nil {
		log.Fatalf("ip link error: %v", err)
	}

	// Create a new UDP socket.
	host, port, _ := net.SplitHostPort(config.NetworkAddress)
	serverMode := host == ""
	laddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort("", port))
	if err != nil {
		log.Fatalf("error resolving address: %v", err)
	}
	cn, err := net.ListenUDP("udp", laddr)
	if err != nil {
		log.Fatalf("error listening on socket: %v", err)
	}
	defer cn.Close()

	// TODO(dsnet): We should drop root privileges at this point since the
	// TUN device and UDP socket have been set up. However, there is no good
	// support for doing so currently: https://golang.org/issue/1435

	var atomicRaddr atomic.Value
	atomicRaddr.Store((*net.UDPAddr)(nil))
	magic := md5.Sum([]byte(config.PacketMagic))
	pf := newPortFilter(config.AllowedPorts)
	if serverMode {
		log.Println("daemon started in server mode")
	} else {
		log.Println("daemon started in client mode")
	}

	// Handle outbound traffic.
	go func() {
		var last uint64 // Last time we attempted DNS loookup
		b := make([]byte, 1<<16)
		for {
			n, err := iface.Read(b[len(magic):])
			if err != nil {
				if isDone(ctx) {
					return
				}
				log.Printf("tun read error: %v", err)
				continue
			}
			n += copy(b, magic[:])
			p := b[len(magic):n]

			// Since the remote address could change due to updates to DNS,
			// periodically check DNS for a new address.
			raddr := atomicRaddr.Load().(*net.UDPAddr)
			if !serverMode && (raddr == nil || timeNow()-last > 30) {
				addr, err := net.ResolveUDPAddr("udp", config.NetworkAddress)
				if !equalAddr(addr, raddr) && addr != nil && err == nil {
					raddr = addr
					atomicRaddr.Store(raddr)
					log.Printf("switching remote address: %v", raddr)
				}
				last = timeNow()
			}

			if pf.Filter(p, outbound) || raddr == nil {
				logPacket(p, outbound, true)
				continue
			}

			if _, err := cn.WriteToUDP(b[:n], raddr); err != nil {
				log.Printf("net write error: %v", err)
			}
			logPacket(p, outbound, false)
		}
	}()

	// Handle inbound traffic.
	go func() {
		b := make([]byte, 1<<16)
		for {
			n, raddr, err := cn.ReadFromUDP(b)
			if err != nil {
				if isDone(ctx) {
					return
				}
				log.Printf("net read error: %v", err)
				continue
			}
			if !bytes.HasPrefix(b, magic[:]) {
				log.Printf("invalid packet from remote address: %v", raddr)
				continue
			}
			p := b[len(magic):n]

			if pf.Filter(p, inbound) {
				logPacket(p, inbound, true)
				continue
			}

			// We assume a matching magic prefix is sufficient to validate
			// that the new IP is really the remote endpoint.
			// We assume that any adversary capable of performing a replay
			// attack already has the power to disrupt communication.
			if serverMode {
				if !equalAddr(atomicRaddr.Load().(*net.UDPAddr), raddr) {
					atomicRaddr.Store(raddr)
					log.Printf("switching remote address: %v", raddr)
				}
			}

			if _, err := iface.Write(p); err != nil {
				log.Printf("tun write error: %v", err)
			}
			logPacket(p, inbound, false)
		}
	}()

	<-ctx.Done()
}

func isDone(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}

func equalAddr(x, y *net.UDPAddr) bool {
	if x == nil || y == nil {
		return x == nil && y == nil
	}
	return x.IP.Equal(y.IP) && x.Port == y.Port && x.Zone == y.Zone
}

// The current timestamp in seconds. Must be read using atomic operations.
var atomicNow uint64

func init() {
	atomicNow = uint64(time.Now().Unix())
	go func() {
		for range time.Tick(time.Second) {
			atomic.AddUint64(&atomicNow, 1)
		}
	}()
}

func timeNow() uint64 {
	return atomic.LoadUint64(&atomicNow)
}
<commit_msg>Add versioning information to binary<commit_after>// Copyright 2017, The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.

// udptunnel is a daemon that sets up a point-to-point virtual private network
// between two hosts:
//	* A client host that may be behind an obtrusive NAT that frequently drops
//	TCP connections, but happens to pass UDP traffic reliably.
//	* A server host that is internet-accessible.
//
// Example Setup
//
// The udptunnel is setup by running it on two different hosts, one in a server
// configuration, and the other in client configuration. The difference between
// a server or client is determined by the NetworkAddress field in the
// configuration. If the address has an empty host portion, then the daemon
// operates in server mode. Otherwise, the daemon operates in client mode and
// will use the host to dial the server.
//
// Example server config:
//	{"TunnelAddress": "10.0.0.1", "NetworkAddress": ":8000", "AllowedPorts": [22]}
// Example client config:
//	{"TunnelAddress": "10.0.0.2", "NetworkAddress": "example.com:8000", "AllowedPorts": [22]}
//
// See the TunnelConfig struct for more details.
//
// Security Considerations
//
// TUN traffic is sent ad-verbatim between the two endpoints via unencrypted
// UDP traffic. The intended use case is to run a secure protocol (like SSH;
// see github.com/dsnet/sshtunnel) on top of this simple VPN. In order to
// prevent attackers from connecting to other locally binded sockets on the
// endpoints, a simple port filter is built-in to restrict IP traffic to only
// the specified ports. Users of udptunnel should also setup iptable rules as
// a secondary measure to restrict malicious traffic.
package main

import (
	"bytes"
	"context"
	"crypto/md5"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"sync/atomic"
	"syscall"
	"time"

	"github.com/dsnet/golib/jsonutil"
	"github.com/songgao/water"
)

// Version of the udptunnel binary. May be set by linker when building.
var version string

type TunnelConfig struct {
	// LogFile is where the tunnel daemon will direct its output log.
	// If the path is empty, then the server will output to os.Stderr.
	LogFile string

	// TunnelDevice is the name of the TUN device (default: "tunnel").
	TunnelDevice string

	// TunnelAddress is the private IPv4 address for the tunnel.
	// The client and server should have different IP addresses both in the
	// 255.255.255.0 subnet mask.
	// Recommended value is 10.0.0.1 for the server and 10.0.0.2 for the client.
	TunnelAddress string

	// NetworkAddress is the public host and port for UDP traffic.
	// If the host portion is empty, then the daemon is operting operating in
	// server mode and will bind on the specified port (e.g., ":8000").
	// Otherwise, the daemon is operating in client mode and will use the
	// specified host to communicate with the server (e.g., "example.com:8000").
	NetworkAddress string

	// AllowedPorts is a list of allowed UDP and TCP ports.
	// Since udptunnel sends traffic as unencrypted messages,
	// only protocols that provide application-layer security (like SSH)
	// should be used.
	//
	// The set of allowed ports must match on both the client and server.
	AllowedPorts []uint16

	// PacketMagic is used to generate a sequence of bytes that is prepended to
	// every TUN packet sent over UDP. Only inbound messages carrying the
	// magic sequence will be accepted. This mechanism is used as a trivial way
	// to protect against denial-of-service attacks by ensuring the server only
	// responds to remote IP addresses that are validated.
	//
	// This validation mechanism is only intended to protect against adversaries
	// with the ability to create arbitrary spoof UDP packets. It does not
	// protect against man-in-the-middle (MITM) attacks since any attacker with
	// the ability to intercept traffic already has the capability to block
	// communication between the client and server.
	//
	// This value must match on both the client and server.
	PacketMagic string
}

type direction byte

const (
	outbound direction = 'T' // Transmit
	inbound  direction = 'R' // Receive
)

func loadConfig(conf string) (config TunnelConfig, closer func() error) {
	var logBuf bytes.Buffer
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.SetOutput(io.MultiWriter(os.Stderr, &logBuf))

	var hash string
	if b, _ := ioutil.ReadFile(os.Args[0]); len(b) > 0 {
		hash = fmt.Sprintf("%x", sha256.Sum256(b))
	}

	// Load configuration file.
	c, err := ioutil.ReadFile(conf)
	if err != nil {
		log.Fatalf("unable to read config: %v", err)
	}
	c, _ = jsonutil.Minify(c)
	if err := json.Unmarshal(c, &config); err != nil {
		log.Fatalf("unable to decode config: %v", err)
	}
	if config.TunnelDevice == "" {
		config.TunnelDevice = "tunnel"
	}
	if _, _, err := net.SplitHostPort(config.NetworkAddress); err != nil {
		log.Fatalf("invalid network address: %v", err)
	}
	if net.ParseIP(config.TunnelAddress).To4() == nil {
		log.Fatalf("private tunnel address must be valid IPv4 address")
	}
	if len(config.AllowedPorts) == 0 {
		log.Fatalf("no allowed ports specified")
	}

	// Print the configuration.
	var b bytes.Buffer
	enc := json.NewEncoder(&b)
	enc.SetEscapeHTML(false)
	enc.SetIndent("", "\t")
	enc.Encode(struct {
		TunnelConfig
		BinaryVersion string `json:",omitempty"`
		BinarySHA256  string `json:",omitempty"`
	}{config, version, hash})
	log.Printf("loaded config:\n%s", b.String())

	// Setup the log output.
	if config.LogFile == "" {
		log.SetOutput(os.Stderr)
		closer = func() error { return nil }
	} else {
		f, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0664)
		if err != nil {
			log.Fatalf("error opening log file: %v", err)
		}
		f.Write(logBuf.Bytes()) // Write log output prior to this point
		log.Printf("suppress stderr logging (redirected to %s)", f.Name())
		log.SetOutput(f)
		closer = f.Close
	}

	return config, closer
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage:\n")
		fmt.Fprintf(os.Stderr, "\t%s CONFIG_PATH\n", os.Args[0])
		os.Exit(1)
	}
	config, closer := loadConfig(os.Args[1])
	defer closer()

	// Setup signal handler to initiate shutdown.
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		sigc := make(chan os.Signal, 1)
		signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
		log.Printf("received %v - initiating shutdown", <-sigc)
		cancel()
	}()

	// Create a new tunnel device (requires root privileges).
	iface, err := water.NewTUN(config.TunnelDevice)
	if err != nil {
		log.Fatalf("error creating tun device: %v", err)
	}
	defer iface.Close()
	if err := exec.Command("/sbin/ip", "link", "set", "dev", config.TunnelDevice, "mtu", "1300").Run(); err != nil {
		log.Fatalf("ip link error: %v", err)
	}
	if err := exec.Command("/sbin/ip", "addr", "add", config.TunnelAddress+"/24", "dev", config.TunnelDevice).Run(); err != nil {
		log.Fatalf("ip addr error: %v", err)
	}
	if err := exec.Command("/sbin/ip", "link", "set", "dev", config.TunnelDevice, "up").Run(); err != nil {
		log.Fatalf("ip link error: %v", err)
	}

	// Create a new UDP socket.
	host, port, _ := net.SplitHostPort(config.NetworkAddress)
	serverMode := host == ""
	laddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort("", port))
	if err != nil {
		log.Fatalf("error resolving address: %v", err)
	}
	cn, err := net.ListenUDP("udp", laddr)
	if err != nil {
		log.Fatalf("error listening on socket: %v", err)
	}
	defer cn.Close()

	// TODO(dsnet): We should drop root privileges at this point since the
	// TUN device and UDP socket have been set up. However, there is no good
	// support for doing so currently: https://golang.org/issue/1435

	var atomicRaddr atomic.Value
	atomicRaddr.Store((*net.UDPAddr)(nil))
	magic := md5.Sum([]byte(config.PacketMagic))
	pf := newPortFilter(config.AllowedPorts)
	if serverMode {
		log.Println("daemon started in server mode")
	} else {
		log.Println("daemon started in client mode")
	}

	// Handle outbound traffic.
	go func() {
		var last uint64 // Last time we attempted DNS loookup
		b := make([]byte, 1<<16)
		for {
			n, err := iface.Read(b[len(magic):])
			if err != nil {
				if isDone(ctx) {
					return
				}
				log.Printf("tun read error: %v", err)
				continue
			}
			n += copy(b, magic[:])
			p := b[len(magic):n]

			// Since the remote address could change due to updates to DNS,
			// periodically check DNS for a new address.
			raddr := atomicRaddr.Load().(*net.UDPAddr)
			if !serverMode && (raddr == nil || timeNow()-last > 30) {
				addr, err := net.ResolveUDPAddr("udp", config.NetworkAddress)
				if !equalAddr(addr, raddr) && addr != nil && err == nil {
					raddr = addr
					atomicRaddr.Store(raddr)
					log.Printf("switching remote address: %v", raddr)
				}
				last = timeNow()
			}

			if pf.Filter(p, outbound) || raddr == nil {
				logPacket(p, outbound, true)
				continue
			}

			if _, err := cn.WriteToUDP(b[:n], raddr); err != nil {
				log.Printf("net write error: %v", err)
			}
			logPacket(p, outbound, false)
		}
	}()

	// Handle inbound traffic.
	go func() {
		b := make([]byte, 1<<16)
		for {
			n, raddr, err := cn.ReadFromUDP(b)
			if err != nil {
				if isDone(ctx) {
					return
				}
				log.Printf("net read error: %v", err)
				continue
			}
			if !bytes.HasPrefix(b, magic[:]) {
				log.Printf("invalid packet from remote address: %v", raddr)
				continue
			}
			p := b[len(magic):n]

			if pf.Filter(p, inbound) {
				logPacket(p, inbound, true)
				continue
			}

			// We assume a matching magic prefix is sufficient to validate
			// that the new IP is really the remote endpoint.
			// We assume that any adversary capable of performing a replay
			// attack already has the power to disrupt communication.
			if serverMode {
				if !equalAddr(atomicRaddr.Load().(*net.UDPAddr), raddr) {
					atomicRaddr.Store(raddr)
					log.Printf("switching remote address: %v", raddr)
				}
			}

			if _, err := iface.Write(p); err != nil {
				log.Printf("tun write error: %v", err)
			}
			logPacket(p, inbound, false)
		}
	}()

	<-ctx.Done()
}

func isDone(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}

func equalAddr(x, y *net.UDPAddr) bool {
	if x == nil || y == nil {
		return x == nil && y == nil
	}
	return x.IP.Equal(y.IP) && x.Port == y.Port && x.Zone == y.Zone
}

// The current timestamp in seconds. Must be read using atomic operations.
var atomicNow uint64

func init() {
	atomicNow = uint64(time.Now().Unix())
	go func() {
		for range time.Tick(time.Second) {
			atomic.AddUint64(&atomicNow, 1)
		}
	}()
}

func timeNow() uint64 {
	return atomic.LoadUint64(&atomicNow)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"fmt"
	_ "net/http/pprof"
	"os"
	"runtime"
	"runtime/debug"
	//"runtime/pprof"

	"github.com/btcboost/copernicus/model/chainparams"
	"github.com/btcboost/copernicus/net/limits"
)

const (
	// blockDbNamePrefix is the prefix for the block database name.  The
	// database type is appended to this value to form the full block
	// database name.
	blockDbNamePrefix = "blocks"
)

// btcdMain is the real main function for btcd.  It is necessary to work around
// the fact that deferred functions do not run when os.Exit() is called.  The
// optional serverChan parameter is mainly used by the service code to be
// notified with the server once it is setup so it can gracefully stop it when
// requested from the service control manager.
func bchMain(ctx context.Context) error {
	// Load configuration and parse command line.  This function also
	// initializes logging and configures it accordingly.

	interrupt := interruptListener()

	s, err := newServer(&chainparams.TestNet3Params, interrupt)
	if err != nil {
		return err
	}
	service2.NewMsgHandle(s.mh, )

	if interruptRequested(interrupt) {
		return nil
	}
	s.Start()

	<-interrupt
	return nil
}

func main() {
	// Use all processor cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Block and transaction processing can cause bursty allocations.  This
	// limits the garbage collector from excessively overallocating during
	// bursts.  This value was arrived at with the help of profiling live
	// usage.
	debug.SetGCPercent(10)

	// Up some limits.
	if err := limits.SetLimits(); err != nil {
		fmt.Fprintf(os.Stderr, "failed to set limits: %v\n", err)
		os.Exit(1)
	}

	// Work around defer not working after os.Exit()
	if err := bchMain(context.Background()); err != nil {
		os.Exit(1)
	}
}
<commit_msg>fix conflict in main.go<commit_after>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"fmt"
	_ "net/http/pprof"
	"os"
	"runtime"
	"runtime/debug"
	//"runtime/pprof"

	"github.com/btcboost/copernicus/model/chainparams"
	"github.com/btcboost/copernicus/net/limits"
)

const (
	// blockDbNamePrefix is the prefix for the block database name.  The
	// database type is appended to this value to form the full block
	// database name.
	blockDbNamePrefix = "blocks"
)

// btcdMain is the real main function for btcd.  It is necessary to work around
// the fact that deferred functions do not run when os.Exit() is called.  The
// optional serverChan parameter is mainly used by the service code to be
// notified with the server once it is setup so it can gracefully stop it when
// requested from the service control manager.
func bchMain(ctx context.Context) error {
	// Load configuration and parse command line.  This function also
	// initializes logging and configures it accordingly.

	interrupt := interruptListener()

	s, err := newServer(&chainparams.TestNet3Params, interrupt)
	if err != nil {
		return err
	}
	//service2.NewMsgHandle(s.mh, )

	if interruptRequested(interrupt) {
		return nil
	}
	s.Start()

	<-interrupt
	return nil
}

func main() {
	// Use all processor cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Block and transaction processing can cause bursty allocations.  This
	// limits the garbage collector from excessively overallocating during
	// bursts.  This value was arrived at with the help of profiling live
	// usage.
	debug.SetGCPercent(10)

	// Up some limits.
	if err := limits.SetLimits(); err != nil {
		fmt.Fprintf(os.Stderr, "failed to set limits: %v\n", err)
		os.Exit(1)
	}

	// Work around defer not working after os.Exit()
	if err := bchMain(context.Background()); err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/garyburd/redigo/redis"
)

type userPassAuth struct {
	User string
	Pass string
}

func authHandler(w http.ResponseWriter, r *http.Request) {
	//enforce POST
	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte(http.StatusText(http.StatusMethodNotAllowed)))
	}

	bodyBytes, bodyError := ioutil.ReadAll(r.Body)

	if bodyError != nil {
		log.Fatalln(bodyError)
	} else {
		var userPass userPassAuth
		UnmarshalError := json.Unmarshal(bodyBytes, &userPass)

		if UnmarshalError != nil {
			log.Println(UnmarshalError)
		} else {
			w.Write([]byte(userPass.User))
		}
	}
}

func setupRedis(RedisSchemeURL *string) (connection redis.Conn) {
	connection, error := redis.DialURL(*RedisSchemeURL)
	if error != nil {
		log.Fatalln("Could not connect to REDIS:", error)
	} else {
		fmt.Println("Connected to REDIS:", *RedisSchemeURL)
	}

	return connection
}

func setupFlags() (RedisSchemeURL *string, HTTPAddress *string) {
	RedisSchemeURL = flag.String("redis-url", "redis://@localhost:6379/0", "Url to connect to redis")
	HTTPAddress = flag.String("http-address", ":8080", "Http address to bind to")

	flag.Parse()

	return RedisSchemeURL, HTTPAddress
}

func main() {
	RedisSchemeURL, HTTPAddress := setupFlags()
	redisConnection := setupRedis(RedisSchemeURL)

	http.HandleFunc("/auth", authHandler)
	log.Fatalln(http.ListenAndServe(*HTTPAddress, nil))

	defer redisConnection.Close()
}
<commit_msg>Finaly got something working !<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/garyburd/redigo/redis"
)

type userPassAuth struct {
	User string
	Pass string
}

type _appContext struct {
	redisConnection *redis.Conn
}

var appContext _appContext

func authHandler(response http.ResponseWriter, request *http.Request) {
	if request.Method != "POST" {
		response.WriteHeader(http.StatusMethodNotAllowed)
		response.Write([]byte(http.StatusText(http.StatusMethodNotAllowed)))

		return
	}

	bodyBytes, bodyError := ioutil.ReadAll(request.Body)

	if bodyError != nil {
		log.Fatalln(bodyError)
		response.WriteHeader(http.StatusBadRequest)
		response.Write([]byte(http.StatusText(http.StatusBadRequest)))

		return
	}

	var userPass userPassAuth
	unmarshalError := json.Unmarshal(bodyBytes, &userPass)

	if unmarshalError != nil {
		log.Fatalln(bodyError)
		response.WriteHeader(http.StatusBadRequest)
		response.Write([]byte(http.StatusText(http.StatusBadRequest)))

		return
	}

	userHashMap, redisError := redis.StringMap((*appContext.redisConnection).Do("HGETALL", userPass.User))

	if redisError != nil {
		log.Fatalln(bodyError)
		response.WriteHeader(http.StatusForbidden)
		response.Write([]byte(http.StatusText(http.StatusForbidden)))

		return
	}

	if userHashMap["password"] == userPass.Pass {
		response.WriteHeader(http.StatusOK)
		response.Write([]byte("You shall pass!"))
	} else {
		log.Fatalln(bodyError)
		response.WriteHeader(http.StatusForbidden)
		response.Write([]byte(http.StatusText(http.StatusForbidden)))

		return
	}
}

func setupRedis(RedisSchemeURL *string) {
	connection, error := redis.DialURL(*RedisSchemeURL)
	if error != nil {
		log.Fatalln("Could not connect to REDIS:", error)
	} else {
		fmt.Println("Connected to REDIS:", *RedisSchemeURL)
	}

	appContext.redisConnection = &connection
}

func setupFlags() (RedisSchemeURL *string, HTTPAddress *string) {
	RedisSchemeURL = flag.String("redis-url", "redis://@localhost:6379/0", "Url to connect to redis")
	HTTPAddress = flag.String("http-address", ":8080", "Http address to bind to")

	flag.Parse()

	return RedisSchemeURL, HTTPAddress
}

func main() {
	RedisSchemeURL, HTTPAddress := setupFlags()

	setupRedis(RedisSchemeURL)

	http.HandleFunc("/auth", authHandler)
	log.Fatalln(http.ListenAndServe(*HTTPAddress, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	log "github.com/Sirupsen/logrus"
	"github.com/julienschmidt/httprouter"
	"github.com/robfig/cron"

	ctrlr "github.com/liam-lai/ptt-alertor/controllers"
	"github.com/liam-lai/ptt-alertor/jobs"
	"github.com/liam-lai/ptt-alertor/line"
	"github.com/liam-lai/ptt-alertor/messenger"
	"github.com/liam-lai/ptt-alertor/myutil"
)

type myRouter struct {
	httprouter.Router
}

func (mr myRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.WithFields(log.Fields{
		"IP":  r.RemoteAddr,
		"URI": r.URL.Path,
	}).Info("visit")
	mr.Router.ServeHTTP(w, r)
}

func newRouter() *myRouter {
	return &myRouter{
		Router: *httprouter.New(),
	}
}

func basicAuth(handle httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		user, password, hasAuth := r.BasicAuth()
		auth := myutil.Config("auth")
		if hasAuth && user == auth["user"] && password == auth["password"] {
			handle(w, r, params)
		} else {
			w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		}
	}
}

func main() {
	log.Info("Start Jobs")
	startJobs()
	// Web Server
	log.Info("Web Server Start on Port 9090")

	router := newRouter()
	router.NotFound = http.FileServer(http.Dir("public"))

	router.GET("/", ctrlr.Index)
	m := messenger.New()
	// boards apis
	router.GET("/boards/:boardName/articles", ctrlr.BoardArticleIndex)
	router.GET("/boards", ctrlr.BoardIndex)

	// users apis
	router.GET("/users/:account", basicAuth(ctrlr.UserFind))
	router.GET("/users", basicAuth(ctrlr.UserAll))
	router.POST("/users", basicAuth(ctrlr.UserCreate))
	router.PUT("/users/:account", basicAuth(ctrlr.UserModify))

	// line
	router.POST("/line/callback", line.HandleRequest)

	// facebook messenger
	router.GET("/messenger/webhook", m.Verify)
	router.POST("/messenger/webhook", m.Received)

	err := http.ListenAndServe(":9090", router)
	if err != nil {
		log.Fatal("ListenAndServer ", err)
	}

}

func startJobs() {
	c := cron.New()
	c.AddFunc("@every 1m", func() {
		new(jobs.Message).Run()
		jobs.NewFetcher().Run()
	})
	c.AddJob("@every 1h", new(jobs.GenBoards))
	c.Start()
}

func init() {
	new(jobs.CleanUpBoards).Run()
	new(jobs.GenBoards).Run()
	jobs.NewFetcher().Run()
}
<commit_msg>check every 30s<commit_after>package main

import (
	"net/http"

	log "github.com/Sirupsen/logrus"
	"github.com/julienschmidt/httprouter"
	"github.com/robfig/cron"

	ctrlr "github.com/liam-lai/ptt-alertor/controllers"
	"github.com/liam-lai/ptt-alertor/jobs"
	"github.com/liam-lai/ptt-alertor/line"
	"github.com/liam-lai/ptt-alertor/messenger"
	"github.com/liam-lai/ptt-alertor/myutil"
)

type myRouter struct {
	httprouter.Router
}

func (mr myRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.WithFields(log.Fields{
		"IP":  r.RemoteAddr,
		"URI": r.URL.Path,
	}).Info("visit")
	mr.Router.ServeHTTP(w, r)
}

func newRouter() *myRouter {
	return &myRouter{
		Router: *httprouter.New(),
	}
}

func basicAuth(handle httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		user, password, hasAuth := r.BasicAuth()
		auth := myutil.Config("auth")
		if hasAuth && user == auth["user"] && password == auth["password"] {
			handle(w, r, params)
		} else {
			w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		}
	}
}

func main() {
	log.Info("Start Jobs")
	startJobs()
	// Web Server
	log.Info("Web Server Start on Port 9090")

	router := newRouter()
	router.NotFound = http.FileServer(http.Dir("public"))

	router.GET("/", ctrlr.Index)
	m := messenger.New()
	// boards apis
	router.GET("/boards/:boardName/articles", ctrlr.BoardArticleIndex)
	router.GET("/boards", ctrlr.BoardIndex)

	// users apis
	router.GET("/users/:account", basicAuth(ctrlr.UserFind))
	router.GET("/users", basicAuth(ctrlr.UserAll))
	router.POST("/users", basicAuth(ctrlr.UserCreate))
	router.PUT("/users/:account", basicAuth(ctrlr.UserModify))

	// line
	router.POST("/line/callback", line.HandleRequest)

	// facebook messenger
	router.GET("/messenger/webhook", m.Verify)
	router.POST("/messenger/webhook", m.Received)

	err := http.ListenAndServe(":9090", router)
	if err != nil {
		log.Fatal("ListenAndServer ", err)
	}

}

func startJobs() {
	c := cron.New()
	c.AddFunc("@every 30s", func() {
		new(jobs.Message).Run()
		jobs.NewFetcher().Run()
	})
	c.AddJob("@every 1h", new(jobs.GenBoards))
	c.Start()
}

func init() {
	new(jobs.CleanUpBoards).Run()
	new(jobs.GenBoards).Run()
	jobs.NewFetcher().Run()
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/cloudfoundry/cli/plugin"
)

func main() {
	localPush := LocalPush{
		OutStream: os.Stdout,
	}

	// Start plugin
	plugin.Start(&localPush)
}
<commit_msg>Add os.Stdin<commit_after>package main

import (
	"os"

	"github.com/cloudfoundry/cli/plugin"
)

func main() {
	localPush := LocalPush{
		OutStream: os.Stdout,
		InStream:  os.Stdin,
	}

	// Start plugin
	plugin.Start(&localPush)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"strings"

	// "github.com/ssbl/trago/db"
)

const (
	SERVFLAG = "-s"
	SERVCMD = "trago -s {dir}"
	serverUsage = "Run in server mode in the specified directory.\n"
)

var (
	server string
	serverDir string
	clientDir string
	flagDir string
	defaultDir = "(nil)"
)

func init() {
	flag.StringVar(&flagDir, "server", defaultDir, serverUsage)
	flag.StringVar(&flagDir, "s", defaultDir, "Shorthand for --server.")

	log.SetFlags(0)
	flag.Usage = usage
}

func main() {
	flag.Parse()

	if flagDir == defaultDir {
		server, serverDir, clientDir := parseArgs()
		log.Printf("%s:%s %s\n", server, serverDir, clientDir)
	}
}

func usage() {
	log.Printf("Usage: trago server:dir client-dir\n\n")

	log.Printf("-s|--server <dir>\n    %s\n", serverUsage);
}

func parseArgs() (string, string, string) {
	var s, sd, cd string

	if len(flag.Args()) != 2 {
		flag.Usage()
		os.Exit(1)
	}

	remote := strings.Split(flag.Arg(0), ":")
	if len(remote) != 2 {
		flag.Usage()
		os.Exit(1)
	} else {
		s = strings.TrimSpace(remote[0])
		sd = strings.TrimSpace(remote[1])
	}

	cd = strings.TrimSpace(flag.Arg(1))

	return s, sd, cd
}
<commit_msg>server mode stuff<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/ssbl/trago/db"
)

const (
	SERVFLAG = "-s"
	SERVCMD = "trago -s {dir}"
	serverUsage = "Run in server mode in the specified directory.\n"
)

var (
	server string
	serverDir string
	clientDir string
	flagDir string
	defaultDir = "(nil)"
)

func init() {
	flag.StringVar(&flagDir, "server", defaultDir, serverUsage)
	flag.StringVar(&flagDir, "s", defaultDir, "Shorthand for --server.")

	log.SetFlags(0)
	flag.Usage = usage
}

func main() {
	flag.Parse()

	if flagDir == defaultDir {
		server, serverDir, clientDir := parseArgs()
		log.Printf("%s:%s %s\n", server, serverDir, clientDir)
	} else {	  // running in server mode, so we ignore all other flags
		if err := os.Chdir(flagDir); err != nil {
			log.Fatalf("Error changing to directory: %s\n", err)
		}

		tradb, err := db.ParseFile()
		if err != nil {
			log.Fatalf("Error parsing db file: %s\n", err)
		}

		tradb.Update()
		fmt.Println(tradb)		// send db to stdout
	}
}

func usage() {
	log.Printf("Usage: trago server:dir client-dir\n\n")

	log.Printf("-s|--server <dir>\n    %s\n", serverUsage);
}

func parseArgs() (string, string, string) {
	var s, sd, cd string

	if len(flag.Args()) != 2 {
		flag.Usage()
		os.Exit(1)
	}

	remote := strings.Split(flag.Arg(0), ":")
	if len(remote) != 2 {
		flag.Usage()
		os.Exit(1)
	} else {
		s = strings.TrimSpace(remote[0])
		sd = strings.TrimSpace(remote[1])
	}

	cd = strings.TrimSpace(flag.Arg(1))

	return s, sd, cd
}
<|endoftext|>