<commit_before>package webgo

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"time"
	//"sync"
)

type App struct {
	router        Router
	definitions   Definitions
	templates     *template.Template
	staticDir     string
	modules       Modules
	workDir       string
	tmpDir        string
	maxBodyLength int64
}

const (
	CT_JSON      = "application/json"
	CT_FORM      = "application/x-www-form-urlencoded"
	CT_MULTIPART = "multipart/form-data"
)

var app App
var LOGGER *Logger

func init() {

	// Init LOGGER
	LOGGER = NewLogger()

	cp := consoleProvider{}
	ep := emailProvider{}

	LOGGER.RegisterProvider(cp)
	LOGGER.RegisterProvider(ep)

	LOGGER.AddLogProvider(PROVIDER_CONSOLE)
	LOGGER.AddErrorProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddFatalProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddDebugProvider(PROVIDER_CONSOLE)

	// Init App
	templates := template.New("template")
	filepath.Walk("templates", func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(path, ".html") {
			templates.ParseFiles(path)
		}
		return nil
	})
	app = App{}
	app.router = Router{make(Routes)}
	app.definitions = Definitions{}
	app.templates = templates
	app.staticDir = "public"
	app.modules = Modules{}

	app.workDir, _ = os.Getwd()
	app.tmpDir = app.workDir + "/tmp"
	app.maxBodyLength = 131072

	//TODO: Проверить папку tmp, создать если необходимо
}

func parseRequest(ctx *Context, limit int64) (errorCode int, err error) {
	var body []byte

	defer func() {
		r := recover()
		if r != nil {
			errorCode = 400
			err = errors.New("Bad Request")
		}
	}()
	ctx.Request.Body = http.MaxBytesReader(ctx.Response, ctx.Request.Body, limit)

	if ctx.Request.Method == "GET" {
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

		// Копируем данные
		for i := range ctx.Request.Form {
			ctx.Query[i] = ctx.Request.Form[i]
		}

		return
	}

	switch ctx.ContentType {
	case CT_JSON:
		body, err = ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			errorCode = 400
			return
		}

		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			errorCode = 400
			return
		}
		ctx._Body = body
		ctx.Body = data.(map[string]interface{})

		return
	case CT_FORM:
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

	case CT_MULTIPART:
		err = ctx.Request.ParseMultipartForm(limit)
		if err != nil {
			//TODO: 400 or 413
			errorCode = 400
			return
		}

		for _, fheaders := range ctx.Request.MultipartForm.File {
			for _, hdr := range fheaders {
				var infile multipart.File
				if infile, err = hdr.Open(); nil != err {
					errorCode = 500
					return
				}

				var outfile *os.File
				if outfile, err = os.Create(app.tmpDir + "/" + hdr.Filename); nil != err {
					errorCode = 500
					return
				}
				// 32K buffer copy
				var written int64
				if written, err = io.Copy(outfile, infile); nil != err {
					errorCode = 500
					return
				}

				ctx.Files = append(ctx.Files, File{FileName: hdr.Filename, Size: int64(written)})
			}
		}

	default:
		err = errors.New("Bad Request")
		errorCode = 400
		return
	}

	for i := range ctx.Request.Form {
		ctx.Body[i] = ctx.Request.Form[i]
	}

	return
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//cn, ok := w.(http.CloseNotifier)
	//if !ok {
	//	LOGGER.Fatal("don't support CloseNotifier")
	//}

	var vc reflect.Value
	var Action reflect.Value
	var middlewareGroup string

	method := r.Method
	path := r.URL.Path

	// TODO как отдавать статику?
	/*// Отдаем статику если был запрошен файл
	ext := filepath.Ext(path)
	if ext != "" {
		http.ServeFile(w, r, app.staticDir+filepath.Clean(path))
		return
	}*/

	if len(path) > 1 && path[len(path)-1:] == "/" {
		http.Redirect(w, r, path[:len(path)-1], 301)
		return
	}

	route := a.router.Match(method, path)
	if route == nil {
		http.Error(w, "", 404)
		return
	}

	if route.Options.Timeout == 0 {
		route.Options.Timeout = 2
	}
	//timeout := time.After(route.Options.Timeout * time.Second)
	//done := make(chan bool)

	vc = reflect.New(route.ControllerType)
	Action = vc.MethodByName(route.Options.Action)
	middlewareGroup = route.Options.MiddlewareGroup

	var err error
	ctx := Context{Action: route.Options.Action, Response: w, Request: r, Query: make(map[string]interface{}), Body: make(map[string]interface{}), Params: route.Params, Method: method}
	ctx.ContentType = ctx.Request.Header.Get("Content-Type")
	ctx.ContentType, _, err = mime.ParseMediaType(ctx.ContentType)

	if err != nil && method != "GET" {
		http.Error(w, "", 400)
		return
	}

	if route.Options.ContentType != "" && (method == "POST" || method == "PUT") {
		if route.Options.ContentType != ctx.ContentType {
			http.Error(w, "", 400)
			return
		}
	}

	Controller, ok := vc.Interface().(ControllerInterface)
	if !ok {
		LOGGER.Error(errors.New("controller is not ControllerInterface"))
		http.Error(w, "", 500)
		return
	}

	// Парсим запрос
	var maxBodyLength int64 = app.maxBodyLength
	if route.Options.BodyLength > 0 {
		maxBodyLength = route.Options.BodyLength
	}

	code, err := parseRequest(&ctx, maxBodyLength)
	if err != nil {
		http.Error(w, "", code)
		return
	}

	// Инициализация контекста
	Controller.Init(&ctx)

	// Запуск предобработчика
	if !Controller.Prepare() {
		Controller.exec()
		return
	}

	// Запуск цепочки middleware
	if middlewareGroup != "" {
		isNext := app.definitions.Run(middlewareGroup, &ctx)
		if !isNext {
			return
		}
	}

	in := make([]reflect.Value, 0)
	Action.Call(in)
	//go func () {
	//	in := make([]reflect.Value, 0)
	//	Action.Call(in)
	//	done <- true
	//}()

	// Запуск постобработчика

	Controller.Finish()

	if ctx.ContentType == "multipart/form-data" {
		err = ctx.Files.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}

		err = ctx.Request.MultipartForm.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}
	}

	Controller.exec()

	//select {
	//case <-timeout:
	//	ctx.close = true
	//	w.WriteHeader(503)
	//	w.Write([]byte(""))
	//	return
	//case <-cn.CloseNotify():
	//	//TODO: НИХРЕНА НЕПОНЯТНО!!!
	//	ctx.close = true
	//	w.WriteHeader(503)
	//	w.Write([]byte(""))
	//	return
	//case <-done:
	//	// TODO: Обработать ошибки
	//	if ctx.error != nil {
	//		if ctx.code == 0 {
	//			ctx.code = 500
	//		}
	//		ctx.Response.WriteHeader(ctx.code)
	//		ctx.Response.Write(ctx.output)
	//		return
	//	}
	//
	//	// Проверяем редирект
	//	if ctx.IsRedirect(){
	//		ctx.Response.WriteHeader(ctx.code)
	//		return
	//	}
	//
	//	// Выводим данные
	//	if ctx.code == 0 {
	//		ctx.code = 200
	//	}
	//	ctx.Response.WriteHeader(ctx.code)
	//	ctx.Response.Write(ctx.output)
	//	return
	//}

}

func RegisterMiddleware(name string, plugins ...MiddlewareInterface) {
	for _, plugin := range plugins {
		app.definitions.Register(name, plugin)
	}
}
func RegisterModule(name string, module ModuleInterface) {
	app.modules.RegisterModule(name, module)
}
func Get(url string, opts RouteOptions) {
	app.router.addRoute("GET", url, &opts)
}
func Post(url string, opts RouteOptions) {
	app.router.addRoute("POST", url, &opts)
}
func Put(url string, opts RouteOptions) {
	app.router.addRoute("PUT", url, &opts)
}
func Delete(url string, opts RouteOptions) {
	app.router.addRoute("DELETE", url, &opts)
}
func Options(url string, opts RouteOptions) {
	app.router.addRoute("OPTIONS", url, &opts)
}

func GetModule(str string) ModuleInterface {
	return app.modules[str]
}

func Run() {
	var r *int = flag.Int("r", 0, "read timeout")
	var w *int = flag.Int("w", 0, "write timeout")

	port := CFG.Int("port")

	if port == 0 {
		port = 80
	}

	host := CFG.Str("host")
	if host == "" {
		host = "127.0.0.1"
	}

	address := fmt.Sprintf("%s:%d", host, port)
	fmt.Println("WebGO start ", address)

	server := http.Server{
		Addr:         address,
		ReadTimeout:  time.Duration(*r) * time.Second,
		WriteTimeout: time.Duration(*w) * time.Second,
		Handler:      &app,
	}

	//server.SetKeepAlivesEnabled(false)

	err := server.ListenAndServe()
	if err != nil {
		LOGGER.Fatal(err)
	}

}
<commit_msg>Added Mail<commit_after>package webgo

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"time"
	//"sync"
	"bytes"
)

type App struct {
	router        Router
	definitions   Definitions
	templates     *template.Template
	staticDir     string
	modules       Modules
	workDir       string
	tmpDir        string
	maxBodyLength int64
}

const (
	CT_JSON      = "application/json"
	CT_FORM      = "application/x-www-form-urlencoded"
	CT_MULTIPART = "multipart/form-data"
)

var app App
var LOGGER *Logger

func init() {

	// Init LOGGER
	LOGGER = NewLogger()

	cp := consoleProvider{}
	ep := emailProvider{}

	LOGGER.RegisterProvider(cp)
	LOGGER.RegisterProvider(ep)

	LOGGER.AddLogProvider(PROVIDER_CONSOLE)
	LOGGER.AddErrorProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddFatalProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddDebugProvider(PROVIDER_CONSOLE)

	// Init App
	templates := template.New("template")
	filepath.Walk("templates", func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(path, ".html") {
			templates.ParseFiles(path)
		}
		return nil
	})
	app = App{}
	app.router = Router{make(Routes)}
	app.definitions = Definitions{}
	app.templates = templates
	app.staticDir = "public"
	app.modules = Modules{}

	app.workDir, _ = os.Getwd()
	app.tmpDir = app.workDir + "/tmp"
	app.maxBodyLength = 131072

	//TODO: Проверить папку tmp, создать если необходимо
}

func parseRequest(ctx *Context, limit int64) (errorCode int, err error) {
	var body []byte

	defer func() {
		r := recover()
		if r != nil {
			errorCode = 400
			err = errors.New("Bad Request")
		}
	}()
	ctx.Request.Body = http.MaxBytesReader(ctx.Response, ctx.Request.Body, limit)

	if ctx.Request.Method == "GET" {
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

		// Копируем данные
		for i := range ctx.Request.Form {
			ctx.Query[i] = ctx.Request.Form[i]
		}

		return
	}

	switch ctx.ContentType {
	case CT_JSON:
		body, err = ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			errorCode = 400
			return
		}

		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			errorCode = 400
			return
		}
		ctx._Body = body
		ctx.Body = data.(map[string]interface{})

		return
	case CT_FORM:
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

	case CT_MULTIPART:
		err = ctx.Request.ParseMultipartForm(limit)
		if err != nil {
			//TODO: 400 or 413
			errorCode = 400
			return
		}

		for _, fheaders := range ctx.Request.MultipartForm.File {
			for _, hdr := range fheaders {
				var infile multipart.File
				if infile, err = hdr.Open(); nil != err {
					errorCode = 500
					return
				}

				var outfile *os.File
				if outfile, err = os.Create(app.tmpDir + "/" + hdr.Filename); nil != err {
					errorCode = 500
					return
				}
				// 32K buffer copy
				var written int64
				if written, err = io.Copy(outfile, infile); nil != err {
					errorCode = 500
					return
				}

				ctx.Files = append(ctx.Files, File{FileName: hdr.Filename, Size: int64(written)})
			}
		}

	default:
		err = errors.New("Bad Request")
		errorCode = 400
		return
	}

	for i := range ctx.Request.Form {
		ctx.Body[i] = ctx.Request.Form[i]
	}

	return
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//cn, ok := w.(http.CloseNotifier)
	//if !ok {
	//	LOGGER.Fatal("don't support CloseNotifier")
	//}

	var vc reflect.Value
	var Action reflect.Value
	var middlewareGroup string

	method := r.Method
	path := r.URL.Path

	// TODO как отдавать статику?
	/*// Отдаем статику если был запрошен файл
	ext := filepath.Ext(path)
	if ext != "" {
		http.ServeFile(w, r, app.staticDir+filepath.Clean(path))
		return
	}*/

	if len(path) > 1 && path[len(path)-1:] == "/" {
		http.Redirect(w, r, path[:len(path)-1], 301)
		return
	}

	route := a.router.Match(method, path)
	if route == nil {
		http.Error(w, "", 404)
		return
	}

	if route.Options.Timeout == 0 {
		route.Options.Timeout = 2
	}
	//timeout := time.After(route.Options.Timeout * time.Second)
	//done := make(chan bool)

	vc = reflect.New(route.ControllerType)
	Action = vc.MethodByName(route.Options.Action)
	middlewareGroup = route.Options.MiddlewareGroup

	var err error
	ctx := Context{Action: route.Options.Action, Response: w, Request: r, Query: make(map[string]interface{}), Body: make(map[string]interface{}), Params: route.Params, Method: method}
	ctx.ContentType = ctx.Request.Header.Get("Content-Type")
	ctx.ContentType, _, err = mime.ParseMediaType(ctx.ContentType)

	if err != nil && method != "GET" {
		http.Error(w, "", 400)
		return
	}

	if route.Options.ContentType != "" && (method == "POST" || method == "PUT") {
		if route.Options.ContentType != ctx.ContentType {
			http.Error(w, "", 400)
			return
		}
	}

	Controller, ok := vc.Interface().(ControllerInterface)
	if !ok {
		LOGGER.Error(errors.New("controller is not ControllerInterface"))
		http.Error(w, "", 500)
		return
	}

	// Парсим запрос
	var maxBodyLength int64 = app.maxBodyLength
	if route.Options.BodyLength > 0 {
		maxBodyLength = route.Options.BodyLength
	}

	code, err := parseRequest(&ctx, maxBodyLength)
	if err != nil {
		http.Error(w, "", code)
		return
	}

	// Инициализация контекста
	Controller.Init(&ctx)

	// Запуск предобработчика
	if !Controller.Prepare() {
		Controller.exec()
		return
	}

	// Запуск цепочки middleware
	if middlewareGroup != "" {
		isNext := app.definitions.Run(middlewareGroup, &ctx)
		if !isNext {
			return
		}
	}

	in := make([]reflect.Value, 0)
	Action.Call(in)
	//go func () {
	//	in := make([]reflect.Value, 0)
	//	Action.Call(in)
	//	done <- true
	//}()

	// Запуск постобработчика

	Controller.Finish()

	if ctx.ContentType == "multipart/form-data" {
		err = ctx.Files.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}

		err = ctx.Request.MultipartForm.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}
	}

	Controller.exec()

	//select {
	//case <-timeout:
	//	ctx.close = true
	//	w.WriteHeader(503)
	//	w.Write([]byte(""))
	//	return
	//case <-cn.CloseNotify():
	//	//TODO: НИХРЕНА НЕПОНЯТНО!!!
	//	ctx.close = true
	//	w.WriteHeader(503)
	//	w.Write([]byte(""))
	//	return
	//case <-done:
	//	// TODO: Обработать ошибки
	//	if ctx.error != nil {
	//		if ctx.code == 0 {
	//			ctx.code = 500
	//		}
	//		ctx.Response.WriteHeader(ctx.code)
	//		ctx.Response.Write(ctx.output)
	//		return
	//	}
	//
	//	// Проверяем редирект
	//	if ctx.IsRedirect(){
	//		ctx.Response.WriteHeader(ctx.code)
	//		return
	//	}
	//
	//	// Выводим данные
	//	if ctx.code == 0 {
	//		ctx.code = 200
	//	}
	//	ctx.Response.WriteHeader(ctx.code)
	//	ctx.Response.Write(ctx.output)
	//	return
	//}

}

func RegisterMiddleware(name string, plugins ...MiddlewareInterface) {
	for _, plugin := range plugins {
		app.definitions.Register(name, plugin)
	}
}
func RegisterModule(name string, module ModuleInterface) {
	app.modules.RegisterModule(name, module)
}
func Get(url string, opts RouteOptions) {
	app.router.addRoute("GET", url, &opts)
}
func Post(url string, opts RouteOptions) {
	app.router.addRoute("POST", url, &opts)
}
func Put(url string, opts RouteOptions) {
	app.router.addRoute("PUT", url, &opts)
}
func Delete(url string, opts RouteOptions) {
	app.router.addRoute("DELETE", url, &opts)
}
func Options(url string, opts RouteOptions) {
	app.router.addRoute("OPTIONS", url, &opts)
}

func GetModule(str string) ModuleInterface {
	return app.modules[str]
}
func Mail (address string, subject string, tpl string, model interface{}) (err error) {
	var message []byte
	bytes := bytes.NewBufferString("")
	err = app.templates.ExecuteTemplate(bytes, tpl+".html", model)
	if err != nil {
		return
	}
	message, err = ioutil.ReadAll(bytes)

	mail := NewMail(address, subject, string(message))
	err = mail.SendMail()
	return
}
func Run() {
	var r *int = flag.Int("r", 0, "read timeout")
	var w *int = flag.Int("w", 0, "write timeout")

	port := CFG.Int("port")

	if port == 0 {
		port = 80
	}

	host := CFG.Str("host")
	if host == "" {
		host = "127.0.0.1"
	}

	address := fmt.Sprintf("%s:%d", host, port)
	fmt.Println("WebGO start ", address)

	server := http.Server{
		Addr:         address,
		ReadTimeout:  time.Duration(*r) * time.Second,
		WriteTimeout: time.Duration(*w) * time.Second,
		Handler:      &app,
	}

	//server.SetKeepAlivesEnabled(false)

	err := server.ListenAndServe()
	if err != nil {
		LOGGER.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package main

/* import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
) */

import (
	"errors"
	"fmt"
	//"strconv"
	//"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	//"encoding/json"
	//"regexp"
	//"time"
	//"crypto/md5"
	//"io"
)

var logger = shim.NewLogger("CLDChaincode")

// Participant
const	SHIPPER      =  "shipper"
const	LOGISTIC_PROVIDER   =  "logistic_provider"
const	INSURENCE_COMPANY = "insurence_company"

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Volume struct {
	NextStop								string `json: nextStop`
	Origin									Origin
	Destination								Destination
	LogisticProvider						LogisticProvider
	Volume									VolumeD
	Event									Event
}

type Origin struct {
	Name 									string `json: "name"`
	Address 								string `json: "address"`
	FederalTaxPayerId						string `json: "federalTaxPayerId"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
}

type EndCustomerFinal struct {
	Name 									string `json: "name"`
	FederalTaxPayerId						string `json: "federalTaxPayerId"`
	Address 								string `json: "address"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
	City									string `json: "city"`
	Quarter									string `json: "quarter"`
	Email									string `json: "email"`
	Phone									string `json: "phone"`
	Cellphone								string `json: "cellphone"`
}

type Destination struct {
	EndCustomer 							EndCustomerFinal
	ShipperEstimatedDeliveryDate 			string `json: "shipperEstimatedDeliveryDate"`
	LogisticProviderEstimatedDeliveryDate	string `json: "logisticProviderEstimatedDeliveryDate"`
}

type LogisticProvider struct {
	Id										string `json: "id"`
	Name 									string `json: "name"`
	Address 								string `json: "address"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
	City									string `json: "city"`
	Quarter									string `json: "quarter"`
}

type VolumeD struct {
	TrackId									string `json: "trackId"`
	VolumeData								VolumeData
}

type VolumeData struct {
	Key										string `json: key`
}

type Event struct {
	Date 									string `json: date`
	StatusCode								string `json: statusCode`
	Description								string `json: description`
	LogisticProviderProperties				string `json: logisticProviderPropertis`
}

func main() {
	fmt.Println("[IP] Start Contract")

	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("invoke is running " + function)

    // Handle different functions
    if function == "init" {
        return t.Init(stub, "init", args)
	} else if function == "createVolume" {
		return t.CreateVolume(stub)
	} /* else if function == "shipperToLogisticProvider" {
        return t.shipperToLogisticProvider(stub, args)
    } else if function == "LogisticProviderToCustomer" {
		return t.LogisticProviderToCustomer(stub, args)
	} else if function == "LogisticProviderToLogisticProvider" {
		return t.LogisticProviderToLogisticProvider(stub, args)
	} else if function == "LogisticProviderToShipper" {
		return t.LogisticProviderToShipper(stub, args)
	} */

    fmt.Println("invoke did not find func: " + function)
	logger.Debug("invoke did not find func: ", function)

    return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("query is running " + function)

    /* if function == "read" {                            //read a variable
        return t.read(stub, args)
    }
    fmt.Println("query did not find func: " + function)
 */
    return nil, errors.New("Received unknown function query")
}

// Functions to Write
func (t *SimpleChaincode) CreateVolume(stub shim.ChaincodeStubInterface) ([]byte, error) {
	var v Volume

	//v.NextStop       	= nil
	//v.Origin         	= nil
	//v.Destination    	= nil
	//v.LogisticProvifer	= nil
	//v.Event         	= nil
	v.Volume.TrackId	= "chave";

 	fmt.Println("[IP][Volume]: fmt" + v.Volume.TrackId)
	logger.Debug("[IP][Volume]: logger", v)

	return nil, nil
	//err = json.Unmarshal([]byte(volume_json), &v)

	// if volume already exists

	/* record, err := stub.GetState(v.id)
	if record != nil { return nil, errors.New("Volume already exists") } */

	//_, err  = t.save_changes(stub, v)

	//if err != nil { fmt.Printf("Create_Volume: Error saving changes: %s", err); return nil, errors.New("Error saving changes") }
}

/* func (t *SimpleChaincode) save_changes(stub shim.ChaincodeStubInterface, v Volume) (bool, error) {

	bytes, err := json.Marshal(v)

	if err != nil { fmt.Printf("SAVE_CHANGES: Error converting vehicle record: %s", err); return false, errors.New("Error converting volume record") }

	err = stub.PutState(v.id, bytes)

	if err != nil { fmt.Printf("SAVE_CHANGES: Error storing volume record: %s", err); return false, errors.New("Error storing volume record") }

	return true, nil
} */

// Functions to Read<commit_msg>teste 4<commit_after>package main

/* import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
) */

import (
	"errors"
	"fmt"
	//"strconv"
	//"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	//"encoding/json"
	//"regexp"
	//"time"
	//"crypto/md5"
	//"io"
)

var logger = shim.NewLogger("CLDChaincode")

// Participant
const	SHIPPER      =  "shipper"
const	LOGISTIC_PROVIDER   =  "logistic_provider"
const	INSURENCE_COMPANY = "insurence_company"

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Volume struct {
	NextStop								string `json: nextStop`
	Origin									Origin
	Destination								Destination
	LogisticProvider						LogisticProvider
	Volume									VolumeD
	Event									Event
}

type Origin struct {
	Name 									string `json: "name"`
	Address 								string `json: "address"`
	FederalTaxPayerId						string `json: "federalTaxPayerId"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
}

type EndCustomerFinal struct {
	Name 									string `json: "name"`
	FederalTaxPayerId						string `json: "federalTaxPayerId"`
	Address 								string `json: "address"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
	City									string `json: "city"`
	Quarter									string `json: "quarter"`
	Email									string `json: "email"`
	Phone									string `json: "phone"`
	Cellphone								string `json: "cellphone"`
}

type Destination struct {
	EndCustomer 							EndCustomerFinal
	ShipperEstimatedDeliveryDate 			string `json: "shipperEstimatedDeliveryDate"`
	LogisticProviderEstimatedDeliveryDate	string `json: "logisticProviderEstimatedDeliveryDate"`
}

type LogisticProvider struct {
	Id										string `json: "id"`
	Name 									string `json: "name"`
	Address 								string `json: "address"`
	AddressNumber							int	   `json: "addressNumber"`
	ZipCode									string `json: "zipCode"`
	City									string `json: "city"`
	Quarter									string `json: "quarter"`
}

type VolumeD struct {
	TrackId									string `json: "trackId"`
	VolumeData								VolumeData
}

type VolumeData struct {
	Key										string `json: key`
}

type Event struct {
	Date 									string `json: date`
	StatusCode								string `json: statusCode`
	Description								string `json: description`
	LogisticProviderProperties				string `json: logisticProviderPropertis`
}

func main() {
	fmt.Println("[IP] Start Contract")

	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("invoke is running " + function)

    // Handle different functions
    if function == "init" {
        return t.Init(stub, "init", args)
	} else if function == "CreateVolume" {
		return t.CreateVolume(stub)
	} /* else if function == "shipperToLogisticProvider" {
        return t.shipperToLogisticProvider(stub, args)
    } else if function == "LogisticProviderToCustomer" {
		return t.LogisticProviderToCustomer(stub, args)
	} else if function == "LogisticProviderToLogisticProvider" {
		return t.LogisticProviderToLogisticProvider(stub, args)
	} else if function == "LogisticProviderToShipper" {
		return t.LogisticProviderToShipper(stub, args)
	} */

    fmt.Println("invoke did not find func: " + function)
	logger.Debug("invoke did not find func: ", function)

    return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("query is running " + function)

    /* if function == "read" {                            //read a variable
        return t.read(stub, args)
    }
    fmt.Println("query did not find func: " + function)
 */
    return nil, errors.New("Received unknown function query")
}

// Functions to Write
func (t *SimpleChaincode) CreateVolume(stub shim.ChaincodeStubInterface) ([]byte, error) {
	var v Volume

	//v.NextStop       	= nil
	//v.Origin         	= nil
	//v.Destination    	= nil
	//v.LogisticProvifer	= nil
	//v.Event         	= nil
	v.Volume.TrackId	= "chave";

 	fmt.Println("[IP][Volume]: fmt" + v.Volume.TrackId)
	logger.Debug("[IP][Volume]: logger", v)

	return nil, nil
	//err = json.Unmarshal([]byte(volume_json), &v)

	// if volume already exists

	/* record, err := stub.GetState(v.id)
	if record != nil { return nil, errors.New("Volume already exists") } */

	//_, err  = t.save_changes(stub, v)

	//if err != nil { fmt.Printf("Create_Volume: Error saving changes: %s", err); return nil, errors.New("Error saving changes") }
}

/* func (t *SimpleChaincode) save_changes(stub shim.ChaincodeStubInterface, v Volume) (bool, error) {

	bytes, err := json.Marshal(v)

	if err != nil { fmt.Printf("SAVE_CHANGES: Error converting vehicle record: %s", err); return false, errors.New("Error converting volume record") }

	err = stub.PutState(v.id, bytes)

	if err != nil { fmt.Printf("SAVE_CHANGES: Error storing volume record: %s", err); return false, errors.New("Error storing volume record") }

	return true, nil
} */

// Functions to Read<|endoftext|>


<commit_before>package webgo

import (
	"encoding/json"
	"errors"
	"html/template"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"flag"
	"time"
)

type App struct {
	router        Router
	definitions   Definitions
	templates     *template.Template
	staticDir     string
	modules       Modules
	workDir       string
	tmpDir        string
	maxBodyLength int64
}

const (
	CT_JSON      = "application/json"
	CT_FORM      = "application/x-www-form-urlencoded"
	CT_MULTIPART = "multipart/form-data"
)

var app App
var CFG config
var LOGGER *Logger

func init() {

	var err error

	// Init CFG
	CFG = make(config)

	err = CFG.Read()

	if err != nil {
		panic(err)
	}

	// Init LOGGER
	LOGGER = NewLogger()

	cp := consoleProvider{}
	ep := emailProvider{}

	LOGGER.RegisterProvider(cp)
	LOGGER.RegisterProvider(ep)

	LOGGER.AddLogProvider(PROVIDER_CONSOLE)
	LOGGER.AddErrorProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddFatalProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddDebugProvider(PROVIDER_CONSOLE)

	// Init App
	templates := template.New("template")
	filepath.Walk("templates", func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(path, ".html") {
			templates.ParseFiles(path)
		}
		return nil
	})
	app = App{}
	app.router = Router{make(Routes)}
	app.definitions = Definitions{}
	app.templates = templates
	app.staticDir = "public"
	app.modules = Modules{}

	app.workDir, err = os.Getwd()
	app.tmpDir = app.workDir + "/tmp"

	if CFG["maxBodyLength"] == "" {
		panic("maxBodyLength is empty")
	}
	app.maxBodyLength, err = strconv.ParseInt(CFG["maxBodyLength"], 10, 64)
	if err != nil {
		os.Exit(1)
	}

	//TODO: Проверить папку tmp, создать если необходимо
}

func parseRequest(ctx *Context, limit int64) (errorCode int, err error) {
	var body []byte

	defer func() {
		r := recover()
		if r != nil {
			errorCode = 400
			err = errors.New("Bad Request")
		}
	}()
	ctx.Request.Body = http.MaxBytesReader(ctx.Response, ctx.Request.Body, limit)

	if ctx.Request.Method == "GET" {
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

		// Копируем данные
		for i := range ctx.Request.Form {
			ctx.Query[i] = ctx.Request.Form[i]
		}

		return
	}

	switch ctx.ContentType {
	case CT_JSON:
		body, err = ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			errorCode = 400
			return
		}

		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			errorCode = 400
			return
		}
		ctx._Body = body
		ctx.Body = data.(map[string]interface{})

		return
	case CT_FORM:
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

	case CT_MULTIPART:
		err = ctx.Request.ParseMultipartForm(limit)
		if err != nil {
			//TODO: 400 or 413
			errorCode = 400
			return
		}

		for _, fheaders := range ctx.Request.MultipartForm.File {
			for _, hdr := range fheaders {
				var infile multipart.File
				if infile, err = hdr.Open(); nil != err {
					errorCode = 500
					return
				}

				var outfile *os.File
				if outfile, err = os.Create(app.tmpDir + "/" + hdr.Filename); nil != err {
					errorCode = 500
					return
				}
				// 32K buffer copy
				var written int64
				if written, err = io.Copy(outfile, infile); nil != err {
					errorCode = 500
					return
				}

				ctx.Files = append(ctx.Files, File{FileName: hdr.Filename, Size: int64(written)})
			}
		}

	default:
		err = errors.New("Bad Request")
		errorCode = 400
		return
	}

	for i := range ctx.Request.Form {
		ctx.Body[i] = ctx.Request.Form[i]
	}

	return
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	var vc reflect.Value
	var Action reflect.Value
	var middlewareGroup string

	method := r.Method
	path := r.URL.Path

	// Отдаем статику если был запрошен файл
	ext := filepath.Ext(path)
	if ext != "" {
		http.ServeFile(w, r, app.staticDir+filepath.Clean(path))
		return
	}

	if len(path) > 1 && path[len(path)-1:] == "/" {
		http.Redirect(w, r, path[:len(path)-1], 301)
		return
	}

	route := a.router.Match(method, path)
	if route == nil {
		http.Error(w, "", 404)
		return
	}

	vc = reflect.New(route.ControllerType)
	Action = vc.MethodByName(route.Options.Action)
	middlewareGroup = route.Options.MiddlewareGroup

	var err error
	ctx := Context{Action: route.Options.Action, Response: w, Request: r, Query: make(map[string]interface{}), Body: make(map[string]interface{}), Params: route.Params, Method: method}
	ctx.ContentType = ctx.Request.Header.Get("Content-Type")
	ctx.ContentType, _, err = mime.ParseMediaType(ctx.ContentType)

	if err != nil && method != "GET" {
		http.Error(w, "", 400)
		return
	}

	if route.Options.ContentType != "" && (method == "POST" || method == "PUT") {
		if route.Options.ContentType != ctx.ContentType {
			http.Error(w, "", 400)
			return
		}
	}

	Controller, ok := vc.Interface().(ControllerInterface)
	if !ok {
		LOGGER.Error(errors.New("controller is not ControllerInterface"))
		http.Error(w, "", 500)
		return
	}

	// Парсим запрос
	code, err := parseRequest(&ctx, app.maxBodyLength)
	if err != nil {
		http.Error(w, "", code)
		return
	}

	// Инициализация контекста
	Controller.Init(&ctx)

	// Запуск предобработчика
	if !Controller.Prepare() {
		return
	}

	// Запуск цепочки middleware
	if middlewareGroup != "" {
		isNext := app.definitions.Run(middlewareGroup, &ctx)
		if !isNext {
			return
		}
	}

	// Запуск Экшена
	in := make([]reflect.Value, 0)
	Action.Call(in)

	if ctx.ContentType == "multipart/form-data" {
		err = ctx.Files.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}

		err = ctx.Request.MultipartForm.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}
	}

	// Обрабатываем ошибки
	if ctx.error != nil {
		LOGGER.Error(err)
		http.Error(w, "", 500)
		return
	}

	// Запуск постобработчика
	Controller.Finish()
}

func RegisterMiddleware(name string, plugins ...MiddlewareInterface) {
	for _, plugin := range plugins {
		app.definitions.Register(name, plugin)
	}
}
func RegisterModule(name string, module ModuleInterface) {
	app.modules.RegisterModule(name, module)
}

func Get(url string, opts RouteOptions) {
	app.router.addRoute("GET", url, &opts)
}
func Post(url string, opts RouteOptions) {
	app.router.addRoute("POST", url, &opts)
}
func Put(url string, opts RouteOptions) {
	app.router.addRoute("PUT", url, &opts)
}
func Delete(url string, opts RouteOptions) {
	app.router.addRoute("DELETE", url, &opts)
}
func Options(url string, opts RouteOptions) {
	app.router.addRoute("OPTIONS", url, &opts)
}

func GetModule(str string) ModuleInterface {
	return app.modules[str]
}

func Run() {
	var r *int = flag.Int("r", 1, "read timeout")
	var w *int = flag.Int("w", 1, "write timeout")

	if CFG["port"] == "" {
		LOGGER.Fatal("Unknow port")
	}
	server := http.Server{
		Addr:         ":"+CFG["port"],
		ReadTimeout:  time.Duration(*r) * time.Second,
		WriteTimeout: time.Duration(*w) * time.Second,
		Handler:&app,
	}

	server.ListenAndServe()

//	err := http.ListenAndServe(":"+CFG["port"], &app)
//	if err != nil {
//		LOGGER.Fatal(err)
//	}
}
<commit_msg>Update<commit_after>package webgo

import (
	"encoding/json"
	"errors"
	"html/template"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"flag"
	"time"
)

type App struct {
	router        Router
	definitions   Definitions
	templates     *template.Template
	staticDir     string
	modules       Modules
	workDir       string
	tmpDir        string
	maxBodyLength int64
}

const (
	CT_JSON      = "application/json"
	CT_FORM      = "application/x-www-form-urlencoded"
	CT_MULTIPART = "multipart/form-data"
)

var app App
var CFG config
var LOGGER *Logger

func init() {

	var err error

	// Init CFG
	CFG = make(config)

	err = CFG.Read()

	if err != nil {
		panic(err)
	}

	// Init LOGGER
	LOGGER = NewLogger()

	cp := consoleProvider{}
	ep := emailProvider{}

	LOGGER.RegisterProvider(cp)
	LOGGER.RegisterProvider(ep)

	LOGGER.AddLogProvider(PROVIDER_CONSOLE)
	LOGGER.AddErrorProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddFatalProvider(PROVIDER_CONSOLE, PROVIDER_EMAIL)
	LOGGER.AddDebugProvider(PROVIDER_CONSOLE)

	// Init App
	templates := template.New("template")
	filepath.Walk("templates", func(path string, info os.FileInfo, err error) error {
		if strings.HasSuffix(path, ".html") {
			templates.ParseFiles(path)
		}
		return nil
	})
	app = App{}
	app.router = Router{make(Routes)}
	app.definitions = Definitions{}
	app.templates = templates
	app.staticDir = "public"
	app.modules = Modules{}

	app.workDir, err = os.Getwd()
	app.tmpDir = app.workDir + "/tmp"

	if CFG["maxBodyLength"] == "" {
		panic("maxBodyLength is empty")
	}
	app.maxBodyLength, err = strconv.ParseInt(CFG["maxBodyLength"], 10, 64)
	if err != nil {
		os.Exit(1)
	}

	//TODO: Проверить папку tmp, создать если необходимо
}

func parseRequest(ctx *Context, limit int64) (errorCode int, err error) {
	var body []byte

	defer func() {
		r := recover()
		if r != nil {
			errorCode = 400
			err = errors.New("Bad Request")
		}
	}()
	ctx.Request.Body = http.MaxBytesReader(ctx.Response, ctx.Request.Body, limit)

	if ctx.Request.Method == "GET" {
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

		// Копируем данные
		for i := range ctx.Request.Form {
			ctx.Query[i] = ctx.Request.Form[i]
		}

		return
	}

	switch ctx.ContentType {
	case CT_JSON:
		body, err = ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			errorCode = 400
			return
		}

		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			errorCode = 400
			return
		}
		ctx._Body = body
		ctx.Body = data.(map[string]interface{})

		return
	case CT_FORM:
		err = ctx.Request.ParseForm()
		if err != nil {
			errorCode = 400
			return
		}

	case CT_MULTIPART:
		err = ctx.Request.ParseMultipartForm(limit)
		if err != nil {
			//TODO: 400 or 413
			errorCode = 400
			return
		}

		for _, fheaders := range ctx.Request.MultipartForm.File {
			for _, hdr := range fheaders {
				var infile multipart.File
				if infile, err = hdr.Open(); nil != err {
					errorCode = 500
					return
				}

				var outfile *os.File
				if outfile, err = os.Create(app.tmpDir + "/" + hdr.Filename); nil != err {
					errorCode = 500
					return
				}
				// 32K buffer copy
				var written int64
				if written, err = io.Copy(outfile, infile); nil != err {
					errorCode = 500
					return
				}

				ctx.Files = append(ctx.Files, File{FileName: hdr.Filename, Size: int64(written)})
			}
		}

	default:
		err = errors.New("Bad Request")
		errorCode = 400
		return
	}

	for i := range ctx.Request.Form {
		ctx.Body[i] = ctx.Request.Form[i]
	}

	return
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	var vc reflect.Value
	var Action reflect.Value
	var middlewareGroup string

	method := r.Method
	path := r.URL.Path

	// Отдаем статику если был запрошен файл
	ext := filepath.Ext(path)
	if ext != "" {
		http.ServeFile(w, r, app.staticDir+filepath.Clean(path))
		return
	}

	if len(path) > 1 && path[len(path)-1:] == "/" {
		http.Redirect(w, r, path[:len(path)-1], 301)
		return
	}

	route := a.router.Match(method, path)
	if route == nil {
		http.Error(w, "", 404)
		return
	}

	vc = reflect.New(route.ControllerType)
	Action = vc.MethodByName(route.Options.Action)
	middlewareGroup = route.Options.MiddlewareGroup

	var err error
	ctx := Context{Action: route.Options.Action, Response: w, Request: r, Query: make(map[string]interface{}), Body: make(map[string]interface{}), Params: route.Params, Method: method}
	ctx.ContentType = ctx.Request.Header.Get("Content-Type")
	ctx.ContentType, _, err = mime.ParseMediaType(ctx.ContentType)

	if err != nil && method != "GET" {
		http.Error(w, "", 400)
		return
	}

	if route.Options.ContentType != "" && (method == "POST" || method == "PUT") {
		if route.Options.ContentType != ctx.ContentType {
			http.Error(w, "", 400)
			return
		}
	}

	Controller, ok := vc.Interface().(ControllerInterface)
	if !ok {
		LOGGER.Error(errors.New("controller is not ControllerInterface"))
		http.Error(w, "", 500)
		return
	}

	// Парсим запрос
	code, err := parseRequest(&ctx, app.maxBodyLength)
	if err != nil {
		http.Error(w, "", code)
		return
	}

	// Инициализация контекста
	Controller.Init(&ctx)

	// Запуск предобработчика
	if !Controller.Prepare() {
		return
	}

	// Запуск цепочки middleware
	if middlewareGroup != "" {
		isNext := app.definitions.Run(middlewareGroup, &ctx)
		if !isNext {
			return
		}
	}

	// Запуск Экшена
	in := make([]reflect.Value, 0)
	Action.Call(in)

	if ctx.ContentType == "multipart/form-data" {
		err = ctx.Files.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}

		err = ctx.Request.MultipartForm.RemoveAll()
		if err != nil {
			LOGGER.Error(err)
		}
	}

	// Обрабатываем ошибки
	if ctx.error != nil {
		LOGGER.Error(err)
		http.Error(w, "", 500)
		return
	}

	// Запуск постобработчика
	Controller.Finish()
}

func RegisterMiddleware(name string, plugins ...MiddlewareInterface) {
	for _, plugin := range plugins {
		app.definitions.Register(name, plugin)
	}
}
func RegisterModule(name string, module ModuleInterface) {
	app.modules.RegisterModule(name, module)
}

func Get(url string, opts RouteOptions) {
	app.router.addRoute("GET", url, &opts)
}
func Post(url string, opts RouteOptions) {
	app.router.addRoute("POST", url, &opts)
}
func Put(url string, opts RouteOptions) {
	app.router.addRoute("PUT", url, &opts)
}
func Delete(url string, opts RouteOptions) {
	app.router.addRoute("DELETE", url, &opts)
}
func Options(url string, opts RouteOptions) {
	app.router.addRoute("OPTIONS", url, &opts)
}

func GetModule(str string) ModuleInterface {
	return app.modules[str]
}

func Run() {
	var r *int = flag.Int("r", 1, "read timeout")
	var w *int = flag.Int("w", 1, "write timeout")

	if CFG["port"] == "" {
		LOGGER.Fatal("Unknow port")
	}
	server := http.Server{
		Addr:         ":"+CFG["port"],
		ReadTimeout:  time.Duration(*r) * time.Second,
		WriteTimeout: time.Duration(*w) * time.Second,
		Handler:&app,
	}

	err := server.ListenAndServe()
	if err != nil {
		LOGGER.Fatal(err)
	}
//	err := http.ListenAndServe(":"+CFG["port"], &app)
//	if err != nil {
//		LOGGER.Fatal(err)
//	}
}
<|endoftext|>


<commit_before>// Clock counts down to or up from a target time.
package main

import (
	"fmt"
	"os"
	"time"
)

// Update target and motto as desired.
var (
	target = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
	motto  = "Just Go"
)

func main() {
	printTargetTime(target, motto)
	exitOnEnterKey()

	var previous time.Time
	for {
		now := time.Now().Truncate(time.Second)
		if now != previous {
			previous = now
			countdown := now.Sub(target) // Negative times are before the target
			printCountdown(now.In(target.Location()), countdown)
		}
		time.Sleep(100 * time.Millisecond)
	}
}

func exitOnEnterKey() {
	go func() {
		buf := make([]byte, 1)
		_, _ = os.Stdin.Read(buf)
		os.Exit(0)
	}()
}

const (
	highlightStart = "\x1b[1;35m"
	highlightEnd   = "\x1b[0m"
	indent         = "\t"
)

func printTargetTime(target time.Time, motto string) {
	fmt.Print(indent, highlightStart, motto, highlightEnd, "\n")
	fmt.Print(indent, target.Format(time.UnixDate), "\n")
}

func printCountdown(now time.Time, countdown time.Duration) {
	var sign string
	if countdown >= 0 {
		sign = "+"
	} else {
		sign = "-"
		countdown = -countdown
	}

	days := int(countdown / (24 * time.Hour))
	countdown = countdown % (24 * time.Hour)

	fmt.Print(indent, now.Format(time.UnixDate), "  ", sign)
	if days > 0 {
		fmt.Print(days, "d")
	}
	fmt.Print(countdown, "          \r")
	os.Stdout.Sync()
}
<commit_msg>Local time<commit_after>// Clock counts down to or up from a target time.
package main

import (
	"fmt"
	"os"
	"time"
)

// Update target and motto as desired.
var (
	target = time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
	motto  = "Just Go"
)

func main() {
	printTargetTime(target, motto)
	exitOnEnterKey()

	var previous time.Time
	for {
		now := time.Now().Truncate(time.Second)
		if now != previous {
			previous = now
			countdown := now.Sub(target) // Negative times are before the target
			printCountdown(now.In(target.Location()), countdown)
		}
		time.Sleep(100 * time.Millisecond)
	}
}

func exitOnEnterKey() {
	go func() {
		buf := make([]byte, 1)
		_, _ = os.Stdin.Read(buf)
		os.Exit(0)
	}()
}

const (
	highlightStart = "\x1b[1;35m"
	highlightEnd   = "\x1b[0m"
	indent         = "\t"
)

func printTargetTime(target time.Time, motto string) {
	fmt.Print(indent, highlightStart, motto, highlightEnd, "\n")
	fmt.Print(indent, target.Format(time.UnixDate), "\n")
}

func printCountdown(now time.Time, countdown time.Duration) {
	var sign string
	if countdown >= 0 {
		sign = "+"
	} else {
		sign = "-"
		countdown = -countdown
	}

	days := int(countdown / (24 * time.Hour))
	countdown = countdown % (24 * time.Hour)

	fmt.Print(indent, now.Format(time.UnixDate), "  ", sign)
	if days > 0 {
		fmt.Print(days, "d")
	}
	fmt.Print(countdown, "          \r")
	os.Stdout.Sync()
}
<|endoftext|>


<commit_before>// Clock counts down to or up from a target time.
package main

import (
	"fmt"
	"os"
	"time"
)

func main() {
	target := time.Date(2018, 5, 12, 21, 36, 0, 0, time.Local)
	motto := "Just Go"
	printTargetTime(target, motto)
	exitOnEnterKey()

	var previous time.Time
	for {
		now := time.Now().Truncate(time.Second)
		if now != previous {
			previous = now
			countdown := now.Sub(target) // Negative times are before the target
			printCountdown(now, countdown)
		}
		time.Sleep(100 * time.Millisecond)
	}
}

func exitOnEnterKey() {
	go func() {
		buf := make([]byte, 1)
		_, _ = os.Stdin.Read(buf)
		os.Exit(0)
	}()
}

const (
	indent         = "\t"
	highlightStart = "\x1b[1;35m"
	highlightEnd   = "\x1b[0m"
)

func printTargetTime(target time.Time, motto string) {
	fmt.Print(indent, highlightStart, motto, highlightEnd, "\n")
	fmt.Print(indent, target.Format(time.UnixDate), "\n")
}

func printCountdown(now time.Time, countdown time.Duration) {
	var sign string
	if countdown >= 0 {
		sign = "+"
	} else {
		sign = "-"
		countdown = -countdown
	}

	days := int(countdown / (24 * time.Hour))
	countdown = countdown % (24 * time.Hour)

	fmt.Print(indent, now.Format(time.UnixDate), "  ", sign)
	if days > 0 {
		fmt.Print(days, "d")
	}
	fmt.Print(countdown, "          \r")
	os.Stdout.Sync()
}
<commit_msg>Go Simplify<commit_after>// Clock counts down to or up from a target time.
package main

import (
	"fmt"
	"os"
	"time"
)

func main() {
	target := time.Date(2018, 5, 21, 0, 0, 0, 0, time.UTC)
	motto := "Go Simplify"
	printTargetTime(target, motto)
	exitOnEnterKey()

	var previous time.Time
	for {
		now := time.Now().Truncate(time.Second)
		if now != previous {
			previous = now
			countdown := now.Sub(target) // Negative times are before the target
			printCountdown(now, countdown)
		}
		time.Sleep(100 * time.Millisecond)
	}
}

func exitOnEnterKey() {
	go func() {
		buf := make([]byte, 1)
		_, _ = os.Stdin.Read(buf)
		os.Exit(0)
	}()
}

const (
	indent         = "\t"
	highlightStart = "\x1b[1;35m"
	highlightEnd   = "\x1b[0m"
)

func printTargetTime(target time.Time, motto string) {
	fmt.Print(indent, highlightStart, motto, highlightEnd, "\n")
	fmt.Print(indent, target.Format(time.UnixDate), "\n")
}

func printCountdown(now time.Time, countdown time.Duration) {
	var sign string
	if countdown >= 0 {
		sign = "+"
	} else {
		sign = "-"
		countdown = -countdown
	}

	days := int(countdown / (24 * time.Hour))
	countdown = countdown % (24 * time.Hour)

	fmt.Print(indent, now.Format(time.UnixDate), "  ", sign)
	if days > 0 {
		fmt.Print(days, "d")
	}
	fmt.Print(countdown, "          \r")
	os.Stdout.Sync()
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2014 by Artem Andreenko, Openstat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 ******************************************************************************/
 package msgbatch

import (
	"code.google.com/p/snappy-go/snappy"
	"github.com/vmihailenco/msgpack"
)

type Batch struct {
	Length  int
	Columns []string
	Values  [][]Value
}

type Value struct {
	i int
	v string
}

func (batch *Batch) Add(e map[string]string) {
	for key, value := range e {
		columnIndex := -1
		for i, column := range batch.Columns {
			if column == key {
				columnIndex = i
				break
			}
		}
		if columnIndex == -1 {
			columnIndex = len(batch.Columns)
			batch.Columns = append(batch.Columns, key)
			batch.Values = append(batch.Values, []Value{})
		}
		batch.Values[columnIndex] = append(batch.Values[columnIndex], Value{i: batch.Length, v: value})
	}
	batch.Length++
}

func (batch *Batch) GetValues() (values []map[string]string) {
	for i := 0; i < batch.Length; i++ {
		values = append(values, make(map[string]string))
	}
	for columnIndex, column := range batch.Values {
		columnName := batch.Columns[columnIndex]
		for valueIndex, value := range column {
			values[valueIndex][columnName] = value.v
		}
	}
	return
}

func (batch *Batch) Encode() (data []byte, err error) {
	data, err = msgpack.Marshal(batch)
	if err != nil {
		return
	}
	data, err = snappy.Encode(nil, data)
	return
}

func Decode(data []byte) (batch Batch, err error) {
	data, err = snappy.Decode(nil, data)
	if err != nil {
		return
	}
	err = msgpack.Unmarshal(data, &batch)
	return
}
<commit_msg>add optional field logic<commit_after>/*******************************************************************************
 * Copyright 2014 by Artem Andreenko, Openstat.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 ******************************************************************************/
 package msgbatch

import (
	"code.google.com/p/snappy-go/snappy"
	"github.com/vmihailenco/msgpack"
)

type Batch struct {
	Length  int
	Columns []string
	Values  [][]Value
}

type Value struct {
	i int
	v string
}

func (batch *Batch) Add(e map[string]string) {
	for key, value := range e {
		columnIndex := -1
		for i, column := range batch.Columns {
			if column == key {
				columnIndex = i
				break
			}
		}
		if columnIndex == -1 {
			columnIndex = len(batch.Columns)
			batch.Columns = append(batch.Columns, key)
			batch.Values = append(batch.Values, []Value{})
		}
		batch.Values[columnIndex] = append(batch.Values[columnIndex], Value{i: batch.Length, v: value})
	}
	batch.Length++
}

func (batch *Batch) GetValues() (values []map[string]string) {
	for i := 0; i < batch.Length; i++ {
		values = append(values, make(map[string]string))
	}
	for columnIndex, column := range batch.Values {
		columnName := batch.Columns[columnIndex]
		for valueIndex, value := range column {
			values[value.i][columnName] = value.v
		}
	}
	return
}

func (batch *Batch) Encode() (data []byte, err error) {
	data, err = msgpack.Marshal(batch)
	if err != nil {
		return
	}
	data, err = snappy.Encode(nil, data)
	return
}

func Decode(data []byte) (batch Batch, err error) {
	data, err = snappy.Decode(nil, data)
	if err != nil {
		return
	}
	err = msgpack.Unmarshal(data, &batch)
	return
}
<|endoftext|>


<commit_before>/*
Color support for linux shell
*/
package klog

import (
	"reflect"
	"strings"
)

const ansiReset = "\x1b[0m"

type ansi struct{}

func (c *ansi) getMethod(name string) (reflect.Method, bool) {
	methodName := strings.Title(name)
	return reflect.TypeOf(c).MethodByName(methodName)
}

func (c *ansi) print(color, s string) string {
	return color + s + ansiReset
}

func (c *ansi) Red(s string) string {
	return c.print("\x1b[31m", s)
}

func (c *ansi) Green(s string) string {
	return c.print("\x1b[32m", s)
}

func (c *ansi) Yellow(s string) string {
	return c.print("\x1b[33m", s)
}

func (c *ansi) Blue(s string) string {
	return c.print("\x1b[34m", s)
}

func (c *ansi) Magenta(s string) string {
	return c.print("\x1b[35m", s)
}

func (c *ansi) Cyan(s string) string {
	return c.print("\x1b[36m", s)
}
<commit_msg>remove color.go, no use now<commit_after><|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path"
	"sort"

	"github.com/gummiboll/woozy/weatherdata"
)

// Configuration for woozy
type Configuration struct {
	Place string `json:"place"`
	Days  int    `json:"days"`
}

var (
	icons = map[string]string{
		"Rain":                           "\U0001f327",
		"Snow":                           "\U0001f328",
		"Rain and thunder":               "\u26C8",
		"Light rain":                     "\U0001f326",
		"Light snow":                     "\U0001f328",
		"Light rain and thunder":         "\u26C8",
		"Light rain showers":             "\U0001f326",
		"Light rain showers and thunder": "\u26C8",
		"Light snow showers":             "\U0001f328",
		"Heavy rain":                     "\U0001f327",
		"Heavy rain and thunder":         "\u26C8",
		"Heavy snow":                     "\U0001f328",
		"Rain showers":                   "\U0001f326",
		"Rain showers and thunder":       "\u26C8",
		"Snow showers":                   "\U0001f328",
		"Clear sky":                      "\u263C",
		"Cloudy":                         "\u2601",
		"Partly cloudy":                  "\u26C5",
		"Fair":                           "\u26C5",
	}

	windIcons = map[string]string{
		"N":   "\u2193",
		"S":   "\u2191",
		"E":   "\u2190",
		"W":   "\u2192",
		"NE":  "\u2199",
		"NNE": "\u2199",
		"NEE": "\u2199",
		"ENE": "\u2199",
		"NW":  "\u2198",
		"NNW": "\u2198",
		"NWW": "\u2198",
		"WNW": "\u2198",
		"SE":  "\u2196",
		"SEE": "\u2196",
		"SSE": "\u2196",
		"ESE": "\u2196",
		"SW":  "\u2197",
		"SSW": "\u2197",
		"SWW": "\u2197",
		"WSW": "\u2197",
	}
)

func printHeader(wd weatherdata.WeatherData) {
	hStr := fmt.Sprintf("%s / %s", wd.Location.Country, wd.Location.Name)
	hStr = fmt.Sprintf("%s | %s %s %s %s %s (%.1f hours)\n", hStr, icons["Clear sky"], windIcons["S"], wd.Sun.Rise.Local().Format("15:04"), windIcons["N"], wd.Sun.Set.Local().Format("15:04"), wd.SunHours())
	fmt.Println(hStr)
}

func printFooter(wd weatherdata.WeatherData) {
	fmt.Println(fmt.Sprintf("Forecast issued %.1f hours ago, next update in %.1f hours", wd.Meta.HoursSinceUpdate(), wd.Meta.HoursToNextUpdate()))
	fmt.Println(fmt.Sprintf("\n%s.\n%s", wd.Credit.Text, wd.Credit.URL))
}

func printForecast(wd weatherdata.WeatherData, days int) {
	forecasts := make(map[string][]weatherdata.WeatherForecast)
	for i := range wd.Forecast {
		// Should maybe be typecasted to int?
		forecasts[wd.Forecast[i].From.Format("20060102")] = append(forecasts[wd.Forecast[i].From.Format("20060102")], wd.Forecast[i])
	}

	mk := make([]string, len(forecasts))
	i := 0
	for k := range forecasts {
		mk[i] = k
		i++
	}

	sort.Strings(mk)

	for i := 0; i < days; i++ {
		var wStr string
		fmt.Println(forecasts[mk[i]][0].From.Format("January 02 (Monday):"))
		for _, w := range forecasts[mk[i]] {
			wStr = fmt.Sprintf(" %s %s    \U0001f321 %d%s    \u2602  %.1fmm", w.PeriodName(), icons[w.Symbol.Name], w.Temperature.Value, "\u2103", w.Precipitation.Value)
			wStr = fmt.Sprintf("%s    \U0001f32C  %.1f m/s %s", wStr, w.WindSpeed.Mps, windIcons[w.WindDirection.Code])
			fmt.Println(wStr)
		}
		fmt.Println("")
	}
}

func loadConfig() (Configuration, error) {
	configuration := Configuration{}

	usr, err := user.Current()
	if err != nil {
		return configuration, err
	}

	cfile := path.Join(usr.HomeDir, ".woozy")

	file, err := os.Open(cfile)
	if err != nil {
		fmt.Println(fmt.Sprintf("Configuration file not found, creating a example in %s..", cfile))
		out, err := os.Create(cfile)
		if err != nil {
			panic(err)
		}
		defer out.Close()
		configuration.Place = "Sweden/Västerbotten/Estersmark"
		configuration.Days = 3
		configjson, err := json.MarshalIndent(configuration, "", "\t")
		ioutil.WriteFile(cfile, configjson, 0600)
		fmt.Println(".. edit it and restart woozy")
		os.Exit(1)
	}

	decoder := json.NewDecoder(file)

	err = decoder.Decode(&configuration)

	if err != nil {
		return configuration, err
	}

	return configuration, nil

}

func main() {
	configuration, err := loadConfig()

	if err != nil {
		panic(err)
	}

	cc := flag.Bool("cache-clear", false, "Force cache clear")
	days := flag.Int("days", 3, "Number of days to print")
	flag.Parse()

	wd, err := weatherdata.LoadWeatherData(configuration.Place, *cc)
	if err != nil {
		panic(err)
	}

	if configuration.Days == 0 {
		configuration.Days = *days
	}

	printHeader(wd)
	printForecast(wd, configuration.Days)
	printFooter(wd)

}
<commit_msg>A little cleanup<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path"
	"sort"

	"github.com/gummiboll/woozy/weatherdata"
)

// Configuration for woozy
type Configuration struct {
	Place string `json:"place"`
	Days  int    `json:"days"`
}

var (
	icons = map[string]string{
		"Rain":                           "\U0001f327",
		"Snow":                           "\U0001f328",
		"Rain and thunder":               "\u26C8",
		"Light rain":                     "\U0001f326",
		"Light snow":                     "\U0001f328",
		"Light rain and thunder":         "\u26C8",
		"Light rain showers":             "\U0001f326",
		"Light rain showers and thunder": "\u26C8",
		"Light snow showers":             "\U0001f328",
		"Heavy rain":                     "\U0001f327",
		"Heavy rain and thunder":         "\u26C8",
		"Heavy snow":                     "\U0001f328",
		"Rain showers":                   "\U0001f326",
		"Rain showers and thunder":       "\u26C8",
		"Snow showers":                   "\U0001f328",
		"Clear sky":                      "\u263C",
		"Cloudy":                         "\u2601",
		"Partly cloudy":                  "\u26C5",
		"Fair":                           "\u26C5",
	}

	windIcons = map[string]string{
		"N":   "\u2193",
		"S":   "\u2191",
		"E":   "\u2190",
		"W":   "\u2192",
		"NE":  "\u2199",
		"NNE": "\u2199",
		"NEE": "\u2199",
		"ENE": "\u2199",
		"NW":  "\u2198",
		"NNW": "\u2198",
		"NWW": "\u2198",
		"WNW": "\u2198",
		"SE":  "\u2196",
		"SEE": "\u2196",
		"SSE": "\u2196",
		"ESE": "\u2196",
		"SW":  "\u2197",
		"SSW": "\u2197",
		"SWW": "\u2197",
		"WSW": "\u2197",
	}
)

func printHeader(wd weatherdata.WeatherData) {
	hStr := fmt.Sprintf("%s / %s", wd.Location.Country, wd.Location.Name)
	hStr = fmt.Sprintf("%s | %s %s %s %s %s (%.1f hours)\n", hStr, icons["Clear sky"], windIcons["S"], wd.Sun.Rise.Local().Format("15:04"), windIcons["N"], wd.Sun.Set.Local().Format("15:04"), wd.SunHours())
	fmt.Println(hStr)
}

func printFooter(wd weatherdata.WeatherData) {
	fmt.Println(fmt.Sprintf("Forecast issued %.1f hours ago, next update in %.1f hours", wd.Meta.HoursSinceUpdate(), wd.Meta.HoursToNextUpdate()))
	fmt.Println(fmt.Sprintf("\n%s.\n%s", wd.Credit.Text, wd.Credit.URL))
}

func printForecast(wd weatherdata.WeatherData, days int) {
	forecasts := make(map[string][]weatherdata.WeatherForecast)
	for i := range wd.Forecast {
		// Should maybe be typecasted to int?
		forecasts[wd.Forecast[i].From.Format("20060102")] = append(forecasts[wd.Forecast[i].From.Format("20060102")], wd.Forecast[i])
	}

	mk := make([]string, len(forecasts))
	i := 0
	for k := range forecasts {
		mk[i] = k
		i++
	}

	sort.Strings(mk)

	for i := 0; i < days; i++ {
		var wStr string
		fmt.Println(forecasts[mk[i]][0].From.Format("January 02 (Monday):"))
		for _, w := range forecasts[mk[i]] {
			wStr = fmt.Sprintf(" %s %s    \U0001f321 %d%s    \u2602  %.1fmm", w.PeriodName(), icons[w.Symbol.Name], w.Temperature.Value, "\u2103", w.Precipitation.Value)
			wStr = fmt.Sprintf("%s    \U0001f32C  %.1f m/s %s", wStr, w.WindSpeed.Mps, windIcons[w.WindDirection.Code])
			fmt.Println(wStr)
		}
		fmt.Println("")
	}
}

func getConfigurationFileName() (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}

	cfile := path.Join(usr.HomeDir, ".woozy")
	return cfile, nil
}

func createDefaultConfiguration(cfile string, cnf Configuration) (error) {
	fmt.Println(fmt.Sprintf("Configuration file not found, creating a example in %s..", cfile))
	out, err := os.Create(cfile)
	if err != nil {
		return err
	}
	defer out.Close()
	cnf.Place = "Sweden/Västerbotten/Estersmark"
	cnf.Days = 3
	configjson, err := json.MarshalIndent(cnf, "", "\t")
	ioutil.WriteFile(cfile, configjson, 0600)
	fmt.Println(".. edit it and restart woozy")
	os.Exit(1)
	return nil
}

func loadConfig() (Configuration, error) {
	configuration := Configuration{}

	cfile, err := getConfigurationFileName()
	if err != nil {
		return configuration, err
	}

	file, err := os.Open(cfile)
	if err != nil {
		cerr := createDefaultConfiguration(cfile, configuration)
		if cerr != nil {
			return configuration, cerr
		}
	}

	decoder := json.NewDecoder(file)

	err = decoder.Decode(&configuration)

	if err != nil {
		return configuration, err
	}

	return configuration, nil

}

func main() {
	configuration, err := loadConfig()

	if err != nil {
		panic(err)
	}

	cc := flag.Bool("cache-clear", false, "Force cache clear")
	days := flag.Int("days", 3, "Number of days to print")
	flag.Parse()

	wd, err := weatherdata.LoadWeatherData(configuration.Place, *cc)
	if err != nil {
		panic(err)
	}

	if configuration.Days == 0 {
		configuration.Days = *days
	}

	printHeader(wd)
	printForecast(wd, configuration.Days)
	printFooter(wd)

}
<|endoftext|>


<commit_before>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import "regexp"

//go:generate go run tools/tldsgen/main.go
//go:generate go run tools/regexgen/main.go

const (
	letters   = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"
	iriChar   = letters + `0-9`
	pathChar  = iriChar + `.,:;/\-+_()?@&=$~!*%'"`
	endChar   = iriChar + `/\-+_@&=$~*%`
	ipv4Addr  = `(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])`
	ipv6Addr  = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr    = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri       = `[` + iriChar + `]([` + iriChar + `\-]{0,61}[` + iriChar + `])?`
	hostName  = `((` + iri + `\.)+` + gtld + `|` + ipAddr + `)`
	wellParen = `([` + pathChar + `]*(\([` + pathChar + `]*\))+)+`
	pathCont  = `(` + wellParen + `|[` + pathChar + `]*[` + endChar + `])`
	path      = `(/` + pathCont + `?)?`
	webURL    = hostName + `(:[0-9]{1,5})?` + path + `(\b|$)`
	email     = `[a-zA-Z0-9._%\-+]{1,256}@` + hostName

	commonScheme = `[a-zA-Z.\-+]+://`
	scheme       = `(\b|^)(` + commonScheme + `|` + otherScheme + `)`
	allStrict    = scheme + pathCont
	all          = allStrict + `|` + webURL + `|` + email
)

var (
	// All matches all the urls it can find
	All = regexp.MustCompile(all)
	// AllStrict matches only urls with a scheme to avoid false positives
	AllStrict = regexp.MustCompile(allStrict)
)

func init() {
	All.Longest()
	AllStrict.Longest()
}
<commit_msg>No need to limit the number of char repetitions<commit_after>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import "regexp"

//go:generate go run tools/tldsgen/main.go
//go:generate go run tools/regexgen/main.go

const (
	letters   = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"
	iriChar   = letters + `0-9`
	pathChar  = iriChar + `.,:;/\-+_()?@&=$~!*%'"`
	endChar   = iriChar + `/\-+_@&=$~*%`
	ipv4Addr  = `(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])`
	ipv6Addr  = `([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}:[0-9a-fA-F]{0,4}|:[0-9a-fA-F]{1,4})?|(:[0-9a-fA-F]{1,4}){0,2})|(:[0-9a-fA-F]{1,4}){0,3})|(:[0-9a-fA-F]{1,4}){0,4})|:(:[0-9a-fA-F]{1,4}){0,5})((:[0-9a-fA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9a-fA-F]{1,4}:){1,6}|:):[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){7}:`
	ipAddr    = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri       = `[` + iriChar + `]([` + iriChar + `\-]*[` + iriChar + `])?`
	hostName  = `((` + iri + `\.)+` + gtld + `|` + ipAddr + `)`
	wellParen = `([` + pathChar + `]*(\([` + pathChar + `]*\))+)+`
	pathCont  = `(` + wellParen + `|[` + pathChar + `]*[` + endChar + `])`
	path      = `(/` + pathCont + `?)?`
	webURL    = hostName + `(:[0-9]{1,5})?` + path + `(\b|$)`
	email     = `[a-zA-Z0-9._%\-+]+@` + hostName

	commonScheme = `[a-zA-Z.\-+]+://`
	scheme       = `(\b|^)(` + commonScheme + `|` + otherScheme + `)`
	allStrict    = scheme + pathCont
	all          = allStrict + `|` + webURL + `|` + email
)

var (
	// All matches all the urls it can find
	All = regexp.MustCompile(all)
	// AllStrict matches only urls with a scheme to avoid false positives
	AllStrict = regexp.MustCompile(allStrict)
)

func init() {
	All.Longest()
	AllStrict.Longest()
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/miclle/brandy/action"

	"github.com/codegangsta/cli"
	// "gopkg.in/fsnotify.v1"

	"github.com/miclle/brandy/logger"
)

var version = "0.0.1-dev"

const usage = `Full stack build system.

Usage: brandy COMMAND [ARGS]

The most common brandy commands are:
 generate    Generate new code (short-cut alias: "g")
 server      Start the brandy server (short-cut alias: "s")
 new         Create a new brandy application. "brandy new my_app" creates a
             new application called MyApp in "./my_app"

In addition to those, there are:
 destroy      Undo code generated with "generate" (short-cut alias: "d")

All commands can be run with -h (or --help) for more information.

More info https://github.com/miclle/brandy
`

func main() {

	app := cli.NewApp()
	app.Name = "brandy"
	app.Usage = usage
	app.Version = version
	app.Author = "Miclle Zheng"
	app.Email = "miclle.zheng@gmail.com"

	app.CommandNotFound = func(c *cli.Context, command string) {
		logger.ExitCode(99)
		logger.Die("Command %s does not exist.", command)
	}

	app.Before = startup

	app.Commands = commands()

	if err := app.Run(os.Args); err != nil {
		logger.Err(err.Error())
		os.Exit(1)
	}

	// If there was a Error message exit non-zero.
	if logger.HasErrored() {
		m := logger.Color(logger.Red, "An Error has occurred")
		logger.Msg(m)
		os.Exit(2)
	}

	// addr := fmt.Sprintf(":%d", conf.Config.Port)
	// handler := http.FileServer(http.Dir(conf.Config.Dir))
	// panic(http.ListenAndServe(addr, handler))
}

func startup(c *cli.Context) error {
	// TODO
	return nil
}

func commands() []cli.Command {
	return []cli.Command{
		{
			Name:  "about",
			Usage: "Learn about brandy",
			Action: func(c *cli.Context) {
				action.About()
			},
		},
	}
}
<commit_msg>Add commands<commit_after>package main

import (
	"os"

	"github.com/miclle/brandy/action"

	"github.com/codegangsta/cli"
	// "gopkg.in/fsnotify.v1"

	"github.com/miclle/brandy/logger"
)

var version = "0.0.1-dev"

const usage = `Full stack build system.

Usage: brandy COMMAND [ARGS]

The most common brandy commands are:
 generate    Generate new code (short-cut alias: "g")
 server      Start the brandy server (short-cut alias: "s")
 new         Create a new brandy application. "brandy new my_app" creates a
             new application called MyApp in "./my_app"

In addition to those, there are:
 destroy      Undo code generated with "generate" (short-cut alias: "d")

All commands can be run with -h (or --help) for more information.

More info https://github.com/miclle/brandy
`

func main() {

	app := cli.NewApp()
	app.Name = "brandy"
	app.Usage = usage
	app.Version = version
	app.Author = "Miclle Zheng"
	app.Email = "miclle.zheng@gmail.com"

	app.CommandNotFound = func(c *cli.Context, command string) {
		logger.ExitCode(99)
		logger.Die("Command %s does not exist.", command)
	}

	app.Before = startup

	app.Commands = commands()

	if err := app.Run(os.Args); err != nil {
		logger.Err(err.Error())
		os.Exit(1)
	}

	// If there was a Error message exit non-zero.
	if logger.HasErrored() {
		m := logger.Color(logger.Red, "An Error has occurred")
		logger.Msg(m)
		os.Exit(2)
	}

	// addr := fmt.Sprintf(":%d", conf.Config.Port)
	// handler := http.FileServer(http.Dir(conf.Config.Dir))
	// panic(http.ListenAndServe(addr, handler))
}

func startup(c *cli.Context) error {
	// TODO
	return nil
}

func commands() []cli.Command {
	return []cli.Command{
		{
			Name:  "about",
			Usage: "Learn about brandy",
			Action: func(c *cli.Context) {
				action.About()
			},
		},
		{
			Name:        "server",
			Usage:       "Start a static file server",
			Description: "Start the brandy server",
			Action: func(c *cli.Context) {
				// TODO
			},
		},
		{
			Name:  "build",
			Usage: "Build the project",
			Action: func(c *cli.Context) {
				// TODO
			},
		},
		{
			Name:  "init",
			Usage: "Initialize the configuration",
			Action: func(c *cli.Context) {
				// TODO
			},
		},
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"os"
	"path"
	"strconv"
	"strings"
	"sync"

	dockerapi "github.com/fsouza/go-dockerclient"
)

type PublishedPort struct {
	HostPort    string
	HostIP      string
	HostName    string
	ExposedPort string
	ExposedIP   string
	PortType    string
	Container   *dockerapi.Container
}

type Service struct {
	ID   string
	Name string
	// HostName string
	Port  int
	IP    string
	Tags  []string
	Attrs map[string]string
	TTL   int

	pp PublishedPort
}

func CombineTags(tagParts ...string) []string {
	tags := make([]string, 0)
	for _, element := range tagParts {
		if element != "" {
			tags = append(tags, strings.Split(element, ",")...)
		}
	}
	return tags
}

func NewService(port PublishedPort, isgroup bool) *Service {
	container := port.Container
	defaultName := strings.Split(path.Base(container.Config.Image), ":")[0]
	if isgroup {
		defaultName = defaultName + "-" + port.ExposedPort
	}

	hostname, err := os.Hostname()
	if err != nil {
		hostname = port.HostIP
	} else {
		if port.HostIP == "0.0.0.0" {
			ip, err := net.ResolveIPAddr("ip", hostname)
			if err == nil {
				port.HostIP = ip.String()
			}
		}
	}

	if *hostIp != "" {
		port.HostIP = *hostIp
	}

	metadata := serviceMetaData(container.Config.Env, port.ExposedPort)

	ignore := mapdefault(metadata, "ignore", "")
	if ignore != "" {
		return nil
	}

	service := new(Service)
	service.pp = port
	service.ID = hostname + ":" + container.Name[1:] + ":" + port.ExposedPort
	service.Name = mapdefault(metadata, "name", defaultName)
	var p int
	if *internal == true {
		service.IP = port.ExposedIP
		p, _ = strconv.Atoi(port.ExposedPort)
		// service.HostName = port.HostName
	} else {
		service.IP = port.HostIP
		p, _ = strconv.Atoi(port.HostPort)
	}
	service.Port = p

	if port.PortType == "udp" {
		service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags, "udp")
		service.ID = service.ID + ":udp"
	} else {
		service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags)
	}

	id := mapdefault(metadata, "id", "")
	if id != "" {
		service.ID = id
	}

	delete(metadata, "id")
	delete(metadata, "tags")
	delete(metadata, "name")
	service.Attrs = metadata

	service.TTL = *refreshTtl

	return service
}

func serviceMetaData(env []string, port string) map[string]string {
	metadata := make(map[string]string)
	for _, kv := range env {
		kvp := strings.SplitN(kv, "=", 2)
		if strings.HasPrefix(kvp[0], "SERVICE_") && len(kvp) > 1 {
			key := strings.ToLower(strings.TrimPrefix(kvp[0], "SERVICE_"))
			portkey := strings.SplitN(key, "_", 2)
			_, err := strconv.Atoi(portkey[0])
			if err == nil && len(portkey) > 1 {
				if portkey[0] != port {
					continue
				}
				metadata[portkey[1]] = kvp[1]
			} else {
				metadata[key] = kvp[1]
			}
		}
	}
	return metadata
}

type RegistryBridge struct {
	sync.Mutex
	docker   *dockerapi.Client
	registry ServiceRegistry
	services map[string][]*Service
}

func (b *RegistryBridge) Add(containerId string) {
	b.Lock()
	defer b.Unlock()
	container, err := b.docker.InspectContainer(containerId)
	if err != nil {
		log.Println("registrator: unable to inspect container:", containerId[:12], err)
		return
	}

	ports := make([]PublishedPort, 0)
	for port, published := range container.NetworkSettings.Ports {
		var hp, hip string
		if len(published) > 0 {
			hp = published[0].HostPort
			hip = published[0].HostIP
		}
		p := strings.Split(string(port), "/")
		ports = append(ports, PublishedPort{
			HostPort:    hp,
			HostIP:      hip,
			HostName:    container.Config.Hostname,
			ExposedPort: p[0],
			ExposedIP:   container.NetworkSettings.IPAddress,
			PortType:    p[1],
			Container:   container,
		})
		// }
	}

	for _, port := range ports {
		if *internal != true && port.HostPort == "" {
			log.Println("registrator: ignored", container.ID[:12], "port", port.ExposedPort, "not published on host")
			continue
		}
		service := NewService(port, len(ports) > 1)
		if service == nil {
			log.Println("registrator: ignored:", container.ID[:12], "service on port", port.ExposedPort)
			continue
		}
		err := retry(func() error {
			return b.registry.Register(service)
		})
		if err != nil {
			log.Println("registrator: unable to register service:", service, err)
			continue
		}
		b.services[container.ID] = append(b.services[container.ID], service)
		log.Println("registrator: added:", container.ID[:12], service.ID)
	}

	if len(b.services) == 0 {
		log.Println("registrator: ignored:", container.ID[:12], "no published ports")
	}
}

func (b *RegistryBridge) Remove(containerId string) {
	b.Lock()
	defer b.Unlock()
	for _, service := range b.services[containerId] {
		err := retry(func() error {
			return b.registry.Deregister(service)
		})
		if err != nil {
			log.Println("registrator: unable to deregister service:", service.ID, err)
			continue
		}
		log.Println("registrator: removed:", containerId[:12], service.ID)
	}
	delete(b.services, containerId)
}

func (b *RegistryBridge) Refresh() {
	b.Lock()
	defer b.Unlock()
	for containerId, services := range b.services {
		for _, service := range services {
			err := b.registry.Refresh(service)
			if err != nil {
				log.Println("registrator: unable to refresh service:", service.ID, err)
				continue
			}
			log.Println("registrator: refreshed:", containerId[:12], service.ID)
		}
	}
}
<commit_msg>Added discovery for services running with --net=host.<commit_after>package main

import (
	"log"
	"net"
	"os"
	"path"
	"strconv"
	"strings"
	"sync"

	dockerapi "github.com/fsouza/go-dockerclient"
)

type PublishedPort struct {
	HostPort    string
	HostIP      string
	HostName    string
	ExposedPort string
	ExposedIP   string
	PortType    string
	Container   *dockerapi.Container
}

type Service struct {
	ID   string
	Name string
	// HostName string
	Port  int
	IP    string
	Tags  []string
	Attrs map[string]string
	TTL   int

	pp PublishedPort
}

func CombineTags(tagParts ...string) []string {
	tags := make([]string, 0)
	for _, element := range tagParts {
		if element != "" {
			tags = append(tags, strings.Split(element, ",")...)
		}
	}
	return tags
}

func NewService(port PublishedPort, isgroup bool) *Service {
	container := port.Container
	defaultName := strings.Split(path.Base(container.Config.Image), ":")[0]
	if isgroup {
		defaultName = defaultName + "-" + port.ExposedPort
	}

	hostname, err := os.Hostname()
	if err != nil {
		hostname = port.HostIP
	} else {
		if port.HostIP == "0.0.0.0" {
			ip, err := net.ResolveIPAddr("ip", hostname)
			if err == nil {
				port.HostIP = ip.String()
			}
		}
	}

	if *hostIp != "" {
		port.HostIP = *hostIp
	}

	metadata := serviceMetaData(container.Config.Env, port.ExposedPort)

	ignore := mapdefault(metadata, "ignore", "")
	if ignore != "" {
		return nil
	}

	service := new(Service)
	service.pp = port
	service.ID = hostname + ":" + container.Name[1:] + ":" + port.ExposedPort
	service.Name = mapdefault(metadata, "name", defaultName)
	var p int
	if *internal == true {
		service.IP = port.ExposedIP
		p, _ = strconv.Atoi(port.ExposedPort)
		// service.HostName = port.HostName
	} else {
		service.IP = port.HostIP
		p, _ = strconv.Atoi(port.HostPort)
	}
	service.Port = p

	if port.PortType == "udp" {
		service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags, "udp")
		service.ID = service.ID + ":udp"
	} else {
		service.Tags = CombineTags(mapdefault(metadata, "tags", ""), *forceTags)
	}

	id := mapdefault(metadata, "id", "")
	if id != "" {
		service.ID = id
	}

	delete(metadata, "id")
	delete(metadata, "tags")
	delete(metadata, "name")
	service.Attrs = metadata

	service.TTL = *refreshTtl

	return service
}

func serviceMetaData(env []string, port string) map[string]string {
	metadata := make(map[string]string)
	for _, kv := range env {
		kvp := strings.SplitN(kv, "=", 2)
		if strings.HasPrefix(kvp[0], "SERVICE_") && len(kvp) > 1 {
			key := strings.ToLower(strings.TrimPrefix(kvp[0], "SERVICE_"))
			portkey := strings.SplitN(key, "_", 2)
			_, err := strconv.Atoi(portkey[0])
			if err == nil && len(portkey) > 1 {
				if portkey[0] != port {
					continue
				}
				metadata[portkey[1]] = kvp[1]
			} else {
				metadata[key] = kvp[1]
			}
		}
	}
	return metadata
}

type RegistryBridge struct {
	sync.Mutex
	docker   *dockerapi.Client
	registry ServiceRegistry
	services map[string][]*Service
}

func MakePublishedPort(container *dockerapi.Container, port dockerapi.Port, published []dockerapi.PortBinding) PublishedPort {
	var hp, hip string
	if len(published) > 0 {
		hp = published[0].HostPort
		hip = published[0].HostIP
	}
	if (hip == "") {
		hip = "0.0.0.0"
	}
	p := strings.Split(string(port), "/")
	return PublishedPort{
		HostPort:    hp,
		HostIP:      hip,
		HostName:    container.Config.Hostname,
		ExposedPort: p[0],
		ExposedIP:   container.NetworkSettings.IPAddress,
		PortType:    p[1],
		Container:   container,
	}
}

func (b *RegistryBridge) Add(containerId string) {
	b.Lock()
	defer b.Unlock()
	container, err := b.docker.InspectContainer(containerId)
	if err != nil {
		log.Println("registrator: unable to inspect container:", containerId[:12], err)
		return
	}

	ports := make(map[string]PublishedPort)

	// Extract configured host port mappings, relevant when using --net=host
	for port, published := range container.HostConfig.PortBindings {
		ports[string(port)] = MakePublishedPort(container, port, published)
	}

	// Extract runtime port mappings, relevant when using e.g. --net=bridge
	for port, published := range container.NetworkSettings.Ports {
		ports[string(port)] = MakePublishedPort(container, port, published)
	}

	for _, port := range ports {
		if *internal != true && port.HostPort == "" {
			log.Println("registrator: ignored", container.ID[:12], "port", port.ExposedPort, "not published on host")
			continue
		}
		service := NewService(port, len(ports) > 1)
		if service == nil {
			log.Println("registrator: ignored:", container.ID[:12], "service on port", port.ExposedPort)
			continue
		}
		err := retry(func() error {
			return b.registry.Register(service)
		})
		if err != nil {
			log.Println("registrator: unable to register service:", service, err)
			continue
		}
		b.services[container.ID] = append(b.services[container.ID], service)
		log.Println("registrator: added:", container.ID[:12], service.ID)
	}

	if len(b.services[container.ID]) == 0 {
		log.Println("registrator: ignored:", container.ID[:12], "no published ports")
	}
}

func (b *RegistryBridge) Remove(containerId string) {
	b.Lock()
	defer b.Unlock()
	for _, service := range b.services[containerId] {
		err := retry(func() error {
			return b.registry.Deregister(service)
		})
		if err != nil {
			log.Println("registrator: unable to deregister service:", service.ID, err)
			continue
		}
		log.Println("registrator: removed:", containerId[:12], service.ID)
	}
	delete(b.services, containerId)
}

func (b *RegistryBridge) Refresh() {
	b.Lock()
	defer b.Unlock()
	for containerId, services := range b.services {
		for _, service := range services {
			err := b.registry.Refresh(service)
			if err != nil {
				log.Println("registrator: unable to refresh service:", service.ID, err)
				continue
			}
			log.Println("registrator: refreshed:", containerId[:12], service.ID)
		}
	}
}
<|endoftext|>