<commit_before>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.6"
const TimeLayout = "Jan 2, 2006 at 3:04pm (MST)"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)
			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<commit_msg>Version bump to 2.5.7<commit_after>// EVH is designed to be a single-use file transfer system.  Its purpose is to replace
// aging methods of sharing files such as FTP.  With the advent of services like
// DropBox, Box, Google Drive and the like, this type of service is becoming more
// commonplace EVH has some differentiating features that make it an especially
// good tool for corporations and/or home use.
//
// EVH runs in two modes: server and client.  Server hosts a web server interface for
// uploading and downloading files.  The Client is for uploading only and runs
// in a terminal.  This app is designed to run on all platforms that Go supports.
package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"os"
)

// Flags
var ConfigFileFlag string
var DstEmailFlag string
var ExpirationFlag string
var FileDescrFlag string
var FilesFieldFlag string
var ProgressFlag bool
var ServerFlag bool
var SrcEmailFlag string
var UrlFlag string
var Evh1ImportFlag bool
var ProxyUrlFlag string

// Global Variables
var UploadUrlPath = "/upload/"
var DownloadUrlPath = "/download/"
var AdminUrlPath = "/admin/"
var Files []string
var HttpProto = "http"
var SiteDown bool
var Templates *template.Template

// Constants
const VERSION = "2.5.7"
const TimeLayout = "Jan 2, 2006 at 3:04pm (MST)"

func init() {
	flag.StringVar(&ConfigFileFlag, "c", "", "Location of the Configuration file")
	flag.BoolVar(&ServerFlag, "server", false, "Listen for incoming file uploads")

	// Client flags
	flag.StringVar(&UrlFlag, "url", "", "Remote server URL to send files to (client only)")
	flag.StringVar(&FilesFieldFlag, "field", "", "Field name of the form (client only)")
	flag.StringVar(&SrcEmailFlag, "from", "", "Email address of uploader (client only)")
	flag.StringVar(&DstEmailFlag, "to", "", "Comma separated set of email address(es) of file recipient(s) (client only)")
	flag.StringVar(&FileDescrFlag, "description", "", "File desription (use quotes) (client only)")
	flag.BoolVar(&ProgressFlag, "progress", true, "Show progress bar during upload (client only)")
	flag.StringVar(&ExpirationFlag, "expires", "", "Example 1:d for 1 day (client only)")
	flag.BoolVar(&Evh1ImportFlag, "import", false, "Import data from EVH1 instance (client only)")
	flag.StringVar(&ProxyUrlFlag, "proxy", "", "URL/Address for proxy (env=use environment proxy, other=use as defined")
}

func main() {
	flag.Parse()

	// Load in our Config
	Config = NewConfig(ConfigFileFlag)
	Config.ImportFlags()

	if ServerFlag {
		// Final sanity check
		if Config.Server.Assets == "" {
			log.Fatal("ERROR: Cannot continue without specifying assets path")
		}
		if Config.Server.Templates == "" {
			log.Fatal("ERROR: Cannot continue without specifying templates path")
		}
		if Config.Server.ListenAddr == "" {
			log.Fatal("ERROR: Cannot continue without specifying listenaddr value")
		}
		if Config.Server.Mailserver == "" {
			log.Println("WARNING: cannot send emails, mailserver not set")
		}

		// Set so all generated URLs use https if enabled
		if Config.Server.Ssl {
			HttpProto = "https"
		}

		// Setup our assets dir (if it don't already exist)
		err := os.MkdirAll(Config.Server.Assets, 0700)
		if err != nil {
			log.Fatal("Cannot setup assetdir as needed: " + err.Error())
		}

		// Parse our html templates
		go RefreshTemplates()
		go ScrubDownloads()

		// Register our handler functions
		http.HandleFunc(UploadUrlPath, SSLCheck(UploadHandler))
		http.HandleFunc(DownloadUrlPath, SSLCheck(AssetHandler))
		http.HandleFunc(AdminUrlPath, BasicAuth(SSLCheck(AdminHandler)))
		http.HandleFunc("/", Evh1Intercept(SSLCheck(HomeHandler)))

		// Listen
		log.Println("Listening...")

		// Spawn HTTPS listener in another thread
		go func() {
			if Config.Server.Ssl == false || Config.Server.SslPort == "" {
				return
			}
			var addrSsl = Config.Server.ListenAddr + ":" + Config.Server.SslPort
			listenErrSsl := http.ListenAndServeTLS(addrSsl, Config.Server.CertFile, Config.Server.KeyFile, nil)
			if listenErrSsl != nil {
				log.Fatal("ERROR: ssl listen problem: " + listenErrSsl.Error())
			}
		}()

		// Start non-SSL listener
		var addrNonSsl = Config.Server.ListenAddr + ":" + Config.Server.NonSslPort
		listenErr := http.ListenAndServe(addrNonSsl, nil)
		if listenErr != nil {
			log.Fatal("ERROR: non-ssl listen problem: " + listenErr.Error())
		}
	} else {
		// Run import if requested
		if Evh1ImportFlag {
			SpitSlurp()
			return
		}

		// Final sanity check
		if Config.Client.DestEmail == "" {
			log.Println("WARNING: no -destemail value set, cannot send reciever an email")
		}
		if Config.Client.Email == "" {
			log.Println("WARNING: no -email value set, cannot send email to uploader")
		}
		if Config.Client.Field == "" {
			log.Println("WARNING: no -field value set, using \"file\" instead")
			Config.Client.Field = "file"
		}
		if Config.Client.Url == "" {
			log.Fatal("ERROR: Cannot continue without specifying -url value")
		}

		// All filenames are unflagged arguments, loop through them and uplod the file(s)
		for _, fname := range flag.Args() {
			fi, err := os.Stat(fname)
			if err != nil {
				log.Println("WARNING: Cannot read file, skipping ", fname, ": ", err.Error())
			} else {
				if fi.Mode().IsRegular() {
					Files = append(Files, fname)
				}
			}
		}

		Upload(Files)
	}
}
<|endoftext|>


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

// Package types declares the data types and implements
// the algorithms for type-checking of Go packages. Use
// Config.Check to invoke the type checker for a package.
// Alternatively, create a new type checked with NewChecker
// and invoke it incrementally by calling Checker.Files.
//
// Type-checking consists of several interdependent phases:
//
// Name resolution maps each identifier (ast.Ident) in the program to the
// language object (Object) it denotes.
// Use Info.{Defs,Uses,Implicits} for the results of name resolution.
//
// Constant folding computes the exact constant value (exact.Value) for
// every expression (ast.Expr) that is a compile-time constant.
// Use Info.Types[expr].Value for the results of constant folding.
//
// Type inference computes the type (Type) of every expression (ast.Expr)
// and checks for compliance with the language specification.
// Use Info.Types[expr].Type for the results of type inference.
//
package types // import "go/types"

import (
	"bytes"
	"fmt"
	"go/ast"
	exact "go/constant" // Renamed to reduce diffs from x/tools.  TODO: remove
	"go/token"
)

// An Error describes a type-checking error; it implements the error interface.
// A "soft" error is an error that still permits a valid interpretation of a
// package (such as "unused variable"); "hard" errors may lead to unpredictable
// behavior if ignored.
type Error struct {
	Fset *token.FileSet // file set for interpretation of Pos
	Pos  token.Pos      // error position
	Msg  string         // error message
	Soft bool           // if set, error is "soft"
}

// Error returns an error string formatted as follows:
// filename:line:column: message
func (err Error) Error() string {
	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
}

// An importer resolves import paths to Packages.
// See go/importer for existing implementations.
type Importer interface {
	// Import returns the imported package for the given import
	// path, or an error if the package couldn't be imported.
	// Import is responsible for returning the same package for
	// matching import paths.
	Import(path string) (*Package, error)
}

// A Config specifies the configuration for type checking.
// The zero value for Config is a ready-to-use default configuration.
type Config struct {
	// If IgnoreFuncBodies is set, function bodies are not
	// type-checked.
	IgnoreFuncBodies bool

	// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
	// declares an empty "C" package and errors are omitted for qualified
	// identifiers referring to package C (which won't find an object).
	// This feature is intended for the standard library cmd/api tool.
	//
	// Caution: Effects may be unpredictable due to follow-up errors.
	//          Do not use casually!
	FakeImportC bool

	// If Error != nil, it is called with each error found
	// during type checking; err has dynamic type Error.
	// Secondary errors (for instance, to enumerate all types
	// involved in an invalid recursive type declaration) have
	// error strings that start with a '\t' character.
	// If Error == nil, type-checking stops with the first
	// error found.
	Error func(err error)

	// Importer is called for each import declaration except when
	// importing package "unsafe". An error is reported if an
	// importer is needed but none was installed.
	Importer Importer

	// If Sizes != nil, it provides the sizing functions for package unsafe.
	// Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead.
	Sizes Sizes

	// If DisableUnusedImportCheck is set, packages are not checked
	// for unused imports.
	DisableUnusedImportCheck bool
}

// Info holds result type information for a type-checked package.
// Only the information for which a map is provided is collected.
// If the package has type errors, the collected information may
// be incomplete.
type Info struct {
	// Types maps expressions to their types, and for constant
	// expressions, their values. Invalid expressions are omitted.
	//
	// For (possibly parenthesized) identifiers denoting built-in
	// functions, the recorded signatures are call-site specific:
	// if the call result is not a constant, the recorded type is
	// an argument-specific signature. Otherwise, the recorded type
	// is invalid.
	//
	// Identifiers on the lhs of declarations (i.e., the identifiers
	// which are being declared) are collected in the Defs map.
	// Identifiers denoting packages are collected in the Uses maps.
	Types map[ast.Expr]TypeAndValue

	// Defs maps identifiers to the objects they define (including
	// package names, dots "." of dot-imports, and blank "_" identifiers).
	// For identifiers that do not denote objects (e.g., the package name
	// in package clauses, or symbolic variables t in t := x.(type) of
	// type switch headers), the corresponding objects are nil.
	//
	// For an anonymous field, Defs returns the field *Var it defines.
	//
	// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
	Defs map[*ast.Ident]Object

	// Uses maps identifiers to the objects they denote.
	//
	// For an anonymous field, Uses returns the *TypeName it denotes.
	//
	// Invariant: Uses[id].Pos() != id.Pos()
	Uses map[*ast.Ident]Object

	// Implicits maps nodes to their implicitly declared objects, if any.
	// The following node and object types may appear:
	//
	//	node               declared object
	//
	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
	//      *ast.Field         anonymous struct field or parameter *Var
	//
	Implicits map[ast.Node]Object

	// Selections maps selector expressions (excluding qualified identifiers)
	// to their corresponding selections.
	Selections map[*ast.SelectorExpr]*Selection

	// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
	// associated with a specific node but with all files belonging to a package.
	// Thus, the package scope can be found in the type-checked Package object.
	// Scopes nest, with the Universe scope being the outermost scope, enclosing
	// the package scope, which contains (one or more) files scopes, which enclose
	// function scopes which in turn enclose statement and function literal scopes.
	// Note that even though package-level functions are declared in the package
	// scope, the function scopes are embedded in the file scope of the file
	// containing the function declaration.
	//
	// The following node types may appear in Scopes:
	//
	//	*ast.File
	//	*ast.FuncType
	//	*ast.BlockStmt
	//	*ast.IfStmt
	//	*ast.SwitchStmt
	//	*ast.TypeSwitchStmt
	//	*ast.CaseClause
	//	*ast.CommClause
	//	*ast.ForStmt
	//	*ast.RangeStmt
	//
	Scopes map[ast.Node]*Scope

	// InitOrder is the list of package-level initializers in the order in which
	// they must be executed. Initializers referring to variables related by an
	// initialization dependency appear in topological order, the others appear
	// in source order. Variables without an initialization expression do not
	// appear in this list.
	InitOrder []*Initializer
}

// TypeOf returns the type of expression e, or nil if not found.
// Precondition: the Types, Uses and Defs maps are populated.
//
func (info *Info) TypeOf(e ast.Expr) Type {
	if t, ok := info.Types[e]; ok {
		return t.Type
	}
	if id, _ := e.(*ast.Ident); id != nil {
		if obj := info.ObjectOf(id); obj != nil {
			return obj.Type()
		}
	}
	return nil
}

// ObjectOf returns the object denoted by the specified id,
// or nil if not found.
//
// If id is an anonymous struct field, ObjectOf returns the field (*Var)
// it uses, not the type (*TypeName) it defines.
//
// Precondition: the Uses and Defs maps are populated.
//
func (info *Info) ObjectOf(id *ast.Ident) Object {
	if obj, _ := info.Defs[id]; obj != nil {
		return obj
	}
	return info.Uses[id]
}

// TypeAndValue reports the type and value (for constants)
// of the corresponding expression.
type TypeAndValue struct {
	mode  operandMode
	Type  Type
	Value exact.Value
}

// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
// "void" values as regular values but with the empty tuple type.

// IsVoid reports whether the corresponding expression
// is a function call without results.
func (tv TypeAndValue) IsVoid() bool {
	return tv.mode == novalue
}

// IsType reports whether the corresponding expression specifies a type.
func (tv TypeAndValue) IsType() bool {
	return tv.mode == typexpr
}

// IsBuiltin reports whether the corresponding expression denotes
// a (possibly parenthesized) built-in function.
func (tv TypeAndValue) IsBuiltin() bool {
	return tv.mode == builtin
}

// IsValue reports whether the corresponding expression is a value.
// Builtins are not considered values. Constant values have a non-
// nil Value.
func (tv TypeAndValue) IsValue() bool {
	switch tv.mode {
	case constant, variable, mapindex, value, commaok:
		return true
	}
	return false
}

// IsNil reports whether the corresponding expression denotes the
// predeclared value nil.
func (tv TypeAndValue) IsNil() bool {
	return tv.mode == value && tv.Type == Typ[UntypedNil]
}

// Addressable reports whether the corresponding expression
// is addressable (https://golang.org/ref/spec#Address_operators).
func (tv TypeAndValue) Addressable() bool {
	return tv.mode == variable
}

// Assignable reports whether the corresponding expression
// is assignable to (provided a value of the right type).
func (tv TypeAndValue) Assignable() bool {
	return tv.mode == variable || tv.mode == mapindex
}

// HasOk reports whether the corresponding expression may be
// used on the lhs of a comma-ok assignment.
func (tv TypeAndValue) HasOk() bool {
	return tv.mode == commaok || tv.mode == mapindex
}

// An Initializer describes a package-level variable, or a list of variables in case
// of a multi-valued initialization expression, and the corresponding initialization
// expression.
type Initializer struct {
	Lhs []*Var // var Lhs = Rhs
	Rhs ast.Expr
}

func (init *Initializer) String() string {
	var buf bytes.Buffer
	for i, lhs := range init.Lhs {
		if i > 0 {
			buf.WriteString(", ")
		}
		buf.WriteString(lhs.Name())
	}
	buf.WriteString(" = ")
	WriteExpr(&buf, init.Rhs)
	return buf.String()
}

// Check type-checks a package and returns the resulting package object,
// the first error if any, and if info != nil, additional type information.
// The package is marked as complete if no errors occurred, otherwise it is
// incomplete. See Config.Error for controlling behavior in the presence of
// errors.
//
// The package is specified by a list of *ast.Files and corresponding
// file set, and the package path the package is identified with.
// The clean path must not be empty or dot (".").
func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
	pkg := NewPackage(path, "")
	return pkg, NewChecker(conf, fset, pkg, info).Files(files)
}

// AssertableTo reports whether a value of type V can be asserted to have type T.
func AssertableTo(V *Interface, T Type) bool {
	m, _ := assertableTo(V, T)
	return m == nil
}

// AssignableTo reports whether a value of type V is assignable to a variable of type T.
func AssignableTo(V, T Type) bool {
	x := operand{mode: value, typ: V}
	return x.assignableTo(nil, T) // config not needed for non-constant x
}

// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
func ConvertibleTo(V, T Type) bool {
	x := operand{mode: value, typ: V}
	return x.convertibleTo(nil, T) // config not needed for non-constant x
}

// Implements reports whether type V implements interface T.
func Implements(V Type, T *Interface) bool {
	f, _ := MissingMethod(V, T, true)
	return f == nil
}
<commit_msg>go/types: update comment to refer to package go/constant<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package types declares the data types and implements
// the algorithms for type-checking of Go packages. Use
// Config.Check to invoke the type checker for a package.
// Alternatively, create a new type checked with NewChecker
// and invoke it incrementally by calling Checker.Files.
//
// Type-checking consists of several interdependent phases:
//
// Name resolution maps each identifier (ast.Ident) in the program to the
// language object (Object) it denotes.
// Use Info.{Defs,Uses,Implicits} for the results of name resolution.
//
// Constant folding computes the exact constant value (constant.Value)
// for every expression (ast.Expr) that is a compile-time constant.
// Use Info.Types[expr].Value for the results of constant folding.
//
// Type inference computes the type (Type) of every expression (ast.Expr)
// and checks for compliance with the language specification.
// Use Info.Types[expr].Type for the results of type inference.
//
package types // import "go/types"

import (
	"bytes"
	"fmt"
	"go/ast"
	exact "go/constant" // Renamed to reduce diffs from x/tools.  TODO: remove
	"go/token"
)

// An Error describes a type-checking error; it implements the error interface.
// A "soft" error is an error that still permits a valid interpretation of a
// package (such as "unused variable"); "hard" errors may lead to unpredictable
// behavior if ignored.
type Error struct {
	Fset *token.FileSet // file set for interpretation of Pos
	Pos  token.Pos      // error position
	Msg  string         // error message
	Soft bool           // if set, error is "soft"
}

// Error returns an error string formatted as follows:
// filename:line:column: message
func (err Error) Error() string {
	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
}

// An importer resolves import paths to Packages.
// See go/importer for existing implementations.
type Importer interface {
	// Import returns the imported package for the given import
	// path, or an error if the package couldn't be imported.
	// Import is responsible for returning the same package for
	// matching import paths.
	Import(path string) (*Package, error)
}

// A Config specifies the configuration for type checking.
// The zero value for Config is a ready-to-use default configuration.
type Config struct {
	// If IgnoreFuncBodies is set, function bodies are not
	// type-checked.
	IgnoreFuncBodies bool

	// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
	// declares an empty "C" package and errors are omitted for qualified
	// identifiers referring to package C (which won't find an object).
	// This feature is intended for the standard library cmd/api tool.
	//
	// Caution: Effects may be unpredictable due to follow-up errors.
	//          Do not use casually!
	FakeImportC bool

	// If Error != nil, it is called with each error found
	// during type checking; err has dynamic type Error.
	// Secondary errors (for instance, to enumerate all types
	// involved in an invalid recursive type declaration) have
	// error strings that start with a '\t' character.
	// If Error == nil, type-checking stops with the first
	// error found.
	Error func(err error)

	// Importer is called for each import declaration except when
	// importing package "unsafe". An error is reported if an
	// importer is needed but none was installed.
	Importer Importer

	// If Sizes != nil, it provides the sizing functions for package unsafe.
	// Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead.
	Sizes Sizes

	// If DisableUnusedImportCheck is set, packages are not checked
	// for unused imports.
	DisableUnusedImportCheck bool
}

// Info holds result type information for a type-checked package.
// Only the information for which a map is provided is collected.
// If the package has type errors, the collected information may
// be incomplete.
type Info struct {
	// Types maps expressions to their types, and for constant
	// expressions, their values. Invalid expressions are omitted.
	//
	// For (possibly parenthesized) identifiers denoting built-in
	// functions, the recorded signatures are call-site specific:
	// if the call result is not a constant, the recorded type is
	// an argument-specific signature. Otherwise, the recorded type
	// is invalid.
	//
	// Identifiers on the lhs of declarations (i.e., the identifiers
	// which are being declared) are collected in the Defs map.
	// Identifiers denoting packages are collected in the Uses maps.
	Types map[ast.Expr]TypeAndValue

	// Defs maps identifiers to the objects they define (including
	// package names, dots "." of dot-imports, and blank "_" identifiers).
	// For identifiers that do not denote objects (e.g., the package name
	// in package clauses, or symbolic variables t in t := x.(type) of
	// type switch headers), the corresponding objects are nil.
	//
	// For an anonymous field, Defs returns the field *Var it defines.
	//
	// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
	Defs map[*ast.Ident]Object

	// Uses maps identifiers to the objects they denote.
	//
	// For an anonymous field, Uses returns the *TypeName it denotes.
	//
	// Invariant: Uses[id].Pos() != id.Pos()
	Uses map[*ast.Ident]Object

	// Implicits maps nodes to their implicitly declared objects, if any.
	// The following node and object types may appear:
	//
	//	node               declared object
	//
	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
	//      *ast.Field         anonymous struct field or parameter *Var
	//
	Implicits map[ast.Node]Object

	// Selections maps selector expressions (excluding qualified identifiers)
	// to their corresponding selections.
	Selections map[*ast.SelectorExpr]*Selection

	// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
	// associated with a specific node but with all files belonging to a package.
	// Thus, the package scope can be found in the type-checked Package object.
	// Scopes nest, with the Universe scope being the outermost scope, enclosing
	// the package scope, which contains (one or more) files scopes, which enclose
	// function scopes which in turn enclose statement and function literal scopes.
	// Note that even though package-level functions are declared in the package
	// scope, the function scopes are embedded in the file scope of the file
	// containing the function declaration.
	//
	// The following node types may appear in Scopes:
	//
	//	*ast.File
	//	*ast.FuncType
	//	*ast.BlockStmt
	//	*ast.IfStmt
	//	*ast.SwitchStmt
	//	*ast.TypeSwitchStmt
	//	*ast.CaseClause
	//	*ast.CommClause
	//	*ast.ForStmt
	//	*ast.RangeStmt
	//
	Scopes map[ast.Node]*Scope

	// InitOrder is the list of package-level initializers in the order in which
	// they must be executed. Initializers referring to variables related by an
	// initialization dependency appear in topological order, the others appear
	// in source order. Variables without an initialization expression do not
	// appear in this list.
	InitOrder []*Initializer
}

// TypeOf returns the type of expression e, or nil if not found.
// Precondition: the Types, Uses and Defs maps are populated.
//
func (info *Info) TypeOf(e ast.Expr) Type {
	if t, ok := info.Types[e]; ok {
		return t.Type
	}
	if id, _ := e.(*ast.Ident); id != nil {
		if obj := info.ObjectOf(id); obj != nil {
			return obj.Type()
		}
	}
	return nil
}

// ObjectOf returns the object denoted by the specified id,
// or nil if not found.
//
// If id is an anonymous struct field, ObjectOf returns the field (*Var)
// it uses, not the type (*TypeName) it defines.
//
// Precondition: the Uses and Defs maps are populated.
//
func (info *Info) ObjectOf(id *ast.Ident) Object {
	if obj, _ := info.Defs[id]; obj != nil {
		return obj
	}
	return info.Uses[id]
}

// TypeAndValue reports the type and value (for constants)
// of the corresponding expression.
type TypeAndValue struct {
	mode  operandMode
	Type  Type
	Value exact.Value // == constant.Value
}

// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
// "void" values as regular values but with the empty tuple type.

// IsVoid reports whether the corresponding expression
// is a function call without results.
func (tv TypeAndValue) IsVoid() bool {
	return tv.mode == novalue
}

// IsType reports whether the corresponding expression specifies a type.
func (tv TypeAndValue) IsType() bool {
	return tv.mode == typexpr
}

// IsBuiltin reports whether the corresponding expression denotes
// a (possibly parenthesized) built-in function.
func (tv TypeAndValue) IsBuiltin() bool {
	return tv.mode == builtin
}

// IsValue reports whether the corresponding expression is a value.
// Builtins are not considered values. Constant values have a non-
// nil Value.
func (tv TypeAndValue) IsValue() bool {
	switch tv.mode {
	case constant, variable, mapindex, value, commaok:
		return true
	}
	return false
}

// IsNil reports whether the corresponding expression denotes the
// predeclared value nil.
func (tv TypeAndValue) IsNil() bool {
	return tv.mode == value && tv.Type == Typ[UntypedNil]
}

// Addressable reports whether the corresponding expression
// is addressable (https://golang.org/ref/spec#Address_operators).
func (tv TypeAndValue) Addressable() bool {
	return tv.mode == variable
}

// Assignable reports whether the corresponding expression
// is assignable to (provided a value of the right type).
func (tv TypeAndValue) Assignable() bool {
	return tv.mode == variable || tv.mode == mapindex
}

// HasOk reports whether the corresponding expression may be
// used on the lhs of a comma-ok assignment.
func (tv TypeAndValue) HasOk() bool {
	return tv.mode == commaok || tv.mode == mapindex
}

// An Initializer describes a package-level variable, or a list of variables in case
// of a multi-valued initialization expression, and the corresponding initialization
// expression.
type Initializer struct {
	Lhs []*Var // var Lhs = Rhs
	Rhs ast.Expr
}

func (init *Initializer) String() string {
	var buf bytes.Buffer
	for i, lhs := range init.Lhs {
		if i > 0 {
			buf.WriteString(", ")
		}
		buf.WriteString(lhs.Name())
	}
	buf.WriteString(" = ")
	WriteExpr(&buf, init.Rhs)
	return buf.String()
}

// Check type-checks a package and returns the resulting package object,
// the first error if any, and if info != nil, additional type information.
// The package is marked as complete if no errors occurred, otherwise it is
// incomplete. See Config.Error for controlling behavior in the presence of
// errors.
//
// The package is specified by a list of *ast.Files and corresponding
// file set, and the package path the package is identified with.
// The clean path must not be empty or dot (".").
func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
	pkg := NewPackage(path, "")
	return pkg, NewChecker(conf, fset, pkg, info).Files(files)
}

// AssertableTo reports whether a value of type V can be asserted to have type T.
func AssertableTo(V *Interface, T Type) bool {
	m, _ := assertableTo(V, T)
	return m == nil
}

// AssignableTo reports whether a value of type V is assignable to a variable of type T.
func AssignableTo(V, T Type) bool {
	x := operand{mode: value, typ: V}
	return x.assignableTo(nil, T) // config not needed for non-constant x
}

// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
func ConvertibleTo(V, T Type) bool {
	x := operand{mode: value, typ: V}
	return x.convertibleTo(nil, T) // config not needed for non-constant x
}

// Implements reports whether type V implements interface T.
func Implements(V Type, T *Interface) bool {
	f, _ := MissingMethod(V, T, true)
	return f == nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"log"
	"os"
	"time"
	"http"
	"flag"
)

type DaemonLogger struct {
	stdoutLog *log.Logger
	fileLog   *log.Logger
	error     int
	name      string
}

var debug bool

func init() {
	flag.BoolVar(&debug, "d", false, "Log debug information")
}

func NewDaemonLogger(logFilePath string, daemonName string) *DaemonLogger {
	daemonLogger := new(DaemonLogger)
	daemonLogger.name = daemonName
	daemonLogger.stdoutLog = log.New(os.Stdout, "", 0)
	logFile, _ := os.OpenFile(logFilePath+daemonName+".log", os.O_WRONLY|os.O_CREATE, 0666)
	daemonLogger.fileLog = log.New(logFile, "", 0)
	daemonLogger.error = 0
	return daemonLogger
}

func (daemonLogger *DaemonLogger) Log(message string) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s", formatTime, name, daemonLogger.name, pid, message)
	daemonLogger.fileLog.Printf("%s %s %s[%d]: %s", formatTime, name, daemonLogger.name, pid, message)
}

func (daemonLogger *DaemonLogger) LogError(message string, error os.Error) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	if error != nil {
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.error++
	}

}

func (daemonLogger *DaemonLogger) LogHttp(request *http.Request) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
	daemonLogger.fileLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
}

func (daemonLogger *DaemonLogger) DebugHttp(request *http.Request) {
	if debug {
		currentTime := time.LocalTime()
		formatTime := currentTime.Format("Jan _2 15:04:05")
		name, _ := os.Hostname()
		pid := os.Getpid()
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
	}
}

func (daemonLogger *DaemonLogger) LogDebug(message string) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	if debug {
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: DEBUG %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
	}
}

func (daemonLogger *DaemonLogger) ReturnError() int {
	return daemonLogger.error
}
<commit_msg>logging: add to end of logfile<commit_after>package daemon

import (
	"log"
	"os"
	"time"
	"http"
	"flag"
)

type DaemonLogger struct {
	stdoutLog *log.Logger
	fileLog   *log.Logger
	error     int
	name      string
}

var debug bool

func init() {
	flag.BoolVar(&debug, "d", false, "Log debug information")
}

func NewDaemonLogger(logFilePath string, daemonName string) *DaemonLogger {
	daemonLogger := new(DaemonLogger)
	daemonLogger.name = daemonName
	daemonLogger.stdoutLog = log.New(os.Stdout, "", 0)
	logFile, _ := os.OpenFile(logFilePath+daemonName+".log", os.O_WRONLY|os.O_CREATE, 0666)
        logFile.Seek(0, 2)
	daemonLogger.fileLog = log.New(logFile, "", 0)
	daemonLogger.error = 0
	return daemonLogger
}

func (daemonLogger *DaemonLogger) Log(message string) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s", formatTime, name, daemonLogger.name, pid, message)
	daemonLogger.fileLog.Printf("%s %s %s[%d]: %s", formatTime, name, daemonLogger.name, pid, message)
}

func (daemonLogger *DaemonLogger) LogError(message string, error os.Error) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	if error != nil {
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.error++
	}

}

func (daemonLogger *DaemonLogger) LogHttp(request *http.Request) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
	daemonLogger.fileLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
}

func (daemonLogger *DaemonLogger) DebugHttp(request *http.Request) {
	if debug {
		currentTime := time.LocalTime()
		formatTime := currentTime.Format("Jan _2 15:04:05")
		name, _ := os.Hostname()
		pid := os.Getpid()
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: %s %s Bytes Recieved: %d", formatTime, name, daemonLogger.name, pid, request.Method, request.RawURL, request.ContentLength)
	}
}

func (daemonLogger *DaemonLogger) LogDebug(message string) {
	currentTime := time.LocalTime()
	formatTime := currentTime.Format("Jan _2 15:04:05")
	name, _ := os.Hostname()
	pid := os.Getpid()
	if debug {
		daemonLogger.stdoutLog.Printf("%s %s %s[%d]: DEBUG %s", formatTime, name, daemonLogger.name, pid, message)
		daemonLogger.fileLog.Printf("%s %s %s[%d]: ERROR %s", formatTime, name, daemonLogger.name, pid, message)
	}
}

func (daemonLogger *DaemonLogger) ReturnError() int {
	return daemonLogger.error
}
<|endoftext|>


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

package net

func FileConn(f *os.File) (c Conn, err os.Error) {
	return nil, os.EWINDOWS
}

func FileListener(f *os.File) (l Listener, err os.Error) {
	return nil, os.EWINDOWS
}

func FilePacketConn(f *os.File) (c PacketConn, err os.Error) {
	return nil, os.EWINDOWS
}
<commit_msg>net: fix Windows build<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"os"
	"syscall"
)

func FileConn(f *os.File) (c Conn, err os.Error) {
	// TODO: Implement this
	return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
}

func FileListener(f *os.File) (l Listener, err os.Error) {
	// TODO: Implement this
	return nil, os.NewSyscallError("FileListener", syscall.EWINDOWS)
}

func FilePacketConn(f *os.File) (c PacketConn, err os.Error) {
	// TODO: Implement this
	return nil, os.NewSyscallError("FilePacketConn", syscall.EWINDOWS)
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"bufio"
	"fmt"
	"io"
	"sort"
	"unicode"
)

// Lexeme enumerates the types of lexical tokens in a mtail program.
type lexeme int

// Printable names for lexemes.
var lexemeName = map[lexeme]string{
	EOF:        "EOF",
	INVALID:    "INVALID",
	LCURLY:     "LCURLY",
	RCURLY:     "RCURLY",
	LPAREN:     "LPAREN",
	RPAREN:     "RPAREN",
	LSQUARE:    "LSQUARE",
	RSQUARE:    "RSQUARE",
	COMMA:      "COMMA",
	INC:        "INC",
	MINUS:      "MINUS",
	PLUS:       "PLUS",
	MUL:        "MUL",
	DIV:        "DIV",
	ADD_ASSIGN: "ADD_ASSIGN",
	ASSIGN:     "ASSIGN",
	LT:         "LT",
	GT:         "GT",
	LE:         "LE",
	GE:         "GE",
	EQ:         "EQ",
	NE:         "NE",
	REGEX:      "REGEX",
	ID:         "ID",
	CAPREF:     "CAPREF",
	STRING:     "STRING",
	BUILTIN:    "BUILTIN",
	COUNTER:    "COUNTER",
	GAUGE:      "GAUGE",
	TIMER:      "TIMER",
	AS:         "AS",
	BY:         "BY",
	HIDDEN:     "HIDDEN",
	DEF:        "DEF",
	DECO:       "DECO",
	NEXT:       "NEXT",
	CONST:      "CONST",
}

func (t lexeme) String() string {
	if s, ok := lexemeName[t]; ok {
		return s
	}
	return fmt.Sprintf("token%d", int(t))
}

// List of keywords.  Keep this list sorted!
var keywords = map[string]lexeme{
	"as":      AS,
	"by":      BY,
	"const":   CONST,
	"counter": COUNTER,
	"def":     DEF,
	"gauge":   GAUGE,
	"hidden":  HIDDEN,
	"next":    NEXT,
	"timer":   TIMER,
}

// List of builtin functions.  Keep this list sorted!
var builtins = []string{
	"len",
	"strptime",
	"timestamp",
	"tolower",
}

// A position is the location in the source program that a token appears.
type position struct {
	filename string
	line     int // Line in the source for this token.
	startcol int // Starting and ending columns in the source for this token.
	endcol   int
}

func (p position) String() string {
	r := fmt.Sprintf("%s:%d:%d", p.filename, p.line+1, p.startcol+1)
	if p.endcol > p.startcol {
		r += fmt.Sprintf("-%d", p.endcol+1)
	}
	return r
}

// token describes a lexed token from the input, containing its type, the
// original text of the token, and its position in the input.
type token struct {
	kind lexeme
	text string
	pos  position
}

func (t token) String() string {
	return fmt.Sprintf("%s(%q,%s)", t.kind, t.text, t.pos)
}

// A stateFn represents each state the scanner can be in.
type stateFn func(*lexer) stateFn

// A lexer holds the state of the scanner.
type lexer struct {
	name  string        // Name of program.
	input *bufio.Reader // Source program
	state stateFn       // Current state function of the lexer.

	// The "read cursor" in the input.
	rune  rune // The current rune.
	width int  // Width in bytes.
	line  int  // The line position of the current rune.
	col   int  // The column position of the current rune.

	// The currently being lexed token.
	startcol int    // Starting column of the current token.
	text     string // the text of the current token

	tokens chan token // Output channel for tokens emitted.
}

// newLexer creates a new scanner type that reads the input provided.
func newLexer(name string, input io.Reader) *lexer {
	l := &lexer{
		name:   name,
		input:  bufio.NewReader(input),
		state:  lexProg,
		tokens: make(chan token, 2),
	}
	return l
}

// nextToken returns the next token in the input.
func (l *lexer) nextToken() token {
	for {
		select {
		case token := <-l.tokens:
			return token
		default:
			l.state = l.state(l)
		}
	}
}

// emit passes a token to the client.
func (l *lexer) emit(kind lexeme) {
	pos := position{l.name, l.line, l.startcol, l.col - 1}
	l.tokens <- token{kind, l.text, pos}
	// Reset the current token
	l.text = ""
	l.startcol = l.col
}

// Internal end of file value.
var eof rune = -1

// next returns the next rune in the input.
func (l *lexer) next() rune {
	var err error
	l.rune, l.width, err = l.input.ReadRune()
	if err == io.EOF {
		l.width = 1
		return eof
	}
	return l.rune
}

// backup indicates that we haven't yet dealt with the next rune. Use when
// terminating tokens on unknown runes.
func (l *lexer) backup() {
	l.input.UnreadRune()
	l.width = 0
}

// stepCursor moves the read cursor.
func (l *lexer) stepCursor() {
	if l.rune == '\n' {
		l.line++
		l.col = 0
	} else {
		l.col += l.width
	}
}

// accept accepts the current rune and its position into the current token.
func (l *lexer) accept() {
	l.text += string(l.rune)
	l.stepCursor()
}

// skip does not accept the current rune into the current token's text, but
// does accept its position into the token. Use only at the start or end of a
// token.
func (l *lexer) skip() {
	l.stepCursor()
}

// ignore skips over the current rune, removing it from the text of the token,
// and resetting the start position of the current token. Use only between
// tokens.
func (l *lexer) ignore() {
	l.stepCursor()
	l.startcol = l.col
}

// errorf returns an error token and terminates the scanner by passing back a
// nil state function to the state machine.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	pos := position{l.name, l.line, l.startcol, l.col - 1}
	l.tokens <- token{kind: INVALID,
		text: fmt.Sprintf(format, args...),
		pos:  pos}
	return nil
}

// State functions.

// Start lexing a program.
func lexProg(l *lexer) stateFn {
	switch r := l.next(); {
	case r == '#':
		return lexComment
	case isSpace(r):
		l.ignore()
	case r == '{':
		l.accept()
		l.emit(LCURLY)
	case r == '}':
		l.accept()
		l.emit(RCURLY)
	case r == '(':
		l.accept()
		l.emit(LPAREN)
	case r == ')':
		l.accept()
		l.emit(RPAREN)
	case r == '[':
		l.accept()
		l.emit(LSQUARE)
	case r == ']':
		l.accept()
		l.emit(RSQUARE)
	case r == ',':
		l.accept()
		l.emit(COMMA)
	case r == '-':
		l.accept()
		l.emit(MINUS)
	case r == '+':
		l.accept()
		switch l.next() {
		case '+':
			l.accept()
			l.emit(INC)
		case '=':
			l.accept()
			l.emit(ADD_ASSIGN)
		default:
			l.backup()
			l.emit(PLUS)
		}
	case r == '*':
		l.accept()
		l.emit(MUL)
	case r == '=':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(EQ)
		default:
			l.backup()
			l.emit(ASSIGN)
		}
	case r == '<':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(LE)
		default:
			l.backup()
			l.emit(LT)
		}
	case r == '>':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(GE)
		default:
			l.backup()
			l.emit(GT)
		}
	case r == '!':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(NE)
		default:
			l.backup()
			return l.errorf("Unexpected input: %q", r)
		}
	case r == '/':
		return lexRegex
	case r == '"':
		return lexQuotedString
	case r == '$':
		return lexCapref
	case r == '@':
		return lexDecorator
	case isDigit(r):
		return lexNumeric
	case isAlpha(r):
		return lexIdentifier
	case r == eof:
		l.skip()
		l.emit(EOF)
		// Stop the machine, we're done.
		return nil
	default:
		l.accept()
		return l.errorf("Unexpected input: %q", r)
	}
	return lexProg
}

// Lex a comment.
func lexComment(l *lexer) stateFn {
	l.ignore()
Loop:
	for {
		switch l.next() {
		case '\n':
			l.skip()
			fallthrough
		case eof:
			break Loop
		default:
			l.ignore()
		}
	}
	return lexProg
}

// Lex a numerical constant.
func lexNumeric(l *lexer) stateFn {
	l.accept()
Loop:
	for {
		switch r := l.next(); {
		case isDigit(r):
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(NUMERIC)
	return lexProg
}

// Lex a quoted string.  The text of a quoted string does not include the '"' quotes.
func lexQuotedString(l *lexer) stateFn {
	l.skip() // Skip leading quote
Loop:
	for {
		switch l.next() {
		case '\\':
			l.skip()
			if r := l.next(); r != eof && r != '\n' {
				if r != '"' {
					l.text += "\\"
				}
				l.accept()
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("Unterminated quoted string: \"\\\"%s\"", l.text)
		case '"':
			l.skip() // Skip trailing quote.
			break Loop
		default:
			l.accept()
		}
	}
	l.emit(STRING)
	return lexProg
}

// Lex a capture group reference. These are local variable references to
// capture groups in the preceeding regular expression.
func lexCapref(l *lexer) stateFn {
	l.skip() // Skip the leading $
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r) || r == '_':
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(CAPREF)
	return lexProg
}

// Lex an identifier, or builtin keyword.
func lexIdentifier(l *lexer) stateFn {
	l.accept()
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r) || r == '-' || r == '_':
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	if r, ok := keywords[l.text]; ok {
		l.emit(r)
	} else if r := sort.SearchStrings(builtins, l.text); r >= 0 && r < len(builtins) && builtins[r] == l.text {
		l.emit(BUILTIN)
	} else {
		l.emit(ID)
	}
	return lexProg

}

// Lex a regular expression. The text of the regular expression does not
// include the '/' quotes.
func lexRegex(l *lexer) stateFn {
	l.skip() // Skip leading quote
Loop:
	for {
		switch l.next() {
		case '\\':
			l.skip()
			if r := l.next(); r != eof && r != '\n' {
				if r != '/' {
					l.text += `\`
				}
				l.accept()
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("Unterminated regular expression: \"/%s\"", l.text)
		case '/':
			l.skip() // Skip trailing quote
			break Loop
		default:
			l.accept()
		}
	}
	l.emit(REGEX)
	return lexProg
}

// Lex a decorator name. These are functiony templatey wrappers around blocks
// of rules.
func lexDecorator(l *lexer) stateFn {
	l.skip() // Skip the leading @
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r):
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(DECO)
	return lexProg
}

// Helper predicates.

// isAlpha reports whether r is an alphabetical rune.
func isAlpha(r rune) bool {
	return unicode.IsLetter(r)
}

// isAlnum reports whether r is an alphanumeric rune.
func isAlnum(r rune) bool {
	return isAlpha(r) || isDigit(r)
}

// isDigit reports whether r is a numerical rune.
func isDigit(r rune) bool {
	return unicode.IsDigit(r)
}

// isSpace reports whether r is whitespace.
func isSpace(r rune) bool {
	return unicode.IsSpace(r)
}
<commit_msg>Fix comment.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"bufio"
	"fmt"
	"io"
	"sort"
	"unicode"
)

// Lexeme enumerates the types of lexical tokens in a mtail program.
type lexeme int

// Printable names for lexemes.
var lexemeName = map[lexeme]string{
	EOF:        "EOF",
	INVALID:    "INVALID",
	LCURLY:     "LCURLY",
	RCURLY:     "RCURLY",
	LPAREN:     "LPAREN",
	RPAREN:     "RPAREN",
	LSQUARE:    "LSQUARE",
	RSQUARE:    "RSQUARE",
	COMMA:      "COMMA",
	INC:        "INC",
	MINUS:      "MINUS",
	PLUS:       "PLUS",
	MUL:        "MUL",
	DIV:        "DIV",
	ADD_ASSIGN: "ADD_ASSIGN",
	ASSIGN:     "ASSIGN",
	LT:         "LT",
	GT:         "GT",
	LE:         "LE",
	GE:         "GE",
	EQ:         "EQ",
	NE:         "NE",
	REGEX:      "REGEX",
	ID:         "ID",
	CAPREF:     "CAPREF",
	STRING:     "STRING",
	BUILTIN:    "BUILTIN",
	COUNTER:    "COUNTER",
	GAUGE:      "GAUGE",
	TIMER:      "TIMER",
	AS:         "AS",
	BY:         "BY",
	HIDDEN:     "HIDDEN",
	DEF:        "DEF",
	DECO:       "DECO",
	NEXT:       "NEXT",
	CONST:      "CONST",
}

func (t lexeme) String() string {
	if s, ok := lexemeName[t]; ok {
		return s
	}
	return fmt.Sprintf("token%d", int(t))
}

// List of keywords.  Keep this list sorted!
var keywords = map[string]lexeme{
	"as":      AS,
	"by":      BY,
	"const":   CONST,
	"counter": COUNTER,
	"def":     DEF,
	"gauge":   GAUGE,
	"hidden":  HIDDEN,
	"next":    NEXT,
	"timer":   TIMER,
}

// List of builtin functions.  Keep this list sorted!
var builtins = []string{
	"len",
	"strptime",
	"timestamp",
	"tolower",
}

// A position is the location in the source program that a token appears.
type position struct {
	filename string
	line     int // Line in the source for this token.
	startcol int // Starting and ending columns in the source for this token.
	endcol   int
}

func (p position) String() string {
	r := fmt.Sprintf("%s:%d:%d", p.filename, p.line+1, p.startcol+1)
	if p.endcol > p.startcol {
		r += fmt.Sprintf("-%d", p.endcol+1)
	}
	return r
}

// token describes a lexed token from the input, containing its type, the
// original text of the token, and its position in the input.
type token struct {
	kind lexeme
	text string
	pos  position
}

func (t token) String() string {
	return fmt.Sprintf("%s(%q,%s)", t.kind, t.text, t.pos)
}

// A stateFn represents each state the scanner can be in.
type stateFn func(*lexer) stateFn

// A lexer holds the state of the scanner.
type lexer struct {
	name  string        // Name of program.
	input *bufio.Reader // Source program
	state stateFn       // Current state function of the lexer.

	// The "read cursor" in the input.
	rune  rune // The current rune.
	width int  // Width in bytes.
	line  int  // The line position of the current rune.
	col   int  // The column position of the current rune.

	// The currently being lexed token.
	startcol int    // Starting column of the current token.
	text     string // the text of the current token

	tokens chan token // Output channel for tokens emitted.
}

// newLexer creates a new scanner type that reads the input provided.
func newLexer(name string, input io.Reader) *lexer {
	l := &lexer{
		name:   name,
		input:  bufio.NewReader(input),
		state:  lexProg,
		tokens: make(chan token, 2),
	}
	return l
}

// nextToken returns the next token in the input.  When no token is available
// to be returned, it executes the next action in the state machine.
func (l *lexer) nextToken() token {
	for {
		select {
		case token := <-l.tokens:
			return token
		default:
			l.state = l.state(l)
		}
	}
}

// emit passes a token to the client.
func (l *lexer) emit(kind lexeme) {
	pos := position{l.name, l.line, l.startcol, l.col - 1}
	l.tokens <- token{kind, l.text, pos}
	// Reset the current token
	l.text = ""
	l.startcol = l.col
}

// Internal end of file value.
var eof rune = -1

// next returns the next rune in the input.
func (l *lexer) next() rune {
	var err error
	l.rune, l.width, err = l.input.ReadRune()
	if err == io.EOF {
		l.width = 1
		return eof
	}
	return l.rune
}

// backup indicates that we haven't yet dealt with the next rune. Use when
// terminating tokens on unknown runes.
func (l *lexer) backup() {
	l.input.UnreadRune()
	l.width = 0
}

// stepCursor moves the read cursor.
func (l *lexer) stepCursor() {
	if l.rune == '\n' {
		l.line++
		l.col = 0
	} else {
		l.col += l.width
	}
}

// accept accepts the current rune and its position into the current token.
func (l *lexer) accept() {
	l.text += string(l.rune)
	l.stepCursor()
}

// skip does not accept the current rune into the current token's text, but
// does accept its position into the token. Use only at the start or end of a
// token.
func (l *lexer) skip() {
	l.stepCursor()
}

// ignore skips over the current rune, removing it from the text of the token,
// and resetting the start position of the current token. Use only between
// tokens.
func (l *lexer) ignore() {
	l.stepCursor()
	l.startcol = l.col
}

// errorf returns an error token and terminates the scanner by passing back a
// nil state function to the state machine.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	pos := position{l.name, l.line, l.startcol, l.col - 1}
	l.tokens <- token{kind: INVALID,
		text: fmt.Sprintf(format, args...),
		pos:  pos}
	return nil
}

// State functions.

// Start lexing a program.
func lexProg(l *lexer) stateFn {
	switch r := l.next(); {
	case r == '#':
		return lexComment
	case isSpace(r):
		l.ignore()
	case r == '{':
		l.accept()
		l.emit(LCURLY)
	case r == '}':
		l.accept()
		l.emit(RCURLY)
	case r == '(':
		l.accept()
		l.emit(LPAREN)
	case r == ')':
		l.accept()
		l.emit(RPAREN)
	case r == '[':
		l.accept()
		l.emit(LSQUARE)
	case r == ']':
		l.accept()
		l.emit(RSQUARE)
	case r == ',':
		l.accept()
		l.emit(COMMA)
	case r == '-':
		l.accept()
		l.emit(MINUS)
	case r == '+':
		l.accept()
		switch l.next() {
		case '+':
			l.accept()
			l.emit(INC)
		case '=':
			l.accept()
			l.emit(ADD_ASSIGN)
		default:
			l.backup()
			l.emit(PLUS)
		}
	case r == '*':
		l.accept()
		l.emit(MUL)
	case r == '=':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(EQ)
		default:
			l.backup()
			l.emit(ASSIGN)
		}
	case r == '<':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(LE)
		default:
			l.backup()
			l.emit(LT)
		}
	case r == '>':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(GE)
		default:
			l.backup()
			l.emit(GT)
		}
	case r == '!':
		l.accept()
		switch l.next() {
		case '=':
			l.accept()
			l.emit(NE)
		default:
			l.backup()
			return l.errorf("Unexpected input: %q", r)
		}
	case r == '/':
		return lexRegex
	case r == '"':
		return lexQuotedString
	case r == '$':
		return lexCapref
	case r == '@':
		return lexDecorator
	case isDigit(r):
		return lexNumeric
	case isAlpha(r):
		return lexIdentifier
	case r == eof:
		l.skip()
		l.emit(EOF)
		// Stop the machine, we're done.
		return nil
	default:
		l.accept()
		return l.errorf("Unexpected input: %q", r)
	}
	return lexProg
}

// Lex a comment.
func lexComment(l *lexer) stateFn {
	l.ignore()
Loop:
	for {
		switch l.next() {
		case '\n':
			l.skip()
			fallthrough
		case eof:
			break Loop
		default:
			l.ignore()
		}
	}
	return lexProg
}

// Lex a numerical constant.
func lexNumeric(l *lexer) stateFn {
	l.accept()
Loop:
	for {
		switch r := l.next(); {
		case isDigit(r):
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(NUMERIC)
	return lexProg
}

// Lex a quoted string.  The text of a quoted string does not include the '"' quotes.
func lexQuotedString(l *lexer) stateFn {
	l.skip() // Skip leading quote
Loop:
	for {
		switch l.next() {
		case '\\':
			l.skip()
			if r := l.next(); r != eof && r != '\n' {
				if r != '"' {
					l.text += "\\"
				}
				l.accept()
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("Unterminated quoted string: \"\\\"%s\"", l.text)
		case '"':
			l.skip() // Skip trailing quote.
			break Loop
		default:
			l.accept()
		}
	}
	l.emit(STRING)
	return lexProg
}

// Lex a capture group reference. These are local variable references to
// capture groups in the preceeding regular expression.
func lexCapref(l *lexer) stateFn {
	l.skip() // Skip the leading $
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r) || r == '_':
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(CAPREF)
	return lexProg
}

// Lex an identifier, or builtin keyword.
func lexIdentifier(l *lexer) stateFn {
	l.accept()
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r) || r == '-' || r == '_':
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	if r, ok := keywords[l.text]; ok {
		l.emit(r)
	} else if r := sort.SearchStrings(builtins, l.text); r >= 0 && r < len(builtins) && builtins[r] == l.text {
		l.emit(BUILTIN)
	} else {
		l.emit(ID)
	}
	return lexProg

}

// Lex a regular expression. The text of the regular expression does not
// include the '/' quotes.
func lexRegex(l *lexer) stateFn {
	l.skip() // Skip leading quote
Loop:
	for {
		switch l.next() {
		case '\\':
			l.skip()
			if r := l.next(); r != eof && r != '\n' {
				if r != '/' {
					l.text += `\`
				}
				l.accept()
				break
			}
			fallthrough
		case eof, '\n':
			return l.errorf("Unterminated regular expression: \"/%s\"", l.text)
		case '/':
			l.skip() // Skip trailing quote
			break Loop
		default:
			l.accept()
		}
	}
	l.emit(REGEX)
	return lexProg
}

// Lex a decorator name. These are functiony templatey wrappers around blocks
// of rules.
func lexDecorator(l *lexer) stateFn {
	l.skip() // Skip the leading @
Loop:
	for {
		switch r := l.next(); {
		case isAlnum(r):
			l.accept()
		default:
			l.backup()
			break Loop
		}
	}
	l.emit(DECO)
	return lexProg
}

// Helper predicates.

// isAlpha reports whether r is an alphabetical rune.
func isAlpha(r rune) bool {
	return unicode.IsLetter(r)
}

// isAlnum reports whether r is an alphanumeric rune.
func isAlnum(r rune) bool {
	return isAlpha(r) || isDigit(r)
}

// isDigit reports whether r is a numerical rune.
func isDigit(r rune) bool {
	return unicode.IsDigit(r)
}

// isSpace reports whether r is whitespace.
func isSpace(r rune) bool {
	return unicode.IsSpace(r)
}
<|endoftext|>


<commit_before>package vm

import (
	. "github.com/tendermint/tendermint/common"
	ptypes "github.com/tendermint/tendermint/permission/types"
)

const (
	defaultDataStackCapacity = 10
)

type Account struct {
	Address     Word256
	Balance     int64
	Code        []byte
	Nonce       int64
	StorageRoot Word256
	Other       interface{} // For holding all other data.

	Permissions ptypes.AccountPermissions
}

func (acc *Account) String() string {
	return Fmt("VMAccount{%X B:%v C:%X N:%v S:%X}",
		acc.Address, acc.Balance, acc.Code, acc.Nonce, acc.StorageRoot)
}

type Log struct {
	Address Word256
	Topics  []Word256
	Data    []byte
	Height  int64
}

type AppState interface {

	// Accounts
	GetAccount(addr Word256) *Account
	UpdateAccount(*Account)
	RemoveAccount(*Account)
	CreateAccount(*Account) *Account

	// Storage
	GetStorage(Word256, Word256) Word256
	SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.

	// Logs
	AddLog(*Log)
}

type Params struct {
	BlockHeight int64
	BlockHash   Word256
	BlockTime   int64
	GasLimit    int64
}
<commit_msg>vm's Log events are lowercased<commit_after>package vm

import (
	. "github.com/tendermint/tendermint/common"
	ptypes "github.com/tendermint/tendermint/permission/types"
)

const (
	defaultDataStackCapacity = 10
)

type Account struct {
	Address     Word256
	Balance     int64
	Code        []byte
	Nonce       int64
	StorageRoot Word256
	Other       interface{} // For holding all other data.

	Permissions ptypes.AccountPermissions
}

func (acc *Account) String() string {
	return Fmt("VMAccount{%X B:%v C:%X N:%v S:%X}",
		acc.Address, acc.Balance, acc.Code, acc.Nonce, acc.StorageRoot)
}

// NOTE: This is serialized as an event from vm/vm.
// See: EventStringLogEvent
type Log struct {
	Address Word256   `json:"address"`
	Topics  []Word256 `json:"topics"`
	Data    []byte    `json:"data"`
	Height  int64     `json:"height"`
}

type AppState interface {

	// Accounts
	GetAccount(addr Word256) *Account
	UpdateAccount(*Account)
	RemoveAccount(*Account)
	CreateAccount(*Account) *Account

	// Storage
	GetStorage(Word256, Word256) Word256
	SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.

	// Logs
	AddLog(*Log)
}

type Params struct {
	BlockHeight int64
	BlockHash   Word256
	BlockTime   int64
	GasLimit    int64
}
<|endoftext|>


<commit_before>// Copyright (c) 2019-2020 Leonid Kneller. All rights reserved.
// Licensed under the MIT license.
// See the LICENSE file for full license information.

package mym

import (
	"math"
)

// Vmedian3 -- computes the geometric median of u[0],u[1],...,u[len(u)-1].
// This function implements the Weiszfeld iterative algorithm as modified by
// Vardi and Zhang.
//
// Reference: Vardi and Zhang, The multivariate L1-median and associated data depth,
// Proceedings of the National Academy of Sciences Feb 2000, 97 (4) 1423-1426.
//
// DOI: https://doi.org/10.1073/pnas.97.4.1423
func Vmedian3(u [][3]float64) [3]float64 {
	n := len(u)
	if n == 0 {
		return [3]float64{0, 0, 0}
	}
	//
	// initial approximation
	mu := Vmean3(u)
	//
	// convergence test based on relative change of mu (L1-norm)
	convtest := func(mu1, mu2 [3]float64) bool {
		t1, _ := Vnrm3(mu1)
		t2, _ := Vnrm3(mu2)
		w := Vsub3(mu1, mu2)
		tw, _ := Vnrm3(w)
		return tw <= SqrtEps*math.Max(t1, t2)
	}
	//
	for iter := 1; iter <= 5000; iter++ {
		eta := 0.0
		S1 := [3]float64{0, 0, 0}
		S2 := 0.0
		R := [3]float64{0, 0, 0}
		//
		for _, v := range u {
			w := Vsub3(v, mu)
			wabs := Vabs3(w)
			//
			if wabs < Epsilon {
				eta += 1
				continue
			}
			//
			S1 = Vadd3(S1, Vdiv3(v, wabs))
			S2 += 1 / wabs
			//
			R = Vadd3(R, Vdiv3(w, wabs))
		}
		//
		T := Vdiv3(S1, S2)
		gamma := math.Min(1, eta/Vabs3(R))
		munew := Vadd3(Vmul3(T, 1-gamma), Vmul3(mu, gamma))
		if convtest(mu, munew) {
			return munew
		}
		//
		mu = munew
	}
	//
	return mu
}
<commit_msg>Check if `gamma` is a finite number.<commit_after>// Copyright (c) 2019-2020 Leonid Kneller. All rights reserved.
// Licensed under the MIT license.
// See the LICENSE file for full license information.

package mym

import (
	"math"
)

// Vmedian3 -- computes the geometric median of u[0],u[1],...,u[len(u)-1].
// This function implements the Weiszfeld iterative algorithm as modified by
// Vardi and Zhang.
//
// Reference: Vardi and Zhang, The multivariate L1-median and associated data depth,
// Proceedings of the National Academy of Sciences Feb 2000, 97 (4) 1423-1426.
//
// DOI: https://doi.org/10.1073/pnas.97.4.1423
func Vmedian3(u [][3]float64) [3]float64 {
	n := len(u)
	if n == 0 {
		return [3]float64{0, 0, 0}
	}
	//
	// initial approximation
	mu := Vmean3(u)
	//
	// convergence test based on relative change of mu (L1-norm)
	convtest := func(mu1, mu2 [3]float64) bool {
		t1, _ := Vnrm3(mu1)
		t2, _ := Vnrm3(mu2)
		w := Vsub3(mu1, mu2)
		tw, _ := Vnrm3(w)
		return tw <= SqrtEps*math.Max(t1, t2)
	}
	//
	for iter := 1; iter <= 5000; iter++ {
		eta := 0.0
		S1 := [3]float64{0, 0, 0}
		S2 := 0.0
		R := [3]float64{0, 0, 0}
		//
		for _, v := range u {
			w := Vsub3(v, mu)
			wabs := Vabs3(w)
			//
			if wabs < Epsilon {
				eta += 1
				continue
			}
			//
			S1 = Vadd3(S1, Vdiv3(v, wabs))
			S2 += 1 / wabs
			//
			R = Vadd3(R, Vdiv3(w, wabs))
		}
		//
		T := Vdiv3(S1, S2)
		gamma := math.Min(1, eta/Vabs3(R))
		if !FiniteIs(gamma) {
			gamma = 0
		}
		munew := Vadd3(Vmul3(T, 1-gamma), Vmul3(mu, gamma))
		//
		if convtest(mu, munew) {
			return munew
		}
		//
		mu = munew
	}
	//
	return mu
}
<|endoftext|>


<commit_before>package web

import (
	"bytes"
	"fmt"
	"net/http"
	"net/mail"
	"net/url"
	"sort"
	"strings"
	"time"

	"github.com/StackExchange/bosun/_third_party/github.com/MiniProfiler/go/miniprofiler"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/opentsdb"
	"github.com/StackExchange/bosun/conf"
	"github.com/StackExchange/bosun/expr"
	"github.com/StackExchange/bosun/sched"
)

func Expr(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	e, err := expr.New(r.FormValue("q"))
	if err != nil {
		return nil, err
	}
	now, err := getTime(r)
	if err != nil {
		return nil, err
	}
	res, queries, err := e.Execute(opentsdb.NewCache(schedule.Conf.TsdbHost, schedule.Conf.ResponseLimit), t, now, 0, false, schedule.Search, schedule.Lookups)
	if err != nil {
		return nil, err
	}
	for _, r := range res.Results {
		if r.Computations == nil {
			r.Computations = make(expr.Computations, 0)
		}
	}
	ret := struct {
		Type    string
		Results []*expr.Result
		Queries map[string]opentsdb.Request
	}{
		e.Tree.Root.Return().String(),
		res.Results,
		make(map[string]opentsdb.Request),
	}
	for _, q := range queries {
		if e, err := url.QueryUnescape(q.String()); err == nil {
			ret.Queries[e] = q
		}
	}
	return ret, nil
}

func getTime(r *http.Request) (now time.Time, err error) {
	now = time.Now().UTC()
	if fd := r.FormValue("date"); len(fd) > 0 {
		if ft := r.FormValue("time"); len(ft) > 0 {
			fd += " " + ft
		} else {
			fd += " " + now.Format("15:04")
		}
		now, err = time.Parse("2006-01-02 15:04", fd)
	}
	return
}

type Res struct {
	*sched.Event
	Key expr.AlertKey
}

func Rule(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "tsdbHost = %s\n", schedule.Conf.TsdbHost)
	fmt.Fprintf(&buf, "smtpHost = %s\n", schedule.Conf.SmtpHost)
	fmt.Fprintf(&buf, "emailFrom = %s\n", schedule.Conf.EmailFrom)
	fmt.Fprintf(&buf, "responseLimit = %d\n", schedule.Conf.ResponseLimit)
	for k, v := range schedule.Conf.Vars {
		if strings.HasPrefix(k, "$") {
			fmt.Fprintf(&buf, "%s=%s\n", k, v)
		}
	}
	for _, v := range schedule.Conf.Notifications {
		fmt.Fprintln(&buf, v.Def)
	}
	fmt.Fprintf(&buf, "%s\n", r.FormValue("template"))
	fmt.Fprintf(&buf, "%s\n", r.FormValue("alert"))
	c, err := conf.New("Test Config", buf.String())
	if err != nil {
		return nil, err
	}
	if len(c.Alerts) != 1 {
		return nil, fmt.Errorf("exactly one alert must be defined")
	}
	s := &sched.Schedule{}
	now, err := getTime(r)
	if err != nil {
		return nil, err
	}
	s.CheckStart = now
	s.Init(c)
	s.Search = schedule.Search
	rh := make(sched.RunHistory)
	var a *conf.Alert
	for _, a = range c.Alerts {
	}
	if _, err := s.CheckExpr(rh, a, a.Warn, sched.StWarning, nil); err != nil {
		return nil, err
	}
	if _, err := s.CheckExpr(rh, a, a.Crit, sched.StCritical, nil); err != nil {
		return nil, err
	}
	i := 0
	if len(rh) < 1 {
		return nil, fmt.Errorf("no results returned")
	}
	keys := make(expr.AlertKeys, len(rh))
	for k, v := range rh {
		v.Time = now
		keys[i] = k
		i++
	}
	sort.Sort(keys)
	instance := s.Status(keys[0])
	instance.History = []sched.Event{*rh[keys[0]]}
	body := new(bytes.Buffer)
	subject := new(bytes.Buffer)
	var data interface{}
	warning := make([]string, 0)
	if r.FormValue("notemplate") != "" {
		if err := s.ExecuteBody(body, a, instance); err != nil {
			warning = append(warning, err.Error())
		}
		if err := s.ExecuteSubject(subject, a, instance); err != nil {
			warning = append(warning, err.Error())
		}
		data = s.Data(instance, a)
		if e := r.FormValue("email"); e != "" {
			n := conf.Notification{
				Email: []*mail.Address{&mail.Address{
					Name:    "Bosun Test",
					Address: e,
				}},
			}
			n.DoEmail(subject.Bytes(), body.Bytes(), schedule.Conf.EmailFrom, schedule.Conf.SmtpHost)
		}
	}
	return struct {
		Body    string      `json:",omitempty"`
		Subject string      `json:",omitempty"`
		Data    interface{} `json:",omitempty"`
		Result  sched.RunHistory
		Warning []string `json:",omitempty"`
		Time    int64
	}{
		body.String(),
		subject.String(),
		data,
		rh,
		warning,
		now.Unix(),
	}, nil
}
<commit_msg>Use ParseAddress<commit_after>package web

import (
	"bytes"
	"fmt"
	"net/http"
	"net/mail"
	"net/url"
	"sort"
	"strings"
	"time"

	"github.com/StackExchange/bosun/_third_party/github.com/MiniProfiler/go/miniprofiler"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/opentsdb"
	"github.com/StackExchange/bosun/conf"
	"github.com/StackExchange/bosun/expr"
	"github.com/StackExchange/bosun/sched"
)

func Expr(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	e, err := expr.New(r.FormValue("q"))
	if err != nil {
		return nil, err
	}
	now, err := getTime(r)
	if err != nil {
		return nil, err
	}
	res, queries, err := e.Execute(opentsdb.NewCache(schedule.Conf.TsdbHost, schedule.Conf.ResponseLimit), t, now, 0, false, schedule.Search, schedule.Lookups)
	if err != nil {
		return nil, err
	}
	for _, r := range res.Results {
		if r.Computations == nil {
			r.Computations = make(expr.Computations, 0)
		}
	}
	ret := struct {
		Type    string
		Results []*expr.Result
		Queries map[string]opentsdb.Request
	}{
		e.Tree.Root.Return().String(),
		res.Results,
		make(map[string]opentsdb.Request),
	}
	for _, q := range queries {
		if e, err := url.QueryUnescape(q.String()); err == nil {
			ret.Queries[e] = q
		}
	}
	return ret, nil
}

func getTime(r *http.Request) (now time.Time, err error) {
	now = time.Now().UTC()
	if fd := r.FormValue("date"); len(fd) > 0 {
		if ft := r.FormValue("time"); len(ft) > 0 {
			fd += " " + ft
		} else {
			fd += " " + now.Format("15:04")
		}
		now, err = time.Parse("2006-01-02 15:04", fd)
	}
	return
}

type Res struct {
	*sched.Event
	Key expr.AlertKey
}

func Rule(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "tsdbHost = %s\n", schedule.Conf.TsdbHost)
	fmt.Fprintf(&buf, "smtpHost = %s\n", schedule.Conf.SmtpHost)
	fmt.Fprintf(&buf, "emailFrom = %s\n", schedule.Conf.EmailFrom)
	fmt.Fprintf(&buf, "responseLimit = %d\n", schedule.Conf.ResponseLimit)
	for k, v := range schedule.Conf.Vars {
		if strings.HasPrefix(k, "$") {
			fmt.Fprintf(&buf, "%s=%s\n", k, v)
		}
	}
	for _, v := range schedule.Conf.Notifications {
		fmt.Fprintln(&buf, v.Def)
	}
	fmt.Fprintf(&buf, "%s\n", r.FormValue("template"))
	fmt.Fprintf(&buf, "%s\n", r.FormValue("alert"))
	c, err := conf.New("Test Config", buf.String())
	if err != nil {
		return nil, err
	}
	if len(c.Alerts) != 1 {
		return nil, fmt.Errorf("exactly one alert must be defined")
	}
	s := &sched.Schedule{}
	now, err := getTime(r)
	if err != nil {
		return nil, err
	}
	s.CheckStart = now
	s.Init(c)
	s.Search = schedule.Search
	rh := make(sched.RunHistory)
	var a *conf.Alert
	for _, a = range c.Alerts {
	}
	if _, err := s.CheckExpr(rh, a, a.Warn, sched.StWarning, nil); err != nil {
		return nil, err
	}
	if _, err := s.CheckExpr(rh, a, a.Crit, sched.StCritical, nil); err != nil {
		return nil, err
	}
	i := 0
	if len(rh) < 1 {
		return nil, fmt.Errorf("no results returned")
	}
	keys := make(expr.AlertKeys, len(rh))
	for k, v := range rh {
		v.Time = now
		keys[i] = k
		i++
	}
	sort.Sort(keys)
	instance := s.Status(keys[0])
	instance.History = []sched.Event{*rh[keys[0]]}
	body := new(bytes.Buffer)
	subject := new(bytes.Buffer)
	var data interface{}
	warning := make([]string, 0)
	if r.FormValue("notemplate") != "" {
		if err := s.ExecuteBody(body, a, instance); err != nil {
			warning = append(warning, err.Error())
		}
		if err := s.ExecuteSubject(subject, a, instance); err != nil {
			warning = append(warning, err.Error())
		}
		data = s.Data(instance, a)
		if e := r.FormValue("email"); e != "" {
			if m, err := mail.ParseAddress(e); err != nil {
				warning = append(warning, err.Error())
			} else {
				n := conf.Notification{
					Email: []*mail.Address{m},
				}
				n.DoEmail(subject.Bytes(), body.Bytes(), schedule.Conf.EmailFrom, schedule.Conf.SmtpHost)
			}
		}
	}
	return struct {
		Body    string      `json:",omitempty"`
		Subject string      `json:",omitempty"`
		Data    interface{} `json:",omitempty"`
		Result  sched.RunHistory
		Warning []string `json:",omitempty"`
		Time    int64
	}{
		body.String(),
		subject.String(),
		data,
		rh,
		warning,
		now.Unix(),
	}, nil
}
<|endoftext|>


<commit_before>package web

import (
	"fmt"
	"log"
	"net/http"
	"strconv"

	"hectorcorrea.com/models"
	"hectorcorrea.com/viewModels"
)

var blogRouter Router

func blogPages(resp http.ResponseWriter, req *http.Request) {

	// This should be initialized only once, not on every call.
	blogRouter.Add("GET", "/blog/:title/:id", blogViewOne)
	blogRouter.Add("GET", "/blog/", blogViewAll)
	blogRouter.Add("POST", "/blog/new", blogNew)
	blogRouter.Add("POST", "/blog/:title/:id/edit", blogEdit)
	blogRouter.Add("POST", "/blog/:title/:id/save", blogSave)
	blogRouter.Add("POST", "/blog/:title/:id/post", blogPost)
	blogRouter.Add("POST", "/blog/:title/:id/draft", blogDraft)

	session := newSession(resp, req)
	found, route := blogRouter.FindRoute(req.Method, req.URL.Path)
	if found {
		values := route.UrlValues(req.URL.Path)
		route.handler(session, values)
	} else {
		renderNotFound(session)
	}
}

// func blogPagesOld(resp http.ResponseWriter, req *http.Request) {
//
// 	session := newSession(resp, req)
// 	if req.Method == "GET" {
// 		blogView(session)
// 	} else if req.Method == "POST" {
// 		blogAction(session)
// 	} else {
// 		renderError(session, "Unknown HTTP Method", errors.New("HTTP method not supported"))
// 	}
// }

// func blogView(s session) {
// 	if id, err := parseBlogViewUrl(s.req.URL.Path); err != nil {
// 		renderError(s, "Cannot parse Blog URL", err)
// 	} else if id != 0 {
// 		blogViewOne(s, id)
// 	} else {
// 		blogViewAll(s)
// 	}
// }

func blogViewOne(s session, values map[string]string) {
	id := idFromString(values["id"])
	log.Println(values)
	if id == 0 {
		renderError(s, "No Blog ID was received", nil)
		return
	}

	log.Printf("Loading %d", id)
	blog, err := models.BlogGetById(id)
	if err != nil {
		renderError(s, "Fetching by ID", err)
		return
	}

	vm := viewModels.FromBlog(blog, s.toViewModel())
	renderTemplate(s, "views/blogView.html", vm)
}

func blogViewAll(s session, values map[string]string) {
	log.Printf("Loading all...")
	if blogs, err := models.BlogGetAll(); err != nil {
		renderError(s, "Error fetching all", err)
	} else {
		vm := viewModels.FromBlogs(blogs, s.toViewModel())
		renderTemplate(s, "views/blogList.html", vm)
	}
}

// func blogAction(s session) {
// 	id, action, err := parseBlogEditUrl(s.req.URL.Path)
// 	if err != nil {
// 		renderError(s, "Cannot determine HTTP action", err)
// 		return
// 	}
//
// 	if !s.isAuth() {
// 		renderNotAuthorized(s)
// 		return
// 	}
//
// 	if action == "new" {
// 		blogNew(s)
// 	} else if action == "edit" {
// 		blogEdit(s, id)
// 	} else if action == "save" {
// 		blogSave(s, id)
// 	} else if action == "post" {
// 		blogPost(s, id)
// 	} else if action == "draft" {
// 		blogDraft(s, id)
// 	} else {
// 		renderError(s, "Unknown action", nil)
// 	}
// }

func blogSave(s session, values map[string]string) {
	id := idFromString(values["id"])
	blog := blogFromForm(id, s)
	if err := blog.Save(); err != nil {
		renderError(s, fmt.Sprintf("Saving blog ID: %d"), err)
	} else {
		url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
		log.Printf("Redirect to %s", url)
		http.Redirect(s.resp, s.req, url, 301)
	}
}

func blogNew(s session, values map[string]string) {
	newId, err := models.SaveNew()
	if err != nil {
		renderError(s, fmt.Sprintf("Error creating new blog"), err)
		return
	}
	log.Printf("Redirect to (edit for new) %d", newId)
	values["id"] = fmt.Sprintf("%d", newId)
	blogEdit(s, values)
}

func blogDraft(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	blog, err := models.MarkAsDraft(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Mark as draft: %d", id), err)
		return
	}

	url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
	log.Printf("Marked as draft: %s", url)
	http.Redirect(s.resp, s.req, url, 301)
}

func blogPost(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	blog, err := models.MarkAsPosted(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Mark as posted: %d", id), err)
		return
	}

	url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
	log.Printf("Mark as posted: %s", url)
	http.Redirect(s.resp, s.req, url, 301)
}

func blogEdit(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	log.Printf("Loading %d", id)
	blog, err := models.BlogGetById(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Loading ID: %d", id), err)
		return
	}

	vm := viewModels.FromBlog(blog, s.toViewModel())
	renderTemplate(s, "views/blogEdit.html", vm)
}

func idFromString(str string) int64 {
	id, _ := strconv.ParseInt(str, 10, 64)
	return id
}

// func parseBlogViewUrl(url string) (id int64, err error) {
// 	if url == "/blog/" {
// 		return 0, nil
// 	}
// 	// url /blog/:title/:id
// 	// parts[0] empty
// 	// parts[1] blog
// 	// parts[2] title
// 	// parts[3] id
// 	parts := strings.Split(url, "/")
// 	if len(parts) == 4 && parts[0] == "" && parts[1] == "blog" {
// 		return idFromString(parts[3])
// 	}
// 	return 0, errors.New("Could not parse (view) blog URL")
// }
//
// func parseBlogEditUrl(url string) (id int64, action string, err error) {
// 	if url == "/blog/new" {
// 		return 0, "new", nil
// 	}
// 	// url /blog/:title/:id/:action
// 	// parts[0] empty
// 	// parts[1] blog
// 	// parts[2] title
// 	// parts[3] id
// 	// parts[4] action (edit, post, draft)
// 	parts := strings.Split(url, "/")
// 	if len(parts) == 5 && parts[0] == "" && parts[1] == "blog" {
// 		if id, err := idFromString(parts[3]); err != nil {
// 			return 0, "", err
// 		} else {
// 			action := parts[4]
// 			if action == "edit" || action == "save" ||
// 				action == "post" || action == "draft" {
// 				return id, action, nil
// 			}
// 			return 0, "", errors.New("Invalid action")
// 		}
// 	}
// 	return 0, "", errors.New("Could not parse (edit) blog URL")
// }

func blogFromForm(id int64, s session) models.Blog {
	var blog models.Blog
	blog.Id = id
	blog.Title = s.req.FormValue("title")
	blog.Summary = s.req.FormValue("summary")
	blog.Content = s.req.FormValue("content")
	return blog
}
<commit_msg>Fixed bug in route order and removed dead code<commit_after>package web

import (
	"fmt"
	"log"
	"net/http"
	"strconv"

	"hectorcorrea.com/models"
	"hectorcorrea.com/viewModels"
)

var blogRouter Router

func blogPages(resp http.ResponseWriter, req *http.Request) {

	// This should be initialized only once, not on every call.
	// TODO: I also need a route with GET /blog/:title to handle legacy routes
	blogRouter.Add("GET", "/blog/:title/:id", blogViewOne)
	blogRouter.Add("GET", "/blog/", blogViewAll)
	blogRouter.Add("POST", "/blog/:title/:id/edit", blogEdit)
	blogRouter.Add("POST", "/blog/:title/:id/save", blogSave)
	blogRouter.Add("POST", "/blog/:title/:id/post", blogPost)
	blogRouter.Add("POST", "/blog/:title/:id/draft", blogDraft)
	blogRouter.Add("POST", "/blog/new", blogNew)

	session := newSession(resp, req)
	found, route := blogRouter.FindRoute(req.Method, req.URL.Path)
	if found {
		values := route.UrlValues(req.URL.Path)
		route.handler(session, values)
	} else {
		renderNotFound(session)
	}
}

func blogViewOne(s session, values map[string]string) {
	id := idFromString(values["id"])
	log.Println(values)
	if id == 0 {
		renderError(s, "No Blog ID was received", nil)
		return
	}

	log.Printf("Loading %d", id)
	blog, err := models.BlogGetById(id)
	if err != nil {
		renderError(s, "Fetching by ID", err)
		return
	}

	vm := viewModels.FromBlog(blog, s.toViewModel())
	renderTemplate(s, "views/blogView.html", vm)
}

func blogViewAll(s session, values map[string]string) {
	log.Printf("Loading all...")
	if blogs, err := models.BlogGetAll(); err != nil {
		renderError(s, "Error fetching all", err)
	} else {
		vm := viewModels.FromBlogs(blogs, s.toViewModel())
		renderTemplate(s, "views/blogList.html", vm)
	}
}

func blogSave(s session, values map[string]string) {

	// TODO: handle auth on all POST actions
	// 	if !s.isAuth() {
	// 		renderNotAuthorized(s)
	// 		return
	// 	}
	//

	id := idFromString(values["id"])
	blog := blogFromForm(id, s)
	if err := blog.Save(); err != nil {
		renderError(s, fmt.Sprintf("Saving blog ID: %d"), err)
	} else {
		url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
		log.Printf("Redirect to %s", url)
		http.Redirect(s.resp, s.req, url, 301)
	}
}

func blogNew(s session, values map[string]string) {
	newId, err := models.SaveNew()
	if err != nil {
		renderError(s, fmt.Sprintf("Error creating new blog"), err)
		return
	}
	log.Printf("Redirect to (edit for new) %d", newId)
	values["id"] = fmt.Sprintf("%d", newId)
	blogEdit(s, values)
}

func blogDraft(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	blog, err := models.MarkAsDraft(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Mark as draft: %d", id), err)
		return
	}

	url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
	log.Printf("Marked as draft: %s", url)
	http.Redirect(s.resp, s.req, url, 301)
}

func blogPost(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	blog, err := models.MarkAsPosted(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Mark as posted: %d", id), err)
		return
	}

	url := fmt.Sprintf("/blog/%s/%d", blog.Slug, id)
	log.Printf("Mark as posted: %s", url)
	http.Redirect(s.resp, s.req, url, 301)
}

func blogEdit(s session, values map[string]string) {
	id := idFromString(values["id"])
	if id == 0 {
		renderError(s, "No blog ID was received", nil)
		return
	}

	log.Printf("Loading %d", id)
	blog, err := models.BlogGetById(id)
	if err != nil {
		renderError(s, fmt.Sprintf("Loading ID: %d", id), err)
		return
	}

	vm := viewModels.FromBlog(blog, s.toViewModel())
	renderTemplate(s, "views/blogEdit.html", vm)
}

func idFromString(str string) int64 {
	id, _ := strconv.ParseInt(str, 10, 64)
	return id
}

func blogFromForm(id int64, s session) models.Blog {
	var blog models.Blog
	blog.Id = id
	blog.Title = s.req.FormValue("title")
	blog.Summary = s.req.FormValue("summary")
	blog.Content = s.req.FormValue("content")
	return blog
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"os"

	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/render"
	"github.com/jingweno/travisarchive/filestore"
	"github.com/joho/godotenv"
)

func init() {
	godotenv.Load("../.env")
}

func main() {
	fs, err := filestore.New("s3")
	if err != nil {
		log.Fatal(err)
	}

	port := os.Getenv("PORT")
	m := martini.Classic()
	m.Map(fs)
	m.Use(martini.Static("../web/public"))
	m.Use(render.Renderer(render.Options{
		Directory: "../web/templates",
		Layout:    "layout",
	}))
	m.Get("/", func(fs *filestore.S3, r render.Render) {
		files, err := fs.List("builds")
		if err != nil {
			log.Fatal(err)
		}

		r.HTML(200, "home", files)
	})

	log.Printf("starting server at %s", port)
	err = http.ListenAndServe(":"+port, m)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Sort files by time<commit_after>package main

import (
	"log"
	"net/http"
	"os"
	"sort"

	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/render"
	"github.com/jingweno/travisarchive/filestore"
	"github.com/joho/godotenv"
)

type ByTime []filestore.File

func (t ByTime) Len() int           { return len(t) }
func (t ByTime) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t ByTime) Less(i, j int) bool { return t[i].Time.Before(t[j].Time) }

func init() {
	godotenv.Load("../.env")
}

func main() {
	fs, err := filestore.New("s3")
	if err != nil {
		log.Fatal(err)
	}

	port := os.Getenv("PORT")
	m := martini.Classic()
	m.Map(fs)
	m.Use(martini.Static("../web/public"))
	m.Use(render.Renderer(render.Options{
		Directory: "../web/templates",
		Layout:    "layout",
	}))
	m.Get("/", func(fs *filestore.S3, r render.Render) {
		files, err := fs.List("builds")
		sort.Sort(ByTime(files))
		if err != nil {
			log.Fatal(err)
		}

		r.HTML(200, "home", files)
	})

	log.Printf("starting server at %s", port)
	err = http.ListenAndServe(":"+port, m)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, <Jose Luis Vázquez González> josvazg@gmail.com

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 main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"path"
)

const (
	PREFIX="/webshare/"
)

// currentDir returns the current directory or makes the program fail
func currentDir() string {
	dir,err:=os.Getwd()
	if err!=nil {
		log.Fatal("Can't get working directory!")
	}
	return dir
}

// Abs gets the absolute path from name
func Abs(name string) (string, error) {
	if path.IsAbs(name) {
		return name, nil
	}
	wd, err := os.Getwd()
	return path.Join(wd, name), err
}

func main() {
	// Load command line config
	var prefix,dir string
	var port int
	flag.StringVar(&prefix,"prefix", "", "Web prefix before accesing the shared files")
	flag.StringVar(&dir,"dir",currentDir(),"Local directory to be shared on the web")
	flag.IntVar(&port,"port",80,"Port to share the files from HTTP")
	flag.Parse()

	// Check directory
	dir,err:=Abs(dir)
	if err != nil {
		log.Fatal("Can't open: ", err)
	}

	// prefix defaults to the last name of the shared directory
	if prefix=="" {
		if dir=="/" {
			prefix=PREFIX
		} else {
			prefix="/"+path.Base(dir)+"/"
		}
	}

	// Advertise configuration loaded
	fmt.Printf("WebShare directory %s from :%v%s...\n",dir,port,prefix)

	// Serve files...
	http.Handle(prefix, http.StripPrefix(prefix, http.FileServer(http.Dir(dir))))
	err = http.ListenAndServe(fmt.Sprintf(":%v",port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}<commit_msg>Using filepath instead of path fixes path errors appeared on Windows<commit_after>/*
Copyright (c) 2012, <Jose Luis Vázquez González> josvazg@gmail.com

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 main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
)

const (
	PREFIX="/webshare/"
)

// currentDir returns the current directory or makes the program fail
func currentDir() string {
	dir,err:=os.Getwd()
	if err!=nil {
		log.Fatal("Can't get working directory!")
	}
	return dir
}

func main() {
	// Load command line config
	var prefix,dir string
	var port int
	flag.StringVar(&prefix,"prefix", "", "Web prefix before accesing the shared files")
	flag.StringVar(&dir,"dir",currentDir(),"Local directory to be shared on the web")
	flag.IntVar(&port,"port",80,"Port to share the files from HTTP")
	flag.Parse()

	// Check directory
	dir,err:=filepath.Abs(dir)
	if err != nil {
		log.Fatal("Can't open: ", err)
	}

	// prefix defaults to the last name of the shared directory
	if prefix=="" {
		if dir=="/" {
			prefix=PREFIX
		} else {
			prefix="/"+filepath.Base(dir)+"/"
		}
	}

	// Advertise configuration loaded
	fmt.Printf("WebShare directory %s from :%v%s...\n",dir,port,prefix)

	// Serve files...
	http.Handle(prefix, http.StripPrefix(prefix, http.FileServer(http.Dir(dir))))
	err = http.ListenAndServe(fmt.Sprintf(":%v",port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}<|endoftext|>