<commit_before>package main

import (
	"net/http"
	"os"

	"github.com/codegangsta/negroni"
	"gopkg.in/unrolled/render.v1"
)

var (
	port     = getEnvDefault("PORT", "3000")
	renderer = render.New(render.Options{})
)

func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
	renderer.JSON(w, http.StatusOK, map[string]string{"status": "OK"})
}

func main() {
	httpMux := http.NewServeMux()
	httpMux.HandleFunc("/healthcheck", HealthCheckHandler)

	middleware := negroni.New()
	middleware.UseHandler(httpMux)
	middleware.Run(":" + port)
}

func getEnvDefault(key string, defaultVal string) string {
	val := os.Getenv(key)
	if val == "" {
		return defaultVal
	}

	return val
}
<commit_msg>Log requests using JSON<commit_after>package main

import (
	"net/http"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/meatballhat/negroni-logrus"
	"gopkg.in/unrolled/render.v1"
)

var (
	loggingMiddleware = negronilogrus.NewCustomMiddleware(
		logrus.InfoLevel, &logrus.JSONFormatter{}, "publishing-api")
	port     = getEnvDefault("PORT", "3000")
	renderer = render.New(render.Options{})
)

func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
	renderer.JSON(w, http.StatusOK, map[string]string{"status": "OK"})
}

func main() {
	httpMux := http.NewServeMux()
	httpMux.HandleFunc("/healthcheck", HealthCheckHandler)

	middleware := negroni.New()
	middleware.Use(loggingMiddleware)
	middleware.UseHandler(httpMux)
	middleware.Run(":" + port)
}

func getEnvDefault(key string, defaultVal string) string {
	val := os.Getenv(key)
	if val == "" {
		return defaultVal
	}

	return val
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/google/gops/agent"
	"github.com/julienschmidt/httprouter"
	log "github.com/meifamily/logrus"
	"github.com/robfig/cron"

	ctrlr "github.com/meifamily/ptt-alertor/controllers"
	"github.com/meifamily/ptt-alertor/jobs"
	"github.com/meifamily/ptt-alertor/line"
	"github.com/meifamily/ptt-alertor/messenger"
	"github.com/meifamily/ptt-alertor/myutil"
	"github.com/meifamily/ptt-alertor/telegram"
)

var auth map[string]string

type myRouter struct {
	httprouter.Router
}

func (mr myRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.WithFields(log.Fields{
		"method": r.Method,
		"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()
		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"))
	m := messenger.New()

	router.GET("/", ctrlr.Index)
	router.GET("/messenger", ctrlr.MessengerIndex)
	router.GET("/line", ctrlr.LineIndex)
	router.GET("/telegram", ctrlr.TelegramIndex)
	router.GET("/redirect/:sha1", ctrlr.Redirect)
	router.GET("/top", ctrlr.Top)
	router.GET("/docs", ctrlr.Docs)

	// websocket
	router.GET("/ws", ctrlr.WebSocket)

	router.POST("/broadcast", basicAuth(ctrlr.Broadcast))

	// boards apis
	router.GET("/boards/:boardName/articles/:code", ctrlr.BoardArticle)
	router.GET("/boards/:boardName/articles", ctrlr.BoardArticleIndex)
	router.GET("/boards", ctrlr.BoardIndex)

	// keyword apis
	router.GET("/keyword/boards", ctrlr.KeywordBoards)

	// author apis
	router.GET("/author/boards", ctrlr.AuthorBoards)

	// pushsum apis
	router.GET("/pushsum/boards", ctrlr.PushSumBoards)

	// articles apis
	router.GET("/articles", ctrlr.ArticleIndex)

	// 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)
	router.POST("/line/notify/callback", line.CatchCallback)

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

	// telegram
	router.POST("/telegram/"+telegram.Token, telegram.HandleRequest)

	// gops agent
	if err := agent.Listen(&agent.Options{Addr: ":6060", NoShutdownCleanup: false}); err != nil {
		log.Fatal(err)
	}

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

}

func startJobs() {
	go jobs.NewChecker().Run()
	go jobs.NewPushListChecker().Run()
	go jobs.NewPushSumChecker().Run()
	c := cron.New()
	c.AddJob("@hourly", jobs.NewTop())
	c.AddJob("@every 3d", jobs.NewPushSumKeyReplacer())
	c.Start()
}

func init() {
	auth = myutil.Config("auth")
	jobs.NewTop().Run()
	// for initial app
	// jobs.NewCacheCleaner().Run()
	// jobs.NewGenerator().Run()
	// jobs.NewFetcher().Run()
}
<commit_msg>get telegram token from config<commit_after>package main

import (
	"net/http"

	"github.com/google/gops/agent"
	"github.com/julienschmidt/httprouter"
	log "github.com/meifamily/logrus"
	"github.com/robfig/cron"

	ctrlr "github.com/meifamily/ptt-alertor/controllers"
	"github.com/meifamily/ptt-alertor/jobs"
	"github.com/meifamily/ptt-alertor/line"
	"github.com/meifamily/ptt-alertor/messenger"
	"github.com/meifamily/ptt-alertor/myutil"
	"github.com/meifamily/ptt-alertor/telegram"
)

var auth map[string]string
var telegramToken string

type myRouter struct {
	httprouter.Router
}

func (mr myRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.WithFields(log.Fields{
		"method": r.Method,
		"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()
		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"))
	m := messenger.New()

	router.GET("/", ctrlr.Index)
	router.GET("/messenger", ctrlr.MessengerIndex)
	router.GET("/line", ctrlr.LineIndex)
	router.GET("/telegram", ctrlr.TelegramIndex)
	router.GET("/redirect/:sha1", ctrlr.Redirect)
	router.GET("/top", ctrlr.Top)
	router.GET("/docs", ctrlr.Docs)

	// websocket
	router.GET("/ws", ctrlr.WebSocket)

	router.POST("/broadcast", basicAuth(ctrlr.Broadcast))

	// boards apis
	router.GET("/boards/:boardName/articles/:code", ctrlr.BoardArticle)
	router.GET("/boards/:boardName/articles", ctrlr.BoardArticleIndex)
	router.GET("/boards", ctrlr.BoardIndex)

	// keyword apis
	router.GET("/keyword/boards", ctrlr.KeywordBoards)

	// author apis
	router.GET("/author/boards", ctrlr.AuthorBoards)

	// pushsum apis
	router.GET("/pushsum/boards", ctrlr.PushSumBoards)

	// articles apis
	router.GET("/articles", ctrlr.ArticleIndex)

	// 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)
	router.POST("/line/notify/callback", line.CatchCallback)

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

	// telegram
	router.POST("/telegram/"+telegramToken, telegram.HandleRequest)

	// gops agent
	if err := agent.Listen(&agent.Options{Addr: ":6060", NoShutdownCleanup: false}); err != nil {
		log.Fatal(err)
	}

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

}

func startJobs() {
	go jobs.NewChecker().Run()
	go jobs.NewPushListChecker().Run()
	go jobs.NewPushSumChecker().Run()
	c := cron.New()
	c.AddJob("@hourly", jobs.NewTop())
	c.AddJob("@every 3d", jobs.NewPushSumKeyReplacer())
	c.Start()
}

func init() {
	auth = myutil.Config("auth")
	telegramToken = myutil.Config("telegram")["token"]
	jobs.NewTop().Run()
	// for initial app
	// jobs.NewCacheCleaner().Run()
	// jobs.NewGenerator().Run()
	// jobs.NewFetcher().Run()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudfront"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/lambda"
	"github.com/aws/aws-sdk-go/service/rds"
)

type Result struct {
	Data interface{} `json:"data"`
}

func main() {
	var (
		discoveryType = flag.String("type", "", "type of discovery. EC2, ELB, RDS, CloudFront, Lambda or ECSClusters")
		awsRegion     = flag.String("aws.region", "eu-central-1", "AWS region")
		list          interface{}
		err           error
	)

	flag.Parse()

	awsSession := session.New(aws.NewConfig().WithRegion(*awsRegion))

	switch *discoveryType {
	case "ELB":
		list, err = getAllElasticLoadBalancers(elb.New(awsSession))
		if err != nil {
			log.Fatalf("Could not descibe load balancers: %v", err)
		}
	case "EC2":
		list, err = getAllEC2Instances(ec2.New(awsSession))
		if err != nil {
			log.Fatalf("Could not get ec2 instances: %v", err)
		}
	case "RDS":
		list, err = getAllDBInstances(rds.New(awsSession))
		if err != nil {
			log.Fatalf("Could not describe db instances: %v", err)
		}
	case "CloudFront":
		list, err = getAllCloudFrontDistributions(cloudfront.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list distributions")
		}
	case "ECSClusters":
		list, err = listECSClusters(ecs.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list ECS clusters")
		}
	case "Lambda":
		list, err = getAllLambdas(lambda.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list lambdas")
		}
	default:
		log.Fatalf("discovery type %s not supported", *discoveryType)
	}

	err = json.NewEncoder(os.Stdout).Encode(Result{Data: list})

	if err != nil {
		log.Fatal(err)
	}
}

func getAllEC2Instances(ec2Cli interface {
	DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error)
}) ([]map[string]string, error) {

	resp, err := ec2Cli.DescribeInstances(&ec2.DescribeInstancesInput{})

	if err != nil {
		return nil, fmt.Errorf("getting EC2 instances: %v", err)
	}

	ec2Identifiers := make([]map[string]string, 0, len(resp.Reservations))

	for _, reservation := range resp.Reservations {
		for _, instance := range reservation.Instances {
			var name string
			for _, t := range instance.Tags {
				if *t.Key == "Name" {
					name = *t.Value
					break
				}
			}
			ec2Identifiers = append(ec2Identifiers, map[string]string{
				"{#INSTANCEID}":   *instance.InstanceId,
				"{#INSTANCENAME}": name,
			})
		}

	}
	return ec2Identifiers, nil
}

func getAllDBInstances(rdsCli interface {
	DescribeDBInstances(input *rds.DescribeDBInstancesInput) (*rds.DescribeDBInstancesOutput, error)
}) ([]map[string]string, error) {
	resp, err := rdsCli.DescribeDBInstances(&rds.DescribeDBInstancesInput{})

	if err != nil {
		return nil, fmt.Errorf("getting RDS instances:%v", err)
	}

	rdsIdentifiers := make([]map[string]string, 0, len(resp.DBInstances))

	for _, rds := range resp.DBInstances {

		var dbName string

		// avoiding nil pointer dereference
		if rds.DBName != nil {
			dbName = *rds.DBName
		}

		rdsIdentifiers = append(rdsIdentifiers, map[string]string{
			"{#RDSIDENTIFIER}": *rds.DBInstanceIdentifier,
			"{#RDSDBNAME}":     dbName,
		})
	}

	return rdsIdentifiers, nil
}

func getAllCloudFrontDistributions(cloudFrontCli interface {
	ListDistributions(*cloudfront.ListDistributionsInput) (*cloudfront.ListDistributionsOutput, error)
}) ([]map[string]string, error) {

	resp, err := cloudFrontCli.ListDistributions(&cloudfront.ListDistributionsInput{})

	if err != nil {
		return nil, fmt.Errorf("listing CloudFront distributions %v", err)
	}

	dists := make([]map[string]string, len(resp.DistributionList.Items))

	for ctr, dist := range resp.DistributionList.Items {
		dists[ctr] = map[string]string{
			"{#DISTID}":    *dist.Id,
			"{#DISTALIAS}": *dist.Aliases.Items[0],
		}
	}

	return dists, nil
}

func getAllElasticLoadBalancers(elbCli interface {
	DescribeLoadBalancers(*elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error)
}) ([]map[string]string, error) {

	resp, err := elbCli.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{})

	if err != nil {
		return nil, fmt.Errorf("reading ELBs:%v", err)
	}

	elbs := make([]map[string]string, len(resp.LoadBalancerDescriptions))

	for ctr, elb := range resp.LoadBalancerDescriptions {
		elbs[ctr] = map[string]string{
			"{#LOADBALANCERNAME}": *elb.LoadBalancerName,
		}
	}

	return elbs, nil
}

func listECSClusters(ecsCli interface {
	ListClusters(*ecs.ListClustersInput) (*ecs.ListClustersOutput, error)
}) ([]map[string]string, error) {

	resp, err := ecsCli.ListClusters(&ecs.ListClustersInput{})

	if err != nil {
		return nil, fmt.Errorf("listing ECS clusters %v", err)
	}

	clusterNames := make([]map[string]string, 0, len(resp.ClusterArns))

	for _, clusterArn := range resp.ClusterArns {
		clusterNames = append(clusterNames, map[string]string{
			"{#CLUSTERNAME}": parseClusterName(*clusterArn),
		})
	}

	return clusterNames, nil
}

func getAllLambdas(lambdaCli interface {
	ListFunctions(*lambda.ListFunctionsInput) (*lambda.ListFunctionsOutput, error)
}) ([]map[string]string, error) {

	resp, err := lambdaCli.ListFunctions(&lambda.ListFunctionsInput{})

	if err != nil {
		return nil, fmt.Errorf("listing lambdas %v", err)
	}

	lambdas := make([]map[string]string, len(resp.Functions))

	for ctr, lambda := range resp.Functions {
		lambdas[ctr] = map[string]string{
			"{#FUNCTIONNAME}": *lambda.FunctionName,
		}
	}

	return lambdas, nil
}

func parseClusterName(clusterArn string) string {
	return strings.SplitAfter(clusterArn, "/")[1]
}
<commit_msg>add ecs sevices discovery<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudfront"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/lambda"
	"github.com/aws/aws-sdk-go/service/rds"
)

type Result struct {
	Data interface{} `json:"data"`
}

func main() {
	var (
		discoveryType = flag.String("type", "", "type of discovery. EC2, ELB, RDS, CloudFront, Lambda or ECSClusters")
		awsRegion     = flag.String("aws.region", "eu-central-1", "AWS region")
		list          interface{}
		err           error
	)

	flag.Parse()

	awsSession := session.New(aws.NewConfig().WithRegion(*awsRegion))

	switch *discoveryType {
	case "ELB":
		list, err = getAllElasticLoadBalancers(elb.New(awsSession))
		if err != nil {
			log.Fatalf("Could not descibe load balancers: %v", err)
		}
	case "EC2":
		list, err = getAllEC2Instances(ec2.New(awsSession))
		if err != nil {
			log.Fatalf("Could not get ec2 instances: %v", err)
		}
	case "RDS":
		list, err = getAllDBInstances(rds.New(awsSession))
		if err != nil {
			log.Fatalf("Could not describe db instances: %v", err)
		}
	case "CloudFront":
		list, err = getAllCloudFrontDistributions(cloudfront.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list distributions")
		}
	case "ECSClusters":
		list, err = listECSClusters(ecs.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list ECS clusters")
		}
	case "Lambda":
		list, err = getAllLambdas(lambda.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list lambdas")
		}
	case "ECSServices":
		list, err = listECSServices(ecs.New(awsSession))
		if err != nil {
			log.Fatalf("Could not list ECS services")
		}
	default:
		log.Fatalf("discovery type %s not supported", *discoveryType)
	}

	err = json.NewEncoder(os.Stdout).Encode(Result{Data: list})

	if err != nil {
		log.Fatal(err)
	}
}

func getAllEC2Instances(ec2Cli interface {
	DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error)
}) ([]map[string]string, error) {

	resp, err := ec2Cli.DescribeInstances(&ec2.DescribeInstancesInput{})

	if err != nil {
		return nil, fmt.Errorf("getting EC2 instances: %v", err)
	}

	ec2Identifiers := make([]map[string]string, 0, len(resp.Reservations))

	for _, reservation := range resp.Reservations {
		for _, instance := range reservation.Instances {
			var name string
			for _, t := range instance.Tags {
				if *t.Key == "Name" {
					name = *t.Value
					break
				}
			}
			ec2Identifiers = append(ec2Identifiers, map[string]string{
				"{#INSTANCEID}":   *instance.InstanceId,
				"{#INSTANCENAME}": name,
			})
		}

	}
	return ec2Identifiers, nil
}

func getAllDBInstances(rdsCli interface {
	DescribeDBInstances(input *rds.DescribeDBInstancesInput) (*rds.DescribeDBInstancesOutput, error)
}) ([]map[string]string, error) {
	resp, err := rdsCli.DescribeDBInstances(&rds.DescribeDBInstancesInput{})

	if err != nil {
		return nil, fmt.Errorf("getting RDS instances:%v", err)
	}

	rdsIdentifiers := make([]map[string]string, 0, len(resp.DBInstances))

	for _, rds := range resp.DBInstances {

		var dbName string

		// avoiding nil pointer dereference
		if rds.DBName != nil {
			dbName = *rds.DBName
		}

		rdsIdentifiers = append(rdsIdentifiers, map[string]string{
			"{#RDSIDENTIFIER}": *rds.DBInstanceIdentifier,
			"{#RDSDBNAME}":     dbName,
		})
	}

	return rdsIdentifiers, nil
}

func getAllCloudFrontDistributions(cloudFrontCli interface {
	ListDistributions(*cloudfront.ListDistributionsInput) (*cloudfront.ListDistributionsOutput, error)
}) ([]map[string]string, error) {

	resp, err := cloudFrontCli.ListDistributions(&cloudfront.ListDistributionsInput{})

	if err != nil {
		return nil, fmt.Errorf("listing CloudFront distributions %v", err)
	}

	dists := make([]map[string]string, len(resp.DistributionList.Items))

	for ctr, dist := range resp.DistributionList.Items {
		dists[ctr] = map[string]string{
			"{#DISTID}":    *dist.Id,
			"{#DISTALIAS}": *dist.Aliases.Items[0],
		}
	}

	return dists, nil
}

func getAllElasticLoadBalancers(elbCli interface {
	DescribeLoadBalancers(*elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error)
}) ([]map[string]string, error) {

	resp, err := elbCli.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{})

	if err != nil {
		return nil, fmt.Errorf("reading ELBs:%v", err)
	}

	elbs := make([]map[string]string, len(resp.LoadBalancerDescriptions))

	for ctr, elb := range resp.LoadBalancerDescriptions {
		elbs[ctr] = map[string]string{
			"{#LOADBALANCERNAME}": *elb.LoadBalancerName,
		}
	}

	return elbs, nil
}

func listECSClusters(ecsCli interface {
	ListClusters(*ecs.ListClustersInput) (*ecs.ListClustersOutput, error)
}) ([]map[string]string, error) {

	resp, err := ecsCli.ListClusters(&ecs.ListClustersInput{})

	if err != nil {
		return nil, fmt.Errorf("listing ECS clusters %v", err)
	}

	clusterNames := make([]map[string]string, 0, len(resp.ClusterArns))

	for _, clusterArn := range resp.ClusterArns {
		clusterNames = append(clusterNames, map[string]string{
			"{#CLUSTERNAME}": parseClusterName(*clusterArn),
		})
	}

	return clusterNames, nil
}

func listECSServices(ecsCli *ecs.ECS) ([]map[string]string, error) {

	clusters, err := listECSClusters(ecsCli)

	if err != nil {
		return nil, fmt.Errorf("listing ECS services %v", err)
	}

	var serviceNames []map[string]string

	for _, cluster := range clusters {
		resp, err := ecsCli.ListServices(&ecs.ListServicesInput{
			Cluster: aws.String(cluster["{#CLUSTERNAME}"]),
		})

		if err != nil {
			return nil, fmt.Errorf("listing ECS services %v", err)
		}

		for _, serviceArn := range resp.ServiceArns {
			serviceNames = append(serviceNames, map[string]string{
				"{#CLUSTERNAME}": cluster["{#CLUSTERNAME}"],
				"{#SERVICENAME}": parseClusterName(*serviceArn),
			})
		}
	}

	return serviceNames, nil
}

func getAllLambdas(lambdaCli interface {
	ListFunctions(*lambda.ListFunctionsInput) (*lambda.ListFunctionsOutput, error)
}) ([]map[string]string, error) {

	resp, err := lambdaCli.ListFunctions(&lambda.ListFunctionsInput{})

	if err != nil {
		return nil, fmt.Errorf("listing lambdas %v", err)
	}

	lambdas := make([]map[string]string, len(resp.Functions))

	for ctr, lambda := range resp.Functions {
		lambdas[ctr] = map[string]string{
			"{#FUNCTIONNAME}": *lambda.FunctionName,
		}
	}

	return lambdas, nil
}

func parseClusterName(clusterArn string) string {
	return strings.SplitAfter(clusterArn, "/")[1]
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/crockeo/personalwebsite/config"
	"github.com/crockeo/personalwebsite/handlers"
	"io/ioutil"
	"os"
)

const (
	defaultAuth string = "admin|password"
)

// Checking if a file exists
func exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}

	return true
}

// Functions initialize the project structure
func PreRunInit() {
	os.Mkdir(config.DataDirectory, 0775)
	os.Mkdir(config.PostsDir, 0775)

	if !exists(config.AuthLoc) {
		ioutil.WriteFile(config.AuthLoc, []byte(defaultAuth), 0664)
	}

	if !exists(config.PostIndexLoc) {
		ioutil.WriteFile(config.PostIndexLoc, []byte("0"), 0664)
	}
}

// The main function
func main() {
	PreRunInit()
	handlers.InitHandlersAndStart()
}
<commit_msg>Made the PreRunInit() function work for the new SQL system.<commit_after>package main

import (
	"github.com/crockeo/personalwebsite/database"
	"github.com/crockeo/personalwebsite/handlers"
)

// Functions initialize the project structure
func PreRunInit() {
	db, err := database.OpenDefaultDatabase()

	if err != nil {
		panic(err)
	}
	defer db.Close()

	err = database.CreateDatabaseSchema(db)

	if err != nil {
		panic(err)
	}

	db.Close()
}

// The main function
func main() {
	PreRunInit()
	handlers.InitHandlersAndStart()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/bjwbell/gensimd/codegen"
	"github.com/bjwbell/gensimd/simd"

	"go/build"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
	"golang.org/x/tools/go/types"
)

func filePath(pathName string) string {
	split := strings.Split(pathName, "/")
	dir := ""
	if len(split) == 1 {
		dir = "."
	} else if len(split) == 2 {
		dir = split[0] + "/"
	} else {
		dir = strings.Join(split[0:len(split)-2], "/") // + "/"
	}
	return dir
}

func fileName(pathName string) string {
	split := strings.Split(pathName, "/")
	name := ""
	if len(split) == 0 {
		name = ""
	} else {
		name = split[len(split)-1]
	}
	return name
}

func main() {
	flag.Parse()
	args := flag.Args()
	file := os.ExpandEnv("$GOFILE")
	funcName := ""
	if len(args) == 1 {
		funcName = args[0]

	} else if len(args) == 2 {
		file = args[0]
		funcName = args[1]
	}
	f, err := simd.ParseFile(file)
	if err == nil {
		fmt.Println("Parsed: ", file)
	} else {
		fmt.Println(fmt.Sprintf("Error parsing file \"%v\", error: %v", file, err))
		return
	}

	filePkgName := f.Pkg.Name()
	filePkgPath := f.Pkg.Path()
	conf := loader.Config{Build: &build.Default}

	// Choose types.Sizes from conf.Build.
	var wordSize int64 = 8
	switch conf.Build.GOARCH {
	case "386", "arm":
		panic("SIMD invalid for x86 and arm")
	}
	conf.TypeChecker.Sizes = &types.StdSizes{
		MaxAlign: 8,
		WordSize: wordSize,
	}

	// Use the initial file from the command line/$GOFILE.
	conf.CreateFromFilenames(filePath(file), file)

	// Load, parse and type-check
	iprog, err := conf.Load()
	if err != nil {
		fmt.Println("err:", err)
		return
	}

	// Create and build SSA-form program representation.
	prog := ssautil.CreateProgram(iprog, ssa.PrintFunctions)
	if prog == nil {
		fmt.Println("prog == nil")
	}
	// Build and display only the initial packages (and synthetic wrappers)
	for _, info := range iprog.InitialPackages() {
		prog.Package(info.Pkg).Build()
	}

	// TODO generate assembly instructions

	for _, pkg := range prog.AllPackages() {
		if pkg.Pkg.Path() == filePkgPath+"/" && pkg.Pkg.Name() == filePkgName {
			fmt.Println("found filePkgName:", filePkgName)
			if fn := pkg.Func(funcName); fn == nil {
				fmt.Println(fmt.Printf("Error function \"%v\" not found in \"%v\" package", funcName, filePkgName))
				return
			} else {
				fmt.Println("found function:", funcName)
				codegenFn, err := codegen.CreateFunction("codegen/instructionsetxml/Opcodes/opcodes/x86_64.xml", fn)
				if err != nil {
					fmt.Printf("Error in codegen.CreateFunction,  msg:\"%v\"", err)
				}
				if asm, err := codegenFn.GoAssembly(); err != nil {
					fmt.Println(asm)
					fmt.Printf("Error creating fn asm, msg:\"%v\"\n", err)
				} else {
					fmt.Println("fn asm:")
					fmt.Println(asm)
				}
			}
		}
	}
}
<commit_msg>Add flag "ssa" to control dumping ssa representation<commit_after>package main

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

	"github.com/bjwbell/gensimd/codegen"
	"github.com/bjwbell/gensimd/simd"

	"go/build"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
	"golang.org/x/tools/go/types"
)

func filePath(pathName string) string {
	split := strings.Split(pathName, "/")
	dir := ""
	if len(split) == 1 {
		dir = "."
	} else if len(split) == 2 {
		dir = split[0] + "/"
	} else {
		dir = strings.Join(split[0:len(split)-2], "/") // + "/"
	}
	return dir
}

func fileName(pathName string) string {
	split := strings.Split(pathName, "/")
	name := ""
	if len(split) == 0 {
		name = ""
	} else {
		name = split[len(split)-1]
	}
	return name
}

func main() {
	var ssaDump = flag.Bool("ssa", false, "dump ssa representation")
	flag.Parse()
	args := flag.Args()
	file := os.ExpandEnv("$GOFILE")
	funcName := ""
	if len(args) == 1 {
		funcName = args[0]

	} else if len(args) == 2 {
		file = args[0]
		funcName = args[1]
	}
	f, err := simd.ParseFile(file)
	if err == nil {
		fmt.Println("Parsed: ", file)
	} else {
		fmt.Println(fmt.Sprintf("Error parsing file \"%v\", error: %v", file, err))
		return
	}

	filePkgName := f.Pkg.Name()
	filePkgPath := f.Pkg.Path()
	conf := loader.Config{Build: &build.Default}

	// Choose types.Sizes from conf.Build.
	var wordSize int64 = 8
	switch conf.Build.GOARCH {
	case "386", "arm":
		panic("SIMD invalid for x86 and arm")
	}
	conf.TypeChecker.Sizes = &types.StdSizes{
		MaxAlign: 8,
		WordSize: wordSize,
	}

	// Use the initial file from the command line/$GOFILE.
	conf.CreateFromFilenames(filePath(file), file)

	// Load, parse and type-check
	iprog, err := conf.Load()
	if err != nil {
		fmt.Println("err:", err)
		return
	}

	// Create and build SSA-form program representation.
	builderMode := ssa.SanityCheckFunctions
	if *ssaDump {
		builderMode = ssa.PrintFunctions
	}
	prog := ssautil.CreateProgram(iprog, builderMode)
	if prog == nil {
		fmt.Println("prog == nil")
	}
	// Build and display only the initial packages (and synthetic wrappers)
	for _, info := range iprog.InitialPackages() {
		prog.Package(info.Pkg).Build()
	}

	// TODO generate assembly instructions

	for _, pkg := range prog.AllPackages() {
		if pkg.Pkg.Path() == filePkgPath+"/" && pkg.Pkg.Name() == filePkgName {
			fmt.Println("found filePkgName:", filePkgName)
			if fn := pkg.Func(funcName); fn == nil {
				fmt.Println(fmt.Printf("Error function \"%v\" not found in \"%v\" package", funcName, filePkgName))
				return
			} else {
				fmt.Println("found function:", funcName)
				codegenFn, err := codegen.CreateFunction("codegen/instructionsetxml/Opcodes/opcodes/x86_64.xml", fn)
				if err != nil {
					fmt.Printf("Error in codegen.CreateFunction,  msg:\"%v\"", err)
				}
				if asm, err := codegenFn.GoAssembly(); err != nil {
					fmt.Println(asm)
					fmt.Printf("Error creating fn asm, msg:\"%v\"\n", err)
				} else {
					fmt.Println("fn asm:")
					fmt.Println(asm)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/mpdroog/beanstalkd" //"github.com/maxid/beanstalkd"
	"gopkg.in/gomail.v1"
	"os"
	"smtpw/config"
	"strings"
	"time"
)

const ERR_WAIT_SEC = 5

var verbose bool
var readonly bool
var hostname string

func proc(m config.Email) error {
	conf, ok := config.C.From[m.From]
	if !ok {
		return errors.New("From does not exist: " + m.From)
	}

	msg := gomail.NewMessage()
	msg.SetHeader("Message-ID", fmt.Sprintf("<%s@%s>", RandText(32), hostname))
	if conf.Bounce == nil {
		msg.SetHeader("From", conf.Display+" <"+conf.From+">")
	} else {
		// Set bounce handling
		// From receives bounces
		// Human-clients send to Reply-To
		msg.SetHeader("From", fmt.Sprintf("%s <%s>", conf.Display, *conf.Bounce))
		msg.SetHeader("Reply-To", fmt.Sprintf("%s <%s>", conf.Display, conf.From))
	}
	msg.SetHeader("To", m.To...)
	msg.SetHeader("Bcc", conf.Bcc...)
	msg.SetHeader("Subject", m.Subject)
	msg.SetBody("text/plain", m.Text)
	if len(m.Html) > 0 {
		msg.AddAlternative("text/html", m.Html)
	}

	for name, embed := range m.HtmlEmbed {
		raw, e := base64.StdEncoding.DecodeString(embed)
		if e != nil {
			return errors.New("HtmlEmbed: " + name + " is not base64!")
		}
		if !strings.Contains(m.Html, fmt.Sprintf("cid:"+name)) {
			return errors.New("HtmlEmbed: " + name + " is not used in the HTML!")
		}
		msg.Embed(gomail.CreateFile(name, raw))
	}
	for name, attachment := range m.Attachments {
		raw, e := base64.StdEncoding.DecodeString(attachment)
		if e != nil {
			return errors.New("Attachment: " + name + " is not base64!")
		}
		msg.Embed(gomail.CreateFile(name, raw))
	}

	if readonly {
		fmt.Println("From: " + conf.Display + " <" + conf.From + ">")
		fmt.Println(fmt.Sprintf("To: %v", m.To))
		fmt.Println(fmt.Sprintf("Bcc: %v", conf.Bcc))
		fmt.Println("Subject: " + m.Subject)
		fmt.Println("\ntext/plain")
		fmt.Println(m.Text)
		fmt.Println("\ntext/html")
		fmt.Println(m.Html)
		fmt.Println("\n")
		return nil
	}

	mailer := gomail.NewMailer(conf.Host, conf.User, conf.Pass, conf.Port)
	return mailer.Send(msg)
}

func connect() (*beanstalkd.BeanstalkdClient, error) {
	queue, e := beanstalkd.Dial(config.C.Beanstalk)
	if e != nil {
		return nil, e
	}
	// Only listen to email queue.
	queue.Use("email")
	if _, e := queue.Watch("email"); e != nil {
		return nil, e
	}
	queue.Ignore("default")
	return queue, nil
}

func main() {
	var (
		configPath string
		skipOne    bool
	)
	flag.BoolVar(&verbose, "v", false, "Verbose-mode")
	flag.BoolVar(&skipOne, "s", false, "Delete e-mail on deverr")
	flag.BoolVar(&readonly, "r", false, "Don't email but flush to stdout")
	flag.StringVar(&configPath, "c", "./config.json", "Path to config.json")
	flag.Parse()

	if e := config.Init(configPath); e != nil {
		panic(e)
	}
	if verbose {
		fmt.Printf("%+v\n", config.C)
	}
	// TODO: Test config before starting?

	queue, e := connect()
	if e != nil {
		panic(e)
	}
	hostname, e = os.Hostname()
	if e != nil {
		panic(e)
	}

	if verbose {
		fmt.Println("SMTPw(" + hostname + ") email-tube (ignoring default)")
	}
	if readonly {
		fmt.Println("!! ReadOnly mode !!")
	}
	for {
		job, e := queue.Reserve(0)
		if e != nil {
			fmt.Println("Beanstalkd err: " + e.Error())
			time.Sleep(time.Second * ERR_WAIT_SEC)
			if strings.HasSuffix(e.Error(), "broken pipe") {
				// Beanstalkd down, reconnect!
				q, e := connect()
				if e != nil {
					fmt.Println("Reconnect err: " + e.Error())
				}
				if q != nil {
					queue = q
				}
			}
			continue
		}
		if verbose {
			fmt.Println(fmt.Sprintf("Parse job %d", job.Id))
			fmt.Println("JSON:\r\n" + string(job.Data))
		}
		// Parse
		var m config.Email
		if e := json.Unmarshal(job.Data, &m); e != nil {
			// Broken JSON
			if skipOne {
				fmt.Println("WARN: Skip job as JSON is invalid")
				queue.Delete(job.Id)
				skipOne = false
				continue
			}

			// Ignore decode trouble
			fmt.Println("CRIT: Invalid JSON received (msg=" + e.Error() + ")")
			continue
		}

		if e := proc(m); e != nil {
			// TODO: Isolate deverr from senderr
			// Processing trouble?
			fmt.Println("WARN: Failed sending, retry in 20sec (msg=" + e.Error() + ")")
			time.Sleep(time.Second * 20)
			continue
		}
		queue.Delete(job.Id)
		if verbose {
			fmt.Println(fmt.Sprintf("Finished job %d", job.Id))
		}
	}
	queue.Quit()
}
<commit_msg>Feature. Reserve with timeout (15min) so we can't get an infinit waiting process<commit_after>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/mpdroog/beanstalkd" //"github.com/maxid/beanstalkd"
	"gopkg.in/gomail.v1"
	"os"
	"smtpw/config"
	"strings"
	"time"
)

const ERR_WAIT_SEC = 5
var errTimedOut = errors.New("timed out")

var verbose bool
var readonly bool
var hostname string

func proc(m config.Email) error {
	conf, ok := config.C.From[m.From]
	if !ok {
		return errors.New("From does not exist: " + m.From)
	}

	msg := gomail.NewMessage()
	msg.SetHeader("Message-ID", fmt.Sprintf("<%s@%s>", RandText(32), hostname))
	if conf.Bounce == nil {
		msg.SetHeader("From", conf.Display+" <"+conf.From+">")
	} else {
		// Set bounce handling
		// From receives bounces
		// Human-clients send to Reply-To
		msg.SetHeader("From", fmt.Sprintf("%s <%s>", conf.Display, *conf.Bounce))
		msg.SetHeader("Reply-To", fmt.Sprintf("%s <%s>", conf.Display, conf.From))
	}
	msg.SetHeader("To", m.To...)
	msg.SetHeader("Bcc", conf.Bcc...)
	msg.SetHeader("Subject", m.Subject)
	msg.SetBody("text/plain", m.Text)
	if len(m.Html) > 0 {
		msg.AddAlternative("text/html", m.Html)
	}

	for name, embed := range m.HtmlEmbed {
		raw, e := base64.StdEncoding.DecodeString(embed)
		if e != nil {
			return errors.New("HtmlEmbed: " + name + " is not base64!")
		}
		if !strings.Contains(m.Html, fmt.Sprintf("cid:"+name)) {
			return errors.New("HtmlEmbed: " + name + " is not used in the HTML!")
		}
		msg.Embed(gomail.CreateFile(name, raw))
	}
	for name, attachment := range m.Attachments {
		raw, e := base64.StdEncoding.DecodeString(attachment)
		if e != nil {
			return errors.New("Attachment: " + name + " is not base64!")
		}
		msg.Embed(gomail.CreateFile(name, raw))
	}

	if readonly {
		fmt.Println("From: " + conf.Display + " <" + conf.From + ">")
		fmt.Println(fmt.Sprintf("To: %v", m.To))
		fmt.Println(fmt.Sprintf("Bcc: %v", conf.Bcc))
		fmt.Println("Subject: " + m.Subject)
		fmt.Println("\ntext/plain")
		fmt.Println(m.Text)
		fmt.Println("\ntext/html")
		fmt.Println(m.Html)
		fmt.Println("\n")
		return nil
	}

	mailer := gomail.NewMailer(conf.Host, conf.User, conf.Pass, conf.Port)
	return mailer.Send(msg)
}

func connect() (*beanstalkd.BeanstalkdClient, error) {
	queue, e := beanstalkd.Dial(config.C.Beanstalk)
	if e != nil {
		return nil, e
	}
	// Only listen to email queue.
	queue.Use("email")
	if _, e := queue.Watch("email"); e != nil {
		return nil, e
	}
	queue.Ignore("default")
	return queue, nil
}

func main() {
	var (
		configPath string
		skipOne    bool
	)
	flag.BoolVar(&verbose, "v", false, "Verbose-mode")
	flag.BoolVar(&skipOne, "s", false, "Delete e-mail on deverr")
	flag.BoolVar(&readonly, "r", false, "Don't email but flush to stdout")
	flag.StringVar(&configPath, "c", "./config.json", "Path to config.json")
	flag.Parse()

	if e := config.Init(configPath); e != nil {
		panic(e)
	}
	if verbose {
		fmt.Printf("%+v\n", config.C)
	}
	// TODO: Test config before starting?

	queue, e := connect()
	if e != nil {
		panic(e)
	}
	hostname, e = os.Hostname()
	if e != nil {
		panic(e)
	}

	if verbose {
		fmt.Println("SMTPw(" + hostname + ") email-tube (ignoring default)")
	}
	if readonly {
		fmt.Println("!! ReadOnly mode !!")
	}
	for {
		job, e := queue.Reserve(15*60) //15min timeout
		if e != nil {
			if e.Error() == errTimedOut.Error() {
				// Reserve timeout
				continue
			}

			fmt.Println("Beanstalkd err: " + e.Error())
			time.Sleep(time.Second * ERR_WAIT_SEC)
			if strings.HasSuffix(e.Error(), "broken pipe") {
				// Beanstalkd down, reconnect!
				q, e := connect()
				if e != nil {
					fmt.Println("Reconnect err: " + e.Error())
				}
				if q != nil {
					queue = q
				}
			}
			continue
		}
		if verbose {
			fmt.Println(fmt.Sprintf("Parse job %d", job.Id))
			fmt.Println("JSON:\r\n" + string(job.Data))
		}
		// Parse
		var m config.Email
		if e := json.Unmarshal(job.Data, &m); e != nil {
			// Broken JSON
			if skipOne {
				fmt.Println("WARN: Skip job as JSON is invalid")
				queue.Delete(job.Id)
				skipOne = false
				continue
			}

			// Ignore decode trouble
			fmt.Println("CRIT: Invalid JSON received (msg=" + e.Error() + ")")
			continue
		}

		if e := proc(m); e != nil {
			// TODO: Isolate deverr from senderr
			// Processing trouble?
			fmt.Println("WARN: Failed sending, retry in 20sec (msg=" + e.Error() + ")")
			time.Sleep(time.Second * 20)
			continue
		}
		queue.Delete(job.Id)
		if verbose {
			fmt.Println(fmt.Sprintf("Finished job %d", job.Id))
		}
	}
	queue.Quit()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gophergala2016/togepi/meta"
	"github.com/gophergala2016/togepi/redis"
	"github.com/gophergala2016/togepi/server"
	"github.com/gophergala2016/togepi/tcp"
	"github.com/gophergala2016/togepi/util"
)

var (
	serverMode        = flag.Bool("server", false, "run in server mode")
	httpServerAddress = flag.String("http-host", "http://127.0.0.1:8011", "togepi server's host")
	tcpServerAddress  = flag.String("tcp-host", "127.0.0.1:8012", "togepi server's host")
	socketPort        = flag.Int("socket-port", 8013, "a port to be used for local inter-process communication")
	httpPort          = flag.Int("http-port", 8011, "HTTP server's port")
	tcpPort           = flag.Int("tcp-port", 8012, "TCP server's port")
	redisHost         = flag.String("redis-host", "127.0.0.1:6379", "Redis host address")
	redisDB           = flag.Int("redis-db", 0, "Redis DB")
)

var (
	srv *server.Server
	r   *redis.Redis
	md  *meta.Data
	l   *tcp.Listener
	cl  *tcp.Client
)

func init() {
	flag.Parse()
}

func shutdown() {
	if srv != nil {
		srv.Stop()
	}

	if r != nil {
		r.Close()
	}

	if l != nil {
		l.Stop()
	}

	if cl != nil {
		cl.Close()
	}

	os.Exit(0)
}

func startServer() {
	log.Println("starting server")
	var redisErr error
	r, redisErr = redis.NewClient(*redisHost, *redisDB)
	util.CheckError(redisErr, shutdown)

	sExists, sErr := r.KeyExists("secret")
	util.CheckError(sErr, shutdown)

	if !sExists {
		log.Println("running server for the first time")
		setErr := r.GenerateGlobalSecret()
		util.CheckError(setErr, shutdown)
	}

	getErr := r.RetrieveGlobalSecret()
	util.CheckError(getErr, shutdown)

	srv = server.New("/register", "/validate", "/file", *httpPort, r)
	startErr := srv.Start()
	util.CheckError(startErr, shutdown)

	var lErr error
	l, lErr = tcp.NewListener(*tcpPort, nil)
	util.CheckError(lErr, shutdown)

	l.Start()
}

func startDaemon() {
	log.Println("starting daemon")

	configPath := os.Getenv("HOME") + "/.togepi/data"
	configStat, configStatErr := os.Stat(configPath)

	md.ConfPath = configPath

	switch {
	case os.IsNotExist(configStatErr):
		log.Println("first start, generating configuration")

		resp, respErr := http.Get(*httpServerAddress + "/register")
		util.CheckError(respErr, shutdown)
		body, bodyErr := ioutil.ReadAll(resp.Body)
		util.CheckError(bodyErr, shutdown)
		resp.Body.Close()

		var respStruct server.RegResp
		jsonRespErr := json.Unmarshal(body, &respStruct)
		util.CheckError(jsonRespErr, shutdown)

		md.SetUserData(respStruct.UserID, respStruct.UserKey)
		dataErr := md.CreateDataFile(configPath)
		util.CheckError(dataErr, shutdown)
	case configStat.IsDir():
		util.CheckError(errors.New(configPath+" is a directory"), shutdown)
	default:
		readDataErr := md.ReadDataFile(configPath)
		util.CheckError(readDataErr, shutdown)

		resp, respErr := http.Get(*httpServerAddress + "/validate?uid=" + md.UserID + "&ukey=" + md.UserKey)
		util.CheckError(respErr, shutdown)

		if resp.StatusCode != http.StatusOK {
			util.CheckError(errors.New("invalid user"), shutdown)
		}
	}

	var clErr error
	cl, clErr = tcp.NewClient(md.UserID, *tcpServerAddress)
	util.CheckError(clErr, shutdown)

	cl.HandleServerCommands()

	var lErr error
	l, lErr = tcp.NewListener(*socketPort, md)
	util.CheckError(lErr, shutdown)

	l.AcceptConnections(*httpServerAddress, md.UserID, md.UserKey)
}

func shareFile(filePath string) (err error) {
	err = tcp.SendAndClose(*socketPort, []byte("SHARE::"+filePath))
	return
}

func main() {
	if *serverMode {
		startServer()
	} else {
		if len(os.Args) > 1 {
			md = meta.NewData()

			if os.Args[1] == "start" {
				startDaemon()
			} else {
				filePath := os.Args[1]

				fileStat, fileStatErr := os.Stat(filePath)
				util.CheckError(fileStatErr, shutdown)

				if fileStat.IsDir() {
					util.CheckError(errors.New(filePath+" is a directory"), shutdown)
				}

				currentDir, currentDirErr := os.Getwd()
				util.CheckError(currentDirErr, shutdown)

				shareErr := shareFile(currentDir + "/" + filePath)
				util.CheckError(shareErr, shutdown)
				shutdown()
			}
		} else {
			util.CheckError(errors.New("please provide required arguments"), shutdown)
		}
	}

	// Shutting down on SIGINT.
	go func() {
		intChan := make(chan os.Signal)
		signal.Notify(intChan, os.Interrupt)

		<-intChan
		log.Println("Shutting down gracefully")
		go shutdown()

		fmt.Println("send SIGINT again to kill")
		<-intChan

		os.Exit(1)
	}()

	select {}
}
<commit_msg>outputing shared hash<commit_after>package main

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

	"github.com/gophergala2016/togepi/meta"
	"github.com/gophergala2016/togepi/redis"
	"github.com/gophergala2016/togepi/server"
	"github.com/gophergala2016/togepi/tcp"
	"github.com/gophergala2016/togepi/util"
)

var (
	serverMode        = flag.Bool("server", false, "run in server mode")
	httpServerAddress = flag.String("http-host", "http://127.0.0.1:8011", "togepi server's host")
	tcpServerAddress  = flag.String("tcp-host", "127.0.0.1:8012", "togepi server's host")
	socketPort        = flag.Int("socket-port", 8013, "a port to be used for local inter-process communication")
	httpPort          = flag.Int("http-port", 8011, "HTTP server's port")
	tcpPort           = flag.Int("tcp-port", 8012, "TCP server's port")
	redisHost         = flag.String("redis-host", "127.0.0.1:6379", "Redis host address")
	redisDB           = flag.Int("redis-db", 0, "Redis DB")
)

var (
	srv *server.Server
	r   *redis.Redis
	md  *meta.Data
	l   *tcp.Listener
	cl  *tcp.Client
)

func init() {
	flag.Parse()
}

func shutdown() {
	if srv != nil {
		srv.Stop()
	}

	if r != nil {
		r.Close()
	}

	if l != nil {
		l.Stop()
	}

	if cl != nil {
		cl.Close()
	}

	os.Exit(0)
}

func startServer() {
	log.Println("starting server")
	var redisErr error
	r, redisErr = redis.NewClient(*redisHost, *redisDB)
	util.CheckError(redisErr, shutdown)

	sExists, sErr := r.KeyExists("secret")
	util.CheckError(sErr, shutdown)

	if !sExists {
		log.Println("running server for the first time")
		setErr := r.GenerateGlobalSecret()
		util.CheckError(setErr, shutdown)
	}

	getErr := r.RetrieveGlobalSecret()
	util.CheckError(getErr, shutdown)

	srv = server.New("/register", "/validate", "/file", *httpPort, r)
	startErr := srv.Start()
	util.CheckError(startErr, shutdown)

	var lErr error
	l, lErr = tcp.NewListener(*tcpPort, nil)
	util.CheckError(lErr, shutdown)

	l.Start()
}

func startDaemon() {
	log.Println("starting daemon")

	configPath := os.Getenv("HOME") + "/.togepi/data"
	configStat, configStatErr := os.Stat(configPath)

	md.ConfPath = configPath

	switch {
	case os.IsNotExist(configStatErr):
		log.Println("first start, generating configuration")

		resp, respErr := http.Get(*httpServerAddress + "/register")
		util.CheckError(respErr, shutdown)
		body, bodyErr := ioutil.ReadAll(resp.Body)
		util.CheckError(bodyErr, shutdown)
		resp.Body.Close()

		var respStruct server.RegResp
		jsonRespErr := json.Unmarshal(body, &respStruct)
		util.CheckError(jsonRespErr, shutdown)

		md.SetUserData(respStruct.UserID, respStruct.UserKey)
		dataErr := md.CreateDataFile(configPath)
		util.CheckError(dataErr, shutdown)
	case configStat.IsDir():
		util.CheckError(errors.New(configPath+" is a directory"), shutdown)
	default:
		readDataErr := md.ReadDataFile(configPath)
		util.CheckError(readDataErr, shutdown)

		resp, respErr := http.Get(*httpServerAddress + "/validate?uid=" + md.UserID + "&ukey=" + md.UserKey)
		util.CheckError(respErr, shutdown)

		if resp.StatusCode != http.StatusOK {
			util.CheckError(errors.New("invalid user"), shutdown)
		}
	}

	var clErr error
	cl, clErr = tcp.NewClient(md.UserID, *tcpServerAddress)
	util.CheckError(clErr, shutdown)

	cl.HandleServerCommands()

	var lErr error
	l, lErr = tcp.NewListener(*socketPort, md)
	util.CheckError(lErr, shutdown)

	l.AcceptConnections(*httpServerAddress, md.UserID, md.UserKey)
}

func shareFile(filePath string) (err error) {
	configPath := os.Getenv("HOME") + "/.togepi/data"
	_, err = os.Stat(configPath)
	if err != nil {
		return
	}

	err = md.ReadDataFile(configPath)
	if err != nil {
		return
	}

	err = tcp.SendAndClose(*socketPort, []byte("SHARE::"+filePath))
	if err != nil {
		return
	}

	pathHash := util.Encrypt(filePath, md.UserKey)
	fmt.Println(md.UserID + pathHash)

	return
}

func main() {
	if *serverMode {
		startServer()
	} else {
		if len(os.Args) > 1 {
			md = meta.NewData()

			if os.Args[1] == "start" {
				startDaemon()
			} else {
				filePath := os.Args[1]

				fileStat, fileStatErr := os.Stat(filePath)
				util.CheckError(fileStatErr, shutdown)

				if fileStat.IsDir() {
					util.CheckError(errors.New(filePath+" is a directory"), shutdown)
				}

				currentDir, currentDirErr := os.Getwd()
				util.CheckError(currentDirErr, shutdown)

				shareErr := shareFile(currentDir + "/" + filePath)
				util.CheckError(shareErr, shutdown)
				shutdown()
			}
		} else {
			util.CheckError(errors.New("please provide required arguments"), shutdown)
		}
	}

	// Shutting down on SIGINT.
	go func() {
		intChan := make(chan os.Signal)
		signal.Notify(intChan, os.Interrupt)

		<-intChan
		log.Println("Shutting down gracefully")
		go shutdown()

		fmt.Println("send SIGINT again to kill")
		<-intChan

		os.Exit(1)
	}()

	select {}
}
<|endoftext|>


<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

// 也可以以服务的方式启动nging
// 服务支持的操作有：
// nging service install  	-- 安装服务
// nging service uninstall  -- 卸载服务
// nging service start 		-- 启动服务
// nging service stop 		-- 停止服务
// nging service restart 	-- 重启服务
package main

//go:generate go get github.com/admpub/bindata/...
//go:generate go-bindata -fs -o bindata_assetfs.go -ignore "\\.(git|svn|DS_Store|less|scss)$" -minify "\\.(js|css)$" -tags bindata public/assets/... template/... config/i18n/...

import (
	//register

	"github.com/webx-top/echo"

	"github.com/admpub/log"
	_ "github.com/admpub/nging/application"
	"github.com/admpub/nging/application/cmd"
	_ "github.com/admpub/nging/application/initialize/manager"
	_ "github.com/admpub/nging/application/library/sqlite"
)

var (
	BUILD_TIME string
	CLOUD_GOX  string
	COMMIT     string
	LABEL      = `dev` //beta/alpha/stable
	VERSION    = `2.2.1`

	version   string
	schemaVer = 3.1 //数据表结构版本
)

func main() {
	defer log.Sync()
	echo.Set(`BUILD_TIME`, BUILD_TIME)
	echo.Set(`COMMIT`, COMMIT)
	echo.Set(`LABEL`, LABEL)
	echo.Set(`VERSION`, VERSION)
	echo.Set(`SCHEMA_VER`, schemaVer)
	exec()
}

func exec() {
	cmd.Execute()
}
<commit_msg>improved<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

// 也可以以服务的方式启动nging
// 服务支持的操作有：
// nging service install  	-- 安装服务
// nging service uninstall  -- 卸载服务
// nging service start 		-- 启动服务
// nging service stop 		-- 停止服务
// nging service restart 	-- 重启服务
package main

//go:generate go get github.com/admpub/bindata/...
//go:generate go-bindata -fs -o bindata_assetfs.go -ignore "\\.(git|svn|DS_Store|less|scss)$" -minify "\\.(js|css)$" -tags bindata public/assets/... template/... config/i18n/...

import (
	//register

	"github.com/webx-top/echo"

	"github.com/admpub/log"
	_ "github.com/admpub/nging/application"
	"github.com/admpub/nging/application/cmd"
	_ "github.com/admpub/nging/application/initialize/manager"
	_ "github.com/admpub/nging/application/library/sqlite"
)

var (
	BUILD_TIME string
	CLOUD_GOX  string
	COMMIT     string
	LABEL      = `dev` //beta/alpha/stable
	VERSION    = `2.2.1`

	version   string
	schemaVer = 3.2 //数据表结构版本
)

func main() {
	defer log.Sync()
	echo.Set(`BUILD_TIME`, BUILD_TIME)
	echo.Set(`COMMIT`, COMMIT)
	echo.Set(`LABEL`, LABEL)
	echo.Set(`VERSION`, VERSION)
	echo.Set(`SCHEMA_VER`, schemaVer)
	exec()
}

func exec() {
	cmd.Execute()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"encoding/xml"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/gofly/saml"
)

const (
	cookieName = "qsaml"
)

func readSPConfig(spConfDir string) (map[string]*saml.Metadata, error) {
	metas := make(map[string]*saml.Metadata)
	err := filepath.Walk(spConfDir, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			f, err := os.Open(path)
			if err != nil {
				return err
			}
			defer f.Close()

			meta := &saml.Metadata{}
			err = xml.NewDecoder(f).Decode(meta)
			if err != nil {
				return err
			}
			metas[meta.EntityID] = meta
		}
		return nil
	})
	return metas, err
}

func login(sessProvider *LDAPSessProvider, username, password string) (*http.Cookie, error) {
	session, err := sessProvider.GetSessionByUsernameAndPassword(username, password)
	if err != nil {
		return nil, err
	}
	err = sessProvider.SetSession(session)
	if err != nil {
		err = fmt.Errorf("LDAPSessProvider.SetSession(%s) with error: %s", session.NameID, err)
		return nil, err
	}
	cookie := &http.Cookie{
		Name:     cookieName,
		Value:    session.ID,
		MaxAge:   int(session.ExpireTime.Sub(session.CreateTime)),
		HttpOnly: true,
		Path:     "/",
	}
	return cookie, nil
}

func handleSSO(assetsPrefix string, tmpl *template.Template,
	idp *saml.IdentityProvider, sessProvider *LDAPSessProvider) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var (
			sessionID string
			errMsg    string
		)
		cookie, err := r.Cookie(cookieName)
		if err == nil {
			if time.Now().After(cookie.Expires) {
				err = sessProvider.DestroySession(cookie.Value)
				if err != nil {
					log.Printf("LDAPSessProvider.DestroySession(%s) with error: %s\n", cookie.Value, err)
				}
			} else {
				sessionID = cookie.Value
			}
		}
		err = r.ParseForm()
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			errMsg = "请求参数不正确：无法解析请求"
		} else {
			username := strings.TrimSpace(r.PostFormValue("username"))
			password := strings.TrimSpace(r.PostFormValue("password"))
			if username != "" && password != "" {
				cookie, err = login(sessProvider, username, password)
				if err != nil {
					if err == ErrBindFailed {
						w.WriteHeader(http.StatusUnauthorized)
						errMsg = "用户名或密码错误"
					} else {
						w.WriteHeader(http.StatusInternalServerError)
						errMsg = "登录出错：" + err.Error()
						log.Printf("login with error: %s\n", err)
					}
				} else {
					http.SetCookie(w, cookie)
					sessionID = cookie.Value
				}
			}
		}

		req, err := saml.NewIdpAuthnRequest(idp, r)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			errMsg = "请求参数不正确：" + err.Error()
		} else {
			err = req.Validate()
			if err != nil {
				w.WriteHeader(http.StatusBadRequest)
				errMsg = "请求参数不正确：" + err.Error()
			}
		}

		if sessionID != "" {
			session, err := sessProvider.GetSessionBySessionID(sessionID)
			if err == nil {
				ssoResponse, err := req.GetSSOResponse(session)
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
					errMsg = "登录出错：" + err.Error()
					log.Printf("GetSSOResponse with error: %s\n", err)
				} else {
					err = tmpl.ExecuteTemplate(w, "redirect.html", map[string]interface{}{
						"AssetsPrefix": assetsPrefix,
						"URL":          ssoResponse.URL,
						"SAMLResponse": ssoResponse.SAMLResponse,
						"RelayState":   ssoResponse.RelayState,
					})
					if err != nil {
						log.Printf("tmpl.ExecuteTemplate(redirect.html) with error: %s\n", err)
						w.WriteHeader(http.StatusInternalServerError)
						errMsg = "登录出错：" + err.Error()
						log.Printf("ExecuteTemplate(redirect.html) with error: %s\n", err)
					} else {
						return
					}
				}
			} else {
				w.WriteHeader(http.StatusInternalServerError)
				errMsg = "登录出错：" + err.Error()
				log.Printf("sessProvider.GetSessionBySessionID(%s) with error: %s\n", sessionID, err)
			}
		}

		data := map[string]interface{}{
			"ErrMsg":       errMsg,
			"AssetsPrefix": assetsPrefix,
			"URL":          req.IDP.SSOURL,
			"SAMLRequest":  base64.StdEncoding.EncodeToString(req.RequestBuffer),
			"RelayState":   req.RelayState,
		}
		if err := tmpl.ExecuteTemplate(w, "login.html", data); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(err.Error()))
			return
		}
	}
}
func main() {
	var (
		spConfDir, keyFilePath, certFilePath           string
		httpPrefix, assetsPrefix, ldapAddr, ldapBindDN string
		sessionMaxAgeSeconds                           int
	)
	flag.StringVar(&spConfDir, "sp-dir", "sp", "service provider configs directory")
	flag.StringVar(&keyFilePath, "key-path", "key.pem", "private key path")
	flag.StringVar(&certFilePath, "cert-path", "cert.pem", "certificate path")
	flag.StringVar(&httpPrefix, "http-prefix", "http://localhost:8080", "http prefix")
	flag.StringVar(&assetsPrefix, "assets-prefix", "http://localhost:8080", "assets prefix")
	flag.StringVar(&ldapAddr, "ldap-addr", "localhost:389", "ldap server address")
	flag.StringVar(&ldapBindDN, "ldap-bind-dn", "ou=People,dc=qiniu,dc=com", "ldap bind dn")
	flag.IntVar(&sessionMaxAgeSeconds, "session-max-age", 3600, "session max age in seconds")
	flag.Parse()

	serviceProviders, err := readSPConfig(spConfDir)
	if err != nil {
		log.Fatalf("Read service provider config with error: %s\n", err)
	}

	key, err := ioutil.ReadFile(keyFilePath)
	if err != nil {
		log.Fatalf("Read key file from %s with error: %s\n", keyFilePath, err)
	}

	cert, err := ioutil.ReadFile(certFilePath)
	if err != nil {
		log.Fatalf("Read certificate file from %s with error: %s\n", certFilePath, err)
	}
	sessionMaxAge := time.Second * time.Duration(sessionMaxAgeSeconds)
	sessProvider := NewLDAPSessionProvider(ldapAddr, ldapBindDN, sessionMaxAge)
	idp := &saml.IdentityProvider{
		Key:              string(key),
		Certificate:      string(cert),
		MetadataURL:      fmt.Sprintf("%s/meta", httpPrefix),
		SSOURL:           fmt.Sprintf("%s/sso", httpPrefix),
		ServiceProviders: serviceProviders,
	}

	tmpl := template.Must(template.New("qsaml-templates").ParseGlob("templates/*.html"))
	http.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/samlmetadata+xml")
		encoder := xml.NewEncoder(w)
		encoder.Indent("", "  ")
		encoder.Encode(idp.Metadata())
	})
	http.HandleFunc("/sso", handleSSO(assetsPrefix, tmpl, idp, sessProvider))
	http.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
		cookie, err := r.Cookie(cookieName)
		if err == nil {
			err := sessProvider.DestroySession(cookie.Value)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				log.Printf("DestroySession(%s) with error: %s\n", cookie.Value, err)
				return
			}
		}
		redirect := r.URL.Query().Get("redirect")
		if _, ok := serviceProviders[redirect]; !ok {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte("错误的SP"))
			return
		}
		w.Header().Set("Location", redirect)
		w.WriteHeader(http.StatusFound)
	})
	http.Handle("/static/", http.FileServer(http.Dir(".")))
	http.ListenAndServe(":8080", nil)
}
<commit_msg>fix max age in cookie<commit_after>package main

import (
	"encoding/base64"
	"encoding/xml"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/gofly/saml"
)

const (
	cookieName = "qsaml"
)

func readSPConfig(spConfDir string) (map[string]*saml.Metadata, error) {
	metas := make(map[string]*saml.Metadata)
	err := filepath.Walk(spConfDir, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			f, err := os.Open(path)
			if err != nil {
				return err
			}
			defer f.Close()

			meta := &saml.Metadata{}
			err = xml.NewDecoder(f).Decode(meta)
			if err != nil {
				return err
			}
			metas[meta.EntityID] = meta
		}
		return nil
	})
	return metas, err
}

func login(sessProvider *LDAPSessProvider, username, password string) (*http.Cookie, error) {
	session, err := sessProvider.GetSessionByUsernameAndPassword(username, password)
	if err != nil {
		return nil, err
	}
	err = sessProvider.SetSession(session)
	if err != nil {
		err = fmt.Errorf("LDAPSessProvider.SetSession(%s) with error: %s", session.NameID, err)
		return nil, err
	}
	cookie := &http.Cookie{
		Name:     cookieName,
		Value:    session.ID,
		MaxAge:   int(session.ExpireTime.Sub(session.CreateTime).Seconds()),
		HttpOnly: true,
		Path:     "/",
	}
	return cookie, nil
}

func handleSSO(assetsPrefix string, tmpl *template.Template,
	idp *saml.IdentityProvider, sessProvider *LDAPSessProvider) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var (
			sessionID string
			errMsg    string
		)
		cookie, err := r.Cookie(cookieName)
		if err == nil {
			if time.Now().After(cookie.Expires) {
				err = sessProvider.DestroySession(cookie.Value)
				if err != nil {
					log.Printf("LDAPSessProvider.DestroySession(%s) with error: %s\n", cookie.Value, err)
				}
			} else {
				sessionID = cookie.Value
			}
		}
		err = r.ParseForm()
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			errMsg = "请求参数不正确：无法解析请求"
		} else {
			username := strings.TrimSpace(r.PostFormValue("username"))
			password := strings.TrimSpace(r.PostFormValue("password"))
			if username != "" && password != "" {
				cookie, err = login(sessProvider, username, password)
				if err != nil {
					if err == ErrBindFailed {
						w.WriteHeader(http.StatusUnauthorized)
						errMsg = "用户名或密码错误"
					} else {
						w.WriteHeader(http.StatusInternalServerError)
						errMsg = "登录出错：" + err.Error()
						log.Printf("login with error: %s\n", err)
					}
				} else {
					http.SetCookie(w, cookie)
					sessionID = cookie.Value
				}
			}
		}

		req, err := saml.NewIdpAuthnRequest(idp, r)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			errMsg = "请求参数不正确：" + err.Error()
		} else {
			err = req.Validate()
			if err != nil {
				w.WriteHeader(http.StatusBadRequest)
				errMsg = "请求参数不正确：" + err.Error()
			}
		}

		if sessionID != "" {
			session, err := sessProvider.GetSessionBySessionID(sessionID)
			if err == nil {
				ssoResponse, err := req.GetSSOResponse(session)
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
					errMsg = "登录出错：" + err.Error()
					log.Printf("GetSSOResponse with error: %s\n", err)
				} else {
					err = tmpl.ExecuteTemplate(w, "redirect.html", map[string]interface{}{
						"AssetsPrefix": assetsPrefix,
						"URL":          ssoResponse.URL,
						"SAMLResponse": ssoResponse.SAMLResponse,
						"RelayState":   ssoResponse.RelayState,
					})
					if err != nil {
						log.Printf("tmpl.ExecuteTemplate(redirect.html) with error: %s\n", err)
						w.WriteHeader(http.StatusInternalServerError)
						errMsg = "登录出错：" + err.Error()
						log.Printf("ExecuteTemplate(redirect.html) with error: %s\n", err)
					} else {
						return
					}
				}
			} else {
				w.WriteHeader(http.StatusInternalServerError)
				errMsg = "登录出错：" + err.Error()
				log.Printf("sessProvider.GetSessionBySessionID(%s) with error: %s\n", sessionID, err)
			}
		}

		data := map[string]interface{}{
			"ErrMsg":       errMsg,
			"AssetsPrefix": assetsPrefix,
			"URL":          req.IDP.SSOURL,
			"SAMLRequest":  base64.StdEncoding.EncodeToString(req.RequestBuffer),
			"RelayState":   req.RelayState,
		}
		if err := tmpl.ExecuteTemplate(w, "login.html", data); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte(err.Error()))
			return
		}
	}
}
func main() {
	var (
		spConfDir, keyFilePath, certFilePath           string
		httpPrefix, assetsPrefix, ldapAddr, ldapBindDN string
		sessionMaxAgeSeconds                           int
	)
	flag.StringVar(&spConfDir, "sp-dir", "sp", "service provider configs directory")
	flag.StringVar(&keyFilePath, "key-path", "key.pem", "private key path")
	flag.StringVar(&certFilePath, "cert-path", "cert.pem", "certificate path")
	flag.StringVar(&httpPrefix, "http-prefix", "http://localhost:8080", "http prefix")
	flag.StringVar(&assetsPrefix, "assets-prefix", "http://localhost:8080", "assets prefix")
	flag.StringVar(&ldapAddr, "ldap-addr", "localhost:389", "ldap server address")
	flag.StringVar(&ldapBindDN, "ldap-bind-dn", "ou=People,dc=qiniu,dc=com", "ldap bind dn")
	flag.IntVar(&sessionMaxAgeSeconds, "session-max-age", 3600, "session max age in seconds")
	flag.Parse()

	serviceProviders, err := readSPConfig(spConfDir)
	if err != nil {
		log.Fatalf("Read service provider config with error: %s\n", err)
	}

	key, err := ioutil.ReadFile(keyFilePath)
	if err != nil {
		log.Fatalf("Read key file from %s with error: %s\n", keyFilePath, err)
	}

	cert, err := ioutil.ReadFile(certFilePath)
	if err != nil {
		log.Fatalf("Read certificate file from %s with error: %s\n", certFilePath, err)
	}
	sessionMaxAge := time.Second * time.Duration(sessionMaxAgeSeconds)
	sessProvider := NewLDAPSessionProvider(ldapAddr, ldapBindDN, sessionMaxAge)
	idp := &saml.IdentityProvider{
		Key:              string(key),
		Certificate:      string(cert),
		MetadataURL:      fmt.Sprintf("%s/meta", httpPrefix),
		SSOURL:           fmt.Sprintf("%s/sso", httpPrefix),
		ServiceProviders: serviceProviders,
	}

	tmpl := template.Must(template.New("qsaml-templates").ParseGlob("templates/*.html"))
	http.HandleFunc("/meta", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/samlmetadata+xml")
		encoder := xml.NewEncoder(w)
		encoder.Indent("", "  ")
		encoder.Encode(idp.Metadata())
	})
	http.HandleFunc("/sso", handleSSO(assetsPrefix, tmpl, idp, sessProvider))
	http.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
		cookie, err := r.Cookie(cookieName)
		if err == nil {
			err := sessProvider.DestroySession(cookie.Value)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				log.Printf("DestroySession(%s) with error: %s\n", cookie.Value, err)
				return
			}
		}
		redirect := r.URL.Query().Get("redirect")
		if _, ok := serviceProviders[redirect]; !ok {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte("错误的SP"))
			return
		}
		w.Header().Set("Location", redirect)
		w.WriteHeader(http.StatusFound)
	})
	http.Handle("/static/", http.FileServer(http.Dir(".")))
	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"os"

	"github.com/gorilla/mux"
)

const (
	usage = `
Usage: curl http://127.0.0.1:8080/[endpoint]

    Perform HTTP request against the API for a specific action.

Endpoints:

    /            show this message
    /health      check health status
    /hostname    display hostname
`
)

type Payload struct {
	Message string `json:"message"`
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
	io.Copy(w, r.Body)
}

func endpointHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", usage)
	log.Printf("%s", r.URL.Path)
}

func headersHandler(w http.ResponseWriter, r *http.Request) {
	for k, v := range r.Header {
		fmt.Fprintf(w, "%s=%s\n", k, v)
	}
}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
}

func hostnameHandler(w http.ResponseWriter, r *http.Request) {
	hostname, _ := os.Hostname()
	fmt.Fprintf(w, "Hostname: %s\n", hostname)
	log.Printf("%s", r.URL.Path)
}

func logHandler(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()

	var msg Payload
	err := decoder.Decode(&msg)
	if err != nil {
		http.Error(w, "error: reading request body", http.StatusInternalServerError)
	}

	fmt.Fprint(w, msg.Message)
	fmt.Println(msg.Message)
}

func traceHandler(w http.ResponseWriter, req *http.Request) {
	requestDump, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Fprint(w, err.Error())
	} else {
		fmt.Fprint(w, string(requestDump))
	}
}

func main() {

	router := mux.NewRouter()

	router.HandleFunc("/", endpointHandler).Methods("GET")
	router.HandleFunc("/echo", echoHandler).Methods("GET", "POST")
	router.HandleFunc("/headers", headersHandler).Methods("GET")
	router.HandleFunc("/health", healthCheckHandler).Methods("GET")
	router.HandleFunc("/hostname", hostnameHandler).Methods("GET")
	router.HandleFunc("/log", logHandler).Methods("POST")
	router.HandleFunc("/trace", traceHandler).Methods("GET", "POST")

	log.Fatal(http.ListenAndServe(":8080", router))

}
<commit_msg>update root endpoint<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"os"

	"github.com/gorilla/mux"
)

const (
	usage = `
Usage: curl http://127.0.0.1:8080/[endpoint]

    Perform HTTP request against the API for a specific action.

Endpoints:

    /           show this message
    /echo       return the payload sent
    /headers    display all headers
    /hostname   display hostname
    /log        log the message
    /trace      dump the request
    /health     check health status
`
)

type Payload struct {
	Message string `json:"message"`
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
	io.Copy(w, r.Body)
}

func endpointHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", usage)
	log.Printf("%s", r.URL.Path)
}

func headersHandler(w http.ResponseWriter, r *http.Request) {
	for k, v := range r.Header {
		fmt.Fprintf(w, "%s=%s\n", k, v)
	}
}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
}

func hostnameHandler(w http.ResponseWriter, r *http.Request) {
	hostname, _ := os.Hostname()
	fmt.Fprintf(w, "Hostname: %s\n", hostname)
	log.Printf("%s", r.URL.Path)
}

func logHandler(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()

	var msg Payload
	err := decoder.Decode(&msg)
	if err != nil {
		http.Error(w, "error: reading request body", http.StatusInternalServerError)
	}

	fmt.Fprint(w, msg.Message)
	fmt.Println(msg.Message)
}

func traceHandler(w http.ResponseWriter, req *http.Request) {
	requestDump, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Fprint(w, err.Error())
	} else {
		fmt.Fprint(w, string(requestDump))
	}
}

func main() {

	router := mux.NewRouter()

	router.HandleFunc("/", endpointHandler).Methods("GET")
	router.HandleFunc("/echo", echoHandler).Methods("GET", "POST")
	router.HandleFunc("/headers", headersHandler).Methods("GET")
	router.HandleFunc("/health", healthCheckHandler).Methods("GET")
	router.HandleFunc("/hostname", hostnameHandler).Methods("GET")
	router.HandleFunc("/log", logHandler).Methods("POST")
	router.HandleFunc("/trace", traceHandler).Methods("GET", "POST")

	log.Fatal(http.ListenAndServe(":8080", router))

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"runtime"

	"github.com/client9/misspell/lib"
)

func worker(writeit bool, debug bool, files <-chan string, results chan<- int) {
	fails := 0
	for filename := range files {
		//log.Printf("Scanning %q", filename)
		raw, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Printf("Unable to read %q: %s", filename, err)
			continue
		}
		orig := string(raw)
		updated := lib.Replace(orig, debug)

		count := lib.DiffLines(filename, orig, updated, os.Stdout)
		if count == 0 {
			continue
		}
		fails += count
		//log.Printf("Updating %q", filename)
		if writeit {
			ioutil.WriteFile(filename, []byte(updated), 0)
		}
	}
	results <- fails
}

func main() {
	workers := flag.Int("j", 0, "Number of workers, 0 = number of CPUs")
	writeit := flag.Bool("w", false, "Write correction to file (default is just to display)")
	debug := flag.Bool("debug", false, "Debug matching, very slow")
	flag.Parse()

	if *workers < 0 {
		log.Fatalf("-j must >= 0")
	}
	if *workers == 0 {
		*workers = runtime.NumCPU()
	}

	if *debug {
		*workers = 1
	}
	args := flag.Args()

	/*
		if len(args) == 0 {
			rawin, err := ioutil.ReadAll(os.Stdin)
			if err != nil {
				panic(err)
			}
			replacer.WriteString(os.Stdout, string(rawin))
			return
		}
	*/
	c := make(chan string, len(args))
	results := make(chan int, *workers)

	for i := 0; i < *workers; i++ {
		go worker(*writeit, *debug, c, results)
	}

	for _, filename := range args {
		c <- filename
	}
	close(c)

	count := 0
	for i := 0; i < *workers; i++ {
		changed := <-results
		count += changed
	}
	if count != 0 {
		// log.Printf("Got %d", count)
		// error
		os.Exit(1)
	}
}
<commit_msg>better doco<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"runtime"

	"github.com/client9/misspell/lib"
)

func worker(writeit bool, debug bool, files <-chan string, results chan<- int) {
	fails := 0
	for filename := range files {
		//log.Printf("Scanning %q", filename)
		raw, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Printf("Unable to read %q: %s", filename, err)
			continue
		}
		orig := string(raw)
		updated := lib.Replace(orig, debug)

		count := lib.DiffLines(filename, orig, updated, os.Stdout)
		if count == 0 {
			continue
		}
		fails += count
		//log.Printf("Updating %q", filename)
		if writeit {
			ioutil.WriteFile(filename, []byte(updated), 0)
		}
	}
	results <- fails
}

func main() {
	workers := flag.Int("j", 0, "Number of workers, 0 = number of CPUs")
	writeit := flag.Bool("w", false, "Overwrite file with corrections (default is just to display)")
	debug := flag.Bool("debug", false, "Debug matching, very slow")
	flag.Parse()

	if *workers < 0 {
		log.Fatalf("-j must >= 0")
	}
	if *workers == 0 {
		*workers = runtime.NumCPU()
	}

	if *debug {
		*workers = 1
	}
	args := flag.Args()

	/*
		if len(args) == 0 {
			rawin, err := ioutil.ReadAll(os.Stdin)
			if err != nil {
				panic(err)
			}
			replacer.WriteString(os.Stdout, string(rawin))
			return
		}
	*/
	c := make(chan string, len(args))
	results := make(chan int, *workers)

	for i := 0; i < *workers; i++ {
		go worker(*writeit, *debug, c, results)
	}

	for _, filename := range args {
		c <- filename
	}
	close(c)

	count := 0
	for i := 0; i < *workers; i++ {
		changed := <-results
		count += changed
	}
	if count != 0 {
		// log.Printf("Got %d", count)
		// error
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"os"
	"path/filepath"
	"time"

	"gopkg.in/alexzorin/libvirt-go.v2"
	"gopkg.in/yaml.v2"
)

func init() {
	flag.Parse()
}

var l *syslog.Writer
var viruri string
var master_iface string = "vlan1001"
var virconn libvirt.VirConnection
var first bool = true

func getVirConn() libvirt.VirConnection {
	if !first {
		if ok, err := virconn.IsAlive(); !ok || err != nil {
			for {
				vc, err := libvirt.NewVirConnection(viruri)
				if err == nil {
					virconn = vc
					return virconn
				}
				l.Info("failed to connect to libvirt:" + err.Error())
				time.Sleep(5 * time.Second)
			}
		}
	} else {
		for {
			vc, err := libvirt.NewVirConnection(viruri)
			if err == nil {
				first = false
				virconn = vc
				return virconn
			}
			l.Info("failed to connect to libvirt:" + err.Error())
			time.Sleep(5 * time.Second)
		}
	}
	return virconn
}

func main() {
	var vc libvirt.VirConnection
	var err error
	var buf []byte
	var data map[string]string
	l, err = syslog.Dial("", "", syslog.LOG_DAEMON|syslog.LOG_INFO, filepath.Base(os.Args[0]))
	if err != nil {
		log.Fatalf("Failed to connect to syslog: %s\n", err.Error())
		os.Exit(1)
	}
	defer l.Close()

	if buf, err = ioutil.ReadFile("/etc/svirtnet.yml"); err == nil {
		if err = yaml.Unmarshal(buf, &data); err == nil {
			master_iface = data["interface"]
		}
	}

	_, err = os.Stat("/sys/module/xenfs")
	if err == nil {
		viruri = "xen:///"
	} else {
		viruri = "qemu:///system"
	}

	l.Info("ListenAndServeTCPv4")
	go ListenAndServeTCPv4()

	callbackId := -1
	defer func() {
		vc := getVirConn()
		if callbackId >= 0 {
			vc.DomainEventDeregister(callbackId)
		}
		//	vc.CloseConnection()
		vc.UnrefAndCloseConnection()
	}()

	callback := libvirt.DomainEventCallback(
		func(c *libvirt.VirConnection, d *libvirt.VirDomain, eventDetails interface{}, f func()) int {
			if d == nil {
				return -1
			}

			if lifecycleEvent, ok := eventDetails.(libvirt.DomainLifecycleEvent); ok {
				domName, err := d.GetName()
				if err != nil {
					l.Info("failed to get domain name")
					return -1
				}
				switch lifecycleEvent.Event {
				case libvirt.VIR_DOMAIN_EVENT_STARTED:
					srvmutex.Lock()
					if _, ok := servers[domName]; !ok {
						servers[domName] = &Server{name: domName}
						go servers[domName].Start()
						l.Info(domName + " start serving")
						//					} else {
						//						if s.shutdown {
						//							time.Sleep(2 * time.Second)
						//							goto Loop
						//						}
					}
					srvmutex.Unlock()
				case libvirt.VIR_DOMAIN_EVENT_STOPPED, libvirt.VIR_DOMAIN_EVENT_SHUTDOWN, libvirt.VIR_DOMAIN_EVENT_CRASHED:
					srvmutex.Lock()
					if s, ok := servers[domName]; ok {
						s.Stop()
						l.Info(domName + " stop serving")
						delete(servers, domName)
					}
					srvmutex.Unlock()
				default:
					fmt.Printf("%#+v\n", eventDetails)
				}
			}
			f()
			return 0
		},
	)

	libvirt.EventRegisterDefaultImpl()

	vc = getVirConn()
	//	defer vc.UnrefAndCloseConnection()

	callbackId = vc.DomainEventRegister(
		libvirt.VirDomain{},
		libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
		&callback,
		func() {
			fmt.Printf("catch")
		},
	)
	if callbackId < 0 {
		log.Fatalf("libvirt event registration failed")
		os.Exit(1)
	}

	if virdomains, err := vc.ListAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE | libvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE); err == nil {
		for _, d := range virdomains {
			domName, err := d.GetName()
			if err != nil {
				continue
			}
			srvmutex.Lock()
			if _, ok := servers[domName]; !ok {
				servers[domName] = &Server{name: domName}
				l.Info(domName + " start serving")
				go servers[domName].Start()
			}
			srvmutex.Unlock()
		}
	}

	for {
		libvirt.EventRunDefaultImpl()
	}

	// Deregister the event
	if ret := vc.DomainEventDeregister(callbackId); ret < 0 {
		l.Info("Event deregistration failed")
	}
	callbackId = -1 // Don't deregister twice

}
<commit_msg>replace catch<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"log/syslog"
	"os"
	"path/filepath"
	"time"

	"gopkg.in/alexzorin/libvirt-go.v2"
	"gopkg.in/yaml.v2"
)

func init() {
	flag.Parse()
}

var l *syslog.Writer
var viruri string
var master_iface string = "vlan1001"
var virconn libvirt.VirConnection
var first bool = true

func getVirConn() libvirt.VirConnection {
	if !first {
		if ok, err := virconn.IsAlive(); !ok || err != nil {
			for {
				vc, err := libvirt.NewVirConnection(viruri)
				if err == nil {
					virconn = vc
					return virconn
				}
				l.Info("failed to connect to libvirt:" + err.Error())
				time.Sleep(5 * time.Second)
			}
		}
	} else {
		for {
			vc, err := libvirt.NewVirConnection(viruri)
			if err == nil {
				first = false
				virconn = vc
				return virconn
			}
			l.Info("failed to connect to libvirt:" + err.Error())
			time.Sleep(5 * time.Second)
		}
	}
	return virconn
}

func main() {
	var vc libvirt.VirConnection
	var err error
	var buf []byte
	var data map[string]string
	l, err = syslog.Dial("", "", syslog.LOG_DAEMON|syslog.LOG_INFO, filepath.Base(os.Args[0]))
	if err != nil {
		log.Fatalf("Failed to connect to syslog: %s\n", err.Error())
		os.Exit(1)
	}
	defer l.Close()

	if buf, err = ioutil.ReadFile("/etc/svirtnet.yml"); err == nil {
		if err = yaml.Unmarshal(buf, &data); err == nil {
			master_iface = data["interface"]
		}
	}

	_, err = os.Stat("/sys/module/xenfs")
	if err == nil {
		viruri = "xen:///"
	} else {
		viruri = "qemu:///system"
	}

	l.Info("ListenAndServeTCPv4")
	go ListenAndServeTCPv4()

	callbackId := -1
	defer func() {
		vc := getVirConn()
		if callbackId >= 0 {
			vc.DomainEventDeregister(callbackId)
		}
		//	vc.CloseConnection()
		vc.UnrefAndCloseConnection()
	}()

	callback := libvirt.DomainEventCallback(
		func(c *libvirt.VirConnection, d *libvirt.VirDomain, eventDetails interface{}, f func()) int {
			if d == nil {
				return -1
			}

			if lifecycleEvent, ok := eventDetails.(libvirt.DomainLifecycleEvent); ok {
				domName, err := d.GetName()
				if err != nil {
					l.Info("failed to get domain name")
					return -1
				}
				switch lifecycleEvent.Event {
				case libvirt.VIR_DOMAIN_EVENT_STARTED:
					srvmutex.Lock()
					if _, ok := servers[domName]; !ok {
						servers[domName] = &Server{name: domName}
						go servers[domName].Start()
						l.Info(domName + " start serving")
						//					} else {
						//						if s.shutdown {
						//							time.Sleep(2 * time.Second)
						//							goto Loop
						//						}
					}
					srvmutex.Unlock()
				case libvirt.VIR_DOMAIN_EVENT_STOPPED, libvirt.VIR_DOMAIN_EVENT_SHUTDOWN, libvirt.VIR_DOMAIN_EVENT_CRASHED:
					srvmutex.Lock()
					if s, ok := servers[domName]; ok {
						s.Stop()
						l.Info(domName + " stop serving")
						delete(servers, domName)
					}
					srvmutex.Unlock()
				default:
					fmt.Printf("%#+v\n", eventDetails)
				}
			}
			f()
			return 0
		},
	)

	libvirt.EventRegisterDefaultImpl()

	vc = getVirConn()
	//	defer vc.UnrefAndCloseConnection()

	callbackId = vc.DomainEventRegister(
		libvirt.VirDomain{},
		libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
		&callback,
		func() {
			fmt.Sprintf("catch")
		},
	)
	if callbackId < 0 {
		log.Fatalf("libvirt event registration failed")
		os.Exit(1)
	}

	if virdomains, err := vc.ListAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE | libvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE); err == nil {
		for _, d := range virdomains {
			domName, err := d.GetName()
			if err != nil {
				continue
			}
			srvmutex.Lock()
			if _, ok := servers[domName]; !ok {
				servers[domName] = &Server{name: domName}
				l.Info(domName + " start serving")
				go servers[domName].Start()
			}
			srvmutex.Unlock()
		}
	}

	for {
		libvirt.EventRunDefaultImpl()
	}

	// Deregister the event
	if ret := vc.DomainEventDeregister(callbackId); ret < 0 {
		l.Info("Event deregistration failed")
	}
	callbackId = -1 // Don't deregister twice

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/FarmRadioHangar/fessboxconfig/device"
	"github.com/FarmRadioHangar/fessboxconfig/parser"
	"github.com/gernest/hot"
	"github.com/gorilla/mux"
)

//Config holds configuration values for this application.
type Config struct {
	Port           int64  `json:"port"`
	Host           string `json:"host"`
	StaticDir      string `json:"static_dir"`
	TemplatesDir   string `json:"templates_dir"`
	AsteriskConfig string `json:"asterisk_config_dir"`
	Autodetect     bool   `json:"autodetect"`
}

func defaultConfig() *Config {
	return &Config{
		Port:           8080,
		Host:           "",
		StaticDir:      "static",
		TemplatesDir:   "templates",
		AsteriskConfig: "/etc/asterisk",
		Autodetect:     true,
	}
}

func main() {
	c := flag.String("c", "conf/config.json", "path to the configuration file")
	dev := flag.Bool("dev", false, "set true if running in dev mode")
	flag.Parse()
	b, err := ioutil.ReadFile(*c)
	if err != nil {
		log.Fatal(err)
	}
	cfg := &Config{}
	err = json.Unmarshal(b, cfg)
	if err != nil {
		log.Fatal(err)
	}
	var manager *device.Manager
	if cfg.Autodetect {
		manager = device.New()
		manager.Init()
	}
	if *dev {
		cfg.AsteriskConfig = "sample"
		tmp, err := ioutil.TempDir("", "fconf")
		if err != nil {
			log.Fatal(err)
		}
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
		go func(dir string) {
		END:
			for {
				select {
				case <-c:
					log.Println("removing ", dir)
					_ = os.RemoveAll(dir)
					if cfg.Autodetect {
						manager.Close()
					}
					break END
				}
			}
		}(tmp)
		cfg.AsteriskConfig = tmp
		err = copyFiles(tmp, "sample")
		if err != nil {
			log.Fatal(err)
		}
	}
	s := newServer(cfg)
	s.HandleFunc("/serial/list", manager.List).Methods("GET")
	log.Printf(" starting server on  localhost:%d\n", cfg.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Port), s))
}

//copyFiles copies files from src to dst, directories are ignored
func copyFiles(dst, src string) error {
	files, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		fname := filepath.Join(src, file.Name())
		f, err := ioutil.ReadFile(fname)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(filepath.Join(dst, file.Name()), f, 0600)
		if err != nil {
			return err
		}
	}
	return nil
}

//newServer returns a http.Handler with all the routes for configuring supported
//devices registered.
func newServer(c *Config) *mux.Router {
	s := mux.NewRouter()
	w := newWeb(c)
	s.HandleFunc("/config/{filename}", w.Dongle).Methods("GET")
	s.HandleFunc("/config/{filename}", w.UpdateDongle).Methods("POST")
	//s.PathPrefix("/static/").
	//Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(c.StaticDir))))
	s.HandleFunc("/", w.Home)
	return s
}

// web is the application struct, it defines all the handlers for this
// application as its methods.
//
// It is safe to use this in multiple goroutines
//
// This contains a a loaded hot template, so when run in development mode the
// templates will automatially be reloaded without the need to re run the
// application process. The auto reloading of templates is disabled in
// production.
type web struct {
	cfg *Config
	tpl *hot.Template
}

//newWeb intialises and returns a new instance of *web, the templates are loaded
//and if dev mode is set to true then auto reload is enabled.
func newWeb(cfg *Config) *web {
	w := &web{cfg: cfg}
	config := &hot.Config{
		Watch:          true,
		BaseName:       "fconf",
		Dir:            cfg.TemplatesDir,
		LeftDelim:      "{%",
		RightDelim:     "%}",
		FilesExtension: []string{".tpl", ".html", ".tmpl"},
	}

	tpl, err := hot.New(config)
	if err != nil {
		panic(err)
	}
	w.tpl = tpl
	return w
}

//Home serves the home page
func (ww *web) Home(w http.ResponseWriter, r *http.Request) {
	data := make(map[string]interface{})
	data["Config"] = ww.cfg
	err := ww.tpl.Execute(w, "index.html", data)
	if err != nil {
		log.Println(err)
	}
}

type errMSG struct {
	Message string `json:"error"`
}

// Dongle implements http.HandleFunc for serving the dongle configuration values
// as a json object
//
// This only returns the current values of the dongle configuration file, so it
// is good for GET requests only.
func (ww *web) Dongle(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	file := vars["filename"] + ".conf"
	fName := filepath.Join(ww.cfg.AsteriskConfig, file)
	enc := json.NewEncoder(w)
	w.Header().Set("Content-Type", "application/json")

	f, err := os.Open(fName)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	defer func() { _ = f.Close() }()
	p, err := parser.NewParser(f)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble scanning dongle configuration"})
		return
	}
	ast, err := p.Parse()
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble parsing dongle configuration"})
		return
	}
	err = ast.ToJSON(w)
	if err != nil {
		log.Println(err)
	}
}

//UpdateDongle updates the dongle documentation file, via a json object. This
//doesnot do verification of the object sent with the request.
//
// The received json is loaded into ast and writen to the dongle configuration
// file directly.
//
// TODO(gernest) do some kind of verification?
func (ww *web) UpdateDongle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	ast := &parser.Ast{}
	src := &bytes.Buffer{}
	enc := json.NewEncoder(w)
	_, err := io.Copy(src, r.Body)
	if err != nil {
		_ = enc.Encode(&errMSG{Message: "trouble reading request body"})
		return
	}
	err = ast.LoadJSON(src.Bytes())
	if err != nil {
		_ = enc.Encode(&errMSG{Message: "trouble loading request body"})
		return
	}
	vars := mux.Vars(r)
	file := vars["filename"] + ".conf"
	fName := filepath.Join(ww.cfg.AsteriskConfig, file)
	info, err := os.Stat(fName)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	dst := &bytes.Buffer{}
	parser.PrintAst(dst, ast)
	_ = ioutil.WriteFile(fName, dst.Bytes(), info.Mode())
	_, _ = io.Copy(w, src)
}
<commit_msg>Don't serve index.html<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/FarmRadioHangar/fessboxconfig/device"
	"github.com/FarmRadioHangar/fessboxconfig/parser"
	"github.com/gernest/hot"
	"github.com/gorilla/mux"
)

//Config holds configuration values for this application.
type Config struct {
	Port           int64  `json:"port"`
	Host           string `json:"host"`
	StaticDir      string `json:"static_dir"`
	TemplatesDir   string `json:"templates_dir"`
	AsteriskConfig string `json:"asterisk_config_dir"`
	Autodetect     bool   `json:"autodetect"`
}

func defaultConfig() *Config {
	return &Config{
		Port:           8080,
		Host:           "",
		StaticDir:      "static",
		TemplatesDir:   "templates",
		AsteriskConfig: "/etc/asterisk",
		Autodetect:     true,
	}
}

func main() {
	c := flag.String("c", "conf/config.json", "path to the configuration file")
	dev := flag.Bool("dev", false, "set true if running in dev mode")
	flag.Parse()
	b, err := ioutil.ReadFile(*c)
	if err != nil {
		log.Fatal(err)
	}
	cfg := &Config{}
	err = json.Unmarshal(b, cfg)
	if err != nil {
		log.Fatal(err)
	}
	var manager *device.Manager
	if cfg.Autodetect {
		manager = device.New()
		manager.Init()
	}
	if *dev {
		cfg.AsteriskConfig = "sample"
		tmp, err := ioutil.TempDir("", "fconf")
		if err != nil {
			log.Fatal(err)
		}
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
		go func(dir string) {
		END:
			for {
				select {
				case <-c:
					log.Println("removing ", dir)
					_ = os.RemoveAll(dir)
					if cfg.Autodetect {
						manager.Close()
					}
					break END
				}
			}
		}(tmp)
		cfg.AsteriskConfig = tmp
		err = copyFiles(tmp, "sample")
		if err != nil {
			log.Fatal(err)
		}
	}
	s := newServer(cfg)
	s.HandleFunc("/serial/list", manager.List).Methods("GET")
	log.Printf(" starting server on  localhost:%d\n", cfg.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Port), s))
}

//copyFiles copies files from src to dst, directories are ignored
func copyFiles(dst, src string) error {
	files, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		fname := filepath.Join(src, file.Name())
		f, err := ioutil.ReadFile(fname)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(filepath.Join(dst, file.Name()), f, 0600)
		if err != nil {
			return err
		}
	}
	return nil
}

//newServer returns a http.Handler with all the routes for configuring supported
//devices registered.
func newServer(c *Config) *mux.Router {
	s := mux.NewRouter()
	w := newWeb(c)
	s.HandleFunc("/config/{filename}", w.Dongle).Methods("GET")
	s.HandleFunc("/config/{filename}", w.UpdateDongle).Methods("POST")
	//s.PathPrefix("/static/").
	//Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(c.StaticDir))))
	s.HandleFunc("/", w.Home)
	return s
}

// web is the application struct, it defines all the handlers for this
// application as its methods.
//
// It is safe to use this in multiple goroutines
//
// This contains a a loaded hot template, so when run in development mode the
// templates will automatially be reloaded without the need to re run the
// application process. The auto reloading of templates is disabled in
// production.
type web struct {
	cfg *Config
	tpl *hot.Template
}

//newWeb intialises and returns a new instance of *web, the templates are loaded
//and if dev mode is set to true then auto reload is enabled.
func newWeb(cfg *Config) *web {
	w := &web{cfg: cfg}
	config := &hot.Config{
		Watch:          true,
		BaseName:       "fconf",
		Dir:            cfg.TemplatesDir,
		LeftDelim:      "{%",
		RightDelim:     "%}",
		FilesExtension: []string{".tpl", ".html", ".tmpl"},
	}

	tpl, err := hot.New(config)
	if err != nil {
		panic(err)
	}
	w.tpl = tpl
	return w
}

//Home serves the home page
func (ww *web) Home(w http.ResponseWriter, r *http.Request) {
	//data := make(map[string]interface{})
	//data["Config"] = ww.cfg
	//err := ww.tpl.Execute(w, "index.html", data)
	//if err != nil {
	//log.Println(err)
	//}
}

type errMSG struct {
	Message string `json:"error"`
}

// Dongle implements http.HandleFunc for serving the dongle configuration values
// as a json object
//
// This only returns the current values of the dongle configuration file, so it
// is good for GET requests only.
func (ww *web) Dongle(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	file := vars["filename"] + ".conf"
	fName := filepath.Join(ww.cfg.AsteriskConfig, file)
	enc := json.NewEncoder(w)
	w.Header().Set("Content-Type", "application/json")

	f, err := os.Open(fName)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	defer func() { _ = f.Close() }()
	p, err := parser.NewParser(f)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble scanning dongle configuration"})
		return
	}
	ast, err := p.Parse()
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble parsing dongle configuration"})
		return
	}
	err = ast.ToJSON(w)
	if err != nil {
		log.Println(err)
	}
}

//UpdateDongle updates the dongle documentation file, via a json object. This
//doesnot do verification of the object sent with the request.
//
// The received json is loaded into ast and writen to the dongle configuration
// file directly.
//
// TODO(gernest) do some kind of verification?
func (ww *web) UpdateDongle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	ast := &parser.Ast{}
	src := &bytes.Buffer{}
	enc := json.NewEncoder(w)
	_, err := io.Copy(src, r.Body)
	if err != nil {
		_ = enc.Encode(&errMSG{Message: "trouble reading request body"})
		return
	}
	err = ast.LoadJSON(src.Bytes())
	if err != nil {
		_ = enc.Encode(&errMSG{Message: "trouble loading request body"})
		return
	}
	vars := mux.Vars(r)
	file := vars["filename"] + ".conf"
	fName := filepath.Join(ww.cfg.AsteriskConfig, file)
	info, err := os.Stat(fName)
	if err != nil {
		log.Println(err)
		_ = enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	dst := &bytes.Buffer{}
	parser.PrintAst(dst, ast)
	_ = ioutil.WriteFile(fName, dst.Bytes(), info.Mode())
	_, _ = io.Copy(w, src)
}
<|endoftext|>