<commit_before>// The MIT License (MIT)

// Copyright (c) 2014-2016 Philip O'Toole

// 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 rqlite is a distributed system that provides a replicated SQLite database. rqlite uses Raft to achieve consensus across the cluster of SQLite databases. It ensures that every change made to the database is made to a majority of underlying SQLite files, or none at all.
*/
package rqlite
<commit_msg>Force failure to check 'go fmt' test<commit_after>// The MIT License (MIT)

// Copyright (c) 2014-2016 Philip O'Toole

// 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 rqlite is a distributed system that provides a replicated SQLite database. rqlite uses Raft to achieve consensus across the cluster of SQLite databases. It ensures that every change made to the database is made to a majority of underlying SQLite files, or none at all.
*/
package     rqlite
<|endoftext|>


<commit_before>/*
See LICENSE file for license details
Copyright (c) 2015 XOR Data Exchange, Inc.

Superdog - the Crypto library for Vault from Hashicorp

Superdog is a library for managing strong cryptography in both development and test environments.  Superdog provides an elegant wrapper to the Vault(https://www.vaultproject.io) API that allows you to manage your cryptographic keys in Vault using any code that implements the `KeyProvider` interface.  An implemention of the `KeyProvider` interface is provided for Vault, but others could be supported.

Features

-  Versioned Keys - Key version is stored as the first few bytes of the encrypted text
-  Key Rotation - Rotate your keys safely, knowing that you'll always be able to decrypt older versionss
-  Development implementation for tests and local development
-  Versioned and Rotated IV/Salt - `SaltProvider` interface works the same as `KeyProvider` to allow development and testing access to the crypto libraries without requiring a live Key (Vault) server
-  `Reencrypt` function to simplify key rotation, decrypts with given key, reencrypts with latest key

Cypher Suites

`superdog` supports AES encryption with CFB/CTR/GCM/OFB modes.

Production Usage
By default, `superdog` uses the `DevKeyProvider` which is a static key with static IV.  This is extremely insecure, and SHOULD NOT ever be used in production.

We reccommend using Go's [build tags](https://golang.org/pkg/go/build/) to enable strong cryptography in production usage.

Create a file with your connection routines in the init() function.  Add the build tag `// +build production` to the top of that file.

// +build production

package main
import (
	"github.com/xordataexchange/superdog"
	"github.com/xordataexxchange/superdog/vault/hashi"
	"github.com/hashicorp/vault/api"
)

// Assign each application a unique UUID
// and use Vault's AppID authentication mechanism
const (
	appid = "SOME RANDOM UUID"
)

func init() {
	user := os.Getenv("VAULT_USER")
	vaultaddr := os.Getenv("VAULT_ADDRESS")
	// TEST these for empty strings & handle appropriately in your code

	cfg:= api.DefaultConfig()
	cfg.Address = vaultaddr

	vault, err := hashi.NewVault(cfg)
	if err != nil {
		// handle appropriately
	}
	err = vault.AuthAppID(appid, user)
	if err != nil {
		// handle appropriately
	}

	crypto.DefaultKeyProvider = vault
	crypto.DefaultSaltProvider = vault

}

Now compile your program with `go build -tags production` to include this code.  The `KeyProvider` will be set to use Vault.

*/
package superdog
<commit_msg>examples and godoc<commit_after>/*
See LICENSE file for license details
Copyright (c) 2015 XOR Data Exchange, Inc.

Superdog - the Crypto library for Vault from Hashicorp

Superdog is a library for managing strong cryptography in both development and test environments.  Superdog provides an elegant wrapper to the Vault(https://www.vaultproject.io) API that allows you to manage your cryptographic keys in Vault using any code that implements the `KeyProvider` interface.  An implemention of the `KeyProvider` interface is provided for Vault, but others could be supported.

Features

-  Versioned Keys - Key version is stored as the first few bytes of the encrypted text
-  Key Rotation - Rotate your keys safely, knowing that you'll always be able to decrypt older versionss
-  Development implementation for tests and local development
-  Versioned and Rotated IV/Salt - `SaltProvider` interface works the same as `KeyProvider` to allow development and testing access to the crypto libraries without requiring a live Key (Vault) server
-  `Reencrypt` function to simplify key rotation, decrypts with given key, reencrypts with latest key

Cypher Suites

`superdog` supports AES encryption with CFB/CTR/GCM/OFB modes.

Production Usage
By default, `superdog` uses the `DevKeyProvider` which is a static key with static IV.  This is extremely insecure, and SHOULD NOT ever be used in production.

We reccommend using Go's [build tags](https://golang.org/pkg/go/build/) to enable strong cryptography in production usage.

Create a file with your connection routines in the init() function.  Add the build tag `// +build production` to the top of that file.

	// +build production

	package main
	import (
		"github.com/xordataexchange/superdog"
		"github.com/xordataexxchange/superdog/vault/hashi"
		"github.com/hashicorp/vault/api"
	)

	// Assign each application a unique UUID
	// and use Vault's AppID authentication mechanism
	const (
		appid = "SOME RANDOM UUID"
	)

	func init() {
		user := os.Getenv("VAULT_USER")
		vaultaddr := os.Getenv("VAULT_ADDRESS")
		// TEST these for empty strings & handle appropriately in your code
		cfg:= api.DefaultConfig()
		cfg.Address = vaultaddr
		vault, err := hashi.NewVault(cfg)
		if err != nil {
			// handle appropriately
		}
		err = vault.AuthAppID(appid, user)
		if err != nil {
			// handle appropriately
		}
		crypto.DefaultKeyProvider = vault
		crypto.DefaultSaltProvider = vault
	}

Now compile your program with `go build -tags production` to include this code.  The `KeyProvider` will be set to use Vault.

*/
package superdog
<|endoftext|>


<commit_before>// Copyright 2013 The Gorilla WebSocket 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 websocket implements the WebSocket protocol defined in RFC 6455.
//
// Overview
//
// The Conn type represents a WebSocket connection. A server application uses
// the Upgrade function from an Upgrader object with a HTTP request handler
// to get a pointer to a Conn:
//
//  var upgrader = websocket.Upgrader{
//      ReadBufferSize:  1024,
//      WriteBufferSize: 1024,
//  }
//
//  func handler(w http.ResponseWriter, r *http.Request) {
//      conn, err := upgrader.Upgrade(w, r, nil)
//      if err != nil {
//          log.Println(err)
//          return
//      }
//      ... Use conn to send and receive messages.
//  }
//
// Call the connection's WriteMessage and ReadMessage methods to send and
// receive messages as a slice of bytes. This snippet of code shows how to echo
// messages using these methods:
//
//  for {
//      messageType, p, err := conn.ReadMessage()
//      if err != nil {
//          return
//      }
//      if err = conn.WriteMessage(messageType, p); err != nil {
//          return err
//      }
//  }
//
// In above snippet of code, p is a []byte and messageType is an int with value
// websocket.BinaryMessage or websocket.TextMessage.
//
// An application can also send and receive messages using the io.WriteCloser
// and io.Reader interfaces. To send a message, call the connection NextWriter
// method to get an io.WriteCloser, write the message to the writer and close
// the writer when done. To receive a message, call the connection NextReader
// method to get an io.Reader and read until io.EOF is returned. This snippet
// shows how to echo messages using the NextWriter and NextReader methods:
//
//  for {
//      messageType, r, err := conn.NextReader()
//      if err != nil {
//          return
//      }
//      w, err := conn.NextWriter(messageType)
//      if err != nil {
//          return err
//      }
//      if _, err := io.Copy(w, r); err != nil {
//          return err
//      }
//      if err := w.Close(); err != nil {
//          return err
//      }
//  }
//
// Data Messages
//
// The WebSocket protocol distinguishes between text and binary data messages.
// Text messages are interpreted as UTF-8 encoded text. The interpretation of
// binary messages is left to the application.
//
// This package uses the TextMessage and BinaryMessage integer constants to
// identify the two data message types. The ReadMessage and NextReader methods
// return the type of the received message. The messageType argument to the
// WriteMessage and NextWriter methods specifies the type of a sent message.
//
// It is the application's responsibility to ensure that text messages are
// valid UTF-8 encoded text.
//
// Control Messages
//
// The WebSocket protocol defines three types of control messages: close, ping
// and pong. Call the connection WriteControl, WriteMessage or NextWriter
// methods to send a control message to the peer.
//
// Connections handle received close messages by sending a close message to the
// peer and returning a *CloseError from the the NextReader, ReadMessage or the
// message Read method.
//
// Connections handle received ping and pong messages by invoking callback
// functions set with SetPingHandler and SetPongHandler methods. The callback
// functions are called from the NextReader, ReadMessage and the message Read
// methods.
//
// The default ping handler sends a pong to the peer. The application's reading
// goroutine can block for a short time while the handler writes the pong data
// to the connection.
//
// The application must read the connection to process ping, pong and close
// messages sent from the peer. If the application is not otherwise interested
// in messages from the peer, then the application should start a goroutine to
// read and discard messages from the peer. A simple example is:
//
//  func readLoop(c *websocket.Conn) {
//      for {
//          if _, _, err := c.NextReader(); err != nil {
//              c.Close()
//              break
//          }
//      }
//  }
//
// Concurrency
//
// Connections support one concurrent reader and one concurrent writer.
//
// Applications are responsible for ensuring that no more than one goroutine
// calls the write methods (NextWriter, SetWriteDeadline, WriteMessage,
// WriteJSON) concurrently and that no more than one goroutine calls the read
// methods (NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler,
// SetPingHandler) concurrently.
//
// The Close and WriteControl methods can be called concurrently with all other
// methods.
//
// Origin Considerations
//
// Web browsers allow Javascript applications to open a WebSocket connection to
// any host. It's up to the server to enforce an origin policy using the Origin
// request header sent by the browser.
//
// The Upgrader calls the function specified in the CheckOrigin field to check
// the origin. If the CheckOrigin function returns false, then the Upgrade
// method fails the WebSocket handshake with HTTP status 403.
//
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
// the handshake if the Origin request header is present and not equal to the
// Host request header.
//
// An application can allow connections from any origin by specifying a
// function that always returns true:
//
//  var upgrader = websocket.Upgrader{
//      CheckOrigin: func(r *http.Request) bool { return true },
//  }
//
// The deprecated Upgrade function does not enforce an origin policy. It's the
// application's responsibility to check the Origin header before calling
// Upgrade.
//
// Compression
//
// Per message compression extensions (RFC 7692) are experimentally supported
// by this package in a limited capacity. Setting the EnableCompression option
// to true in Dialer or Upgrader will attempt to negotiate per message deflate
// support. If compression was successfully negotiated with the connection's
// peer, any message received in compressed form will be automatically
// decompressed. All Read methods will return uncompressed bytes.
//
// Per message compression of messages written to a connection can be enabled
// or disabled by calling the corresponding Conn method:
//
//  conn.EnableWriteCompression(true)
//
// Currently this package does not support compression with "context takeover".
// This means that messages must be compressed and decompressed in isolation,
// without retaining sliding window or dictionary state across messages. For
// more details refer to RFC 7692.
//
// Use of compression is experimental and may result in decreased performance.
package websocket
<commit_msg>Update compression documentation<commit_after>// Copyright 2013 The Gorilla WebSocket 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 websocket implements the WebSocket protocol defined in RFC 6455.
//
// Overview
//
// The Conn type represents a WebSocket connection. A server application uses
// the Upgrade function from an Upgrader object with a HTTP request handler
// to get a pointer to a Conn:
//
//  var upgrader = websocket.Upgrader{
//      ReadBufferSize:  1024,
//      WriteBufferSize: 1024,
//  }
//
//  func handler(w http.ResponseWriter, r *http.Request) {
//      conn, err := upgrader.Upgrade(w, r, nil)
//      if err != nil {
//          log.Println(err)
//          return
//      }
//      ... Use conn to send and receive messages.
//  }
//
// Call the connection's WriteMessage and ReadMessage methods to send and
// receive messages as a slice of bytes. This snippet of code shows how to echo
// messages using these methods:
//
//  for {
//      messageType, p, err := conn.ReadMessage()
//      if err != nil {
//          return
//      }
//      if err = conn.WriteMessage(messageType, p); err != nil {
//          return err
//      }
//  }
//
// In above snippet of code, p is a []byte and messageType is an int with value
// websocket.BinaryMessage or websocket.TextMessage.
//
// An application can also send and receive messages using the io.WriteCloser
// and io.Reader interfaces. To send a message, call the connection NextWriter
// method to get an io.WriteCloser, write the message to the writer and close
// the writer when done. To receive a message, call the connection NextReader
// method to get an io.Reader and read until io.EOF is returned. This snippet
// shows how to echo messages using the NextWriter and NextReader methods:
//
//  for {
//      messageType, r, err := conn.NextReader()
//      if err != nil {
//          return
//      }
//      w, err := conn.NextWriter(messageType)
//      if err != nil {
//          return err
//      }
//      if _, err := io.Copy(w, r); err != nil {
//          return err
//      }
//      if err := w.Close(); err != nil {
//          return err
//      }
//  }
//
// Data Messages
//
// The WebSocket protocol distinguishes between text and binary data messages.
// Text messages are interpreted as UTF-8 encoded text. The interpretation of
// binary messages is left to the application.
//
// This package uses the TextMessage and BinaryMessage integer constants to
// identify the two data message types. The ReadMessage and NextReader methods
// return the type of the received message. The messageType argument to the
// WriteMessage and NextWriter methods specifies the type of a sent message.
//
// It is the application's responsibility to ensure that text messages are
// valid UTF-8 encoded text.
//
// Control Messages
//
// The WebSocket protocol defines three types of control messages: close, ping
// and pong. Call the connection WriteControl, WriteMessage or NextWriter
// methods to send a control message to the peer.
//
// Connections handle received close messages by sending a close message to the
// peer and returning a *CloseError from the the NextReader, ReadMessage or the
// message Read method.
//
// Connections handle received ping and pong messages by invoking callback
// functions set with SetPingHandler and SetPongHandler methods. The callback
// functions are called from the NextReader, ReadMessage and the message Read
// methods.
//
// The default ping handler sends a pong to the peer. The application's reading
// goroutine can block for a short time while the handler writes the pong data
// to the connection.
//
// The application must read the connection to process ping, pong and close
// messages sent from the peer. If the application is not otherwise interested
// in messages from the peer, then the application should start a goroutine to
// read and discard messages from the peer. A simple example is:
//
//  func readLoop(c *websocket.Conn) {
//      for {
//          if _, _, err := c.NextReader(); err != nil {
//              c.Close()
//              break
//          }
//      }
//  }
//
// Concurrency
//
// Connections support one concurrent reader and one concurrent writer.
//
// Applications are responsible for ensuring that no more than one goroutine
// calls the write methods (NextWriter, SetWriteDeadline, WriteMessage,
// WriteJSON) concurrently and that no more than one goroutine calls the read
// methods (NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler,
// SetPingHandler) concurrently.
//
// The Close and WriteControl methods can be called concurrently with all other
// methods.
//
// Origin Considerations
//
// Web browsers allow Javascript applications to open a WebSocket connection to
// any host. It's up to the server to enforce an origin policy using the Origin
// request header sent by the browser.
//
// The Upgrader calls the function specified in the CheckOrigin field to check
// the origin. If the CheckOrigin function returns false, then the Upgrade
// method fails the WebSocket handshake with HTTP status 403.
//
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
// the handshake if the Origin request header is present and not equal to the
// Host request header.
//
// An application can allow connections from any origin by specifying a
// function that always returns true:
//
//  var upgrader = websocket.Upgrader{
//      CheckOrigin: func(r *http.Request) bool { return true },
//  }
//
// The deprecated Upgrade function does not enforce an origin policy. It's the
// application's responsibility to check the Origin header before calling
// Upgrade.
//
// Compression EXPERIMENTAL
//
// Per message compression extensions (RFC 7692) are experimentally supported
// by this package in a limited capacity. Setting the EnableCompression option
// to true in Dialer or Upgrader will attempt to negotiate per message deflate
// support. If compression was successfully negotiated with the connection's
// peer, any message received in compressed form will be automatically
// decompressed. All Read methods will return uncompressed bytes.
//
// Per message compression of messages written to a connection can be enabled
// or disabled by calling the corresponding Conn method:
//
//  conn.EnableWriteCompression(true)
//
// Currently this package does not support compression with "context takeover".
// This means that messages must be compressed and decompressed in isolation,
// without retaining sliding window or dictionary state across messages. For
// more details refer to RFC 7692.
//
// Use of compression is experimental and may result in decreased performance.
package websocket
<|endoftext|>


<commit_before>// Package statuscake implements a client for statuscake.com API.
//
//  // list all `Tests`
//  c, err := statuscake.New(statuscake.Auth{Username: username, Apikey: apikey})
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  tests, err := c.Tests().All()
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  v := url.Values{}
//  v.Set("tags", "test1,test2")
//  testsWithFilter, err := c.Tests().AllWithFilter(v)
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  // delete a `Test`
//  err = c.Tests().Delete(TestID)
//
//  // create a test
//  t := &statuscake.Test{
//    WebsiteName: "Foo",
//    WebsiteURL:  "htto://example.com",
//    ... other required args...
//  }
//
//  if err = t.Validate(); err != nil {
//    log.Fatal(err)
//  }
//
//  t2 := c.Tests().Update(t)
//  fmt.Printf("New Test created with id: %d\n", t2.TestID)
//
//  // get Tests details
//  t, err := tt.Detail(id)
//  ...
package statuscake
<commit_msg>Fix doc, Update returns an error<commit_after>// Package statuscake implements a client for statuscake.com API.
//
//  // list all `Tests`
//  c, err := statuscake.New(statuscake.Auth{Username: username, Apikey: apikey})
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  tests, err := c.Tests().All()
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  v := url.Values{}
//  v.Set("tags", "test1,test2")
//  testsWithFilter, err := c.Tests().AllWithFilter(v)
//  if err != nil {
//    log.Fatal(err)
//  }
//
//  // delete a `Test`
//  err = c.Tests().Delete(TestID)
//
//  // create a test
//  t := &statuscake.Test{
//    WebsiteName: "Foo",
//    WebsiteURL:  "htto://example.com",
//    ... other required args...
//  }
//
//  if err = t.Validate(); err != nil {
//    log.Fatal(err)
//  }
//
//  t2, err := c.Tests().Update(t)
//  if err != nil {
//    log.Fatal(err)
//  }
//  fmt.Printf("New Test created with id: %d\n", t2.TestID)
//
//  // get Tests details
//  t, err := tt.Detail(id)
//  ...
package statuscake
<|endoftext|>


<commit_before>/*
Package core provides a pure handlers (or middlewares) stack so you can perform actions downstream, then filter and manipulate the response upstream.

The handlers stack

A handler is a function that receives a context.
It can be registered with Use and has the possibility to break the stream or to continue with the next handler in the stack.

Example of a logger followed by the response writing:

	// Log
	core.Use(func(c *core.Context) {
		start := time.Now()                                                           // Before the response.
		c.Next()                                                                      // Execute the next handler in the stack (in this case, the response).
		log.Printf(" %s  %s  %s", c.Request.Method, c.Request.URL, time.Since(start)) // After the response.
	})

	// Response
	core.Use(func(c *core.Context) {
		fmt.Fprint(c.ResponseWriter, "Hello, World!")
	})

	// Run server
	core.Run()

When using Run, your app is reachable at http://localhost:8080 by default.

If you need more flexibility, you can make a new handlers stack, which is fully compatible with the net/http.Handler interface:

	hs := core.NewHandlersStack()

	hs.Use(func(c *core.Context) {
		fmt.Fprint(c.ResponseWriter, "Hello, World!")
	})

	http.ListenAndServe(":8080", hs)

Here is the visualization of the serving flow when using log, secure and compress handlers:

	request open
	  |- log start
	  |--- secure start
	  |----- compress start
	  |------- response write
	  |----- compress end
	  |--- secure end
	  |- log end
	request close

Flags

These flags are preset:

	-address
		The address to listen and serving on.
		Value is saved in Address.
	-production
		Run the server in production environment.
		Some third-party handlers may have different behaviors depending on the environment.
		Value is saved in Production.

It's up to you to call
	flag.Parse()
in your main function if you want to use them.

Panic recovering

When using Run, your server always recovers from panics, logs the error with stack, and sends a 500 Internal Server Error.
If you want to use a custom handler on panic, give one to HandlePanic.

Handlers and helpers

No handlers or helpers are bundled in the core: it does one thing and does it well.
That's why you need to import all and only the handlers or helpers you need:

	compress
		Clever response compressing
		https://godoc.org/github.com/volatile/compress
	cors
		Cross-Origin Resource Sharing support
		https://godoc.org/github.com/volatile/cors
	i18n
		Simple internationalization
		https://godoc.org/github.com/volatile/i18n
	log
		Requests logging
		https://godoc.org/github.com/volatile/log
	response
		Readable response helper
		https://godoc.org/github.com/volatile/response
	route
		Flexible routing helper
		https://godoc.org/github.com/volatile/route
	secure
		Quick security wins
		https://godoc.org/github.com/volatile/secure
	static
		Simple assets serving
		https://godoc.org/github.com/volatile/static
*/
package core
<commit_msg>Simplify doc<commit_after>/*
Package core provides a pure handlers (or middlewares) stack so you can perform actions downstream, then filter and manipulate the response upstream.

The handlers stack

A handler is a function that receives a context.
It can be registered with Use and has the possibility to break the stream or to continue with the next handler in the stack.

Example of a logger, followed security headers setting, followed by the response writing:

	// Log
	core.Use(func(c *core.Context) {
		start := time.Now()                                                           // Before the response.
		c.Next()                                                                      // Execute the next handler in the stack (in this case, security headers setter).
		log.Printf(" %s  %s  %s", c.Request.Method, c.Request.URL, time.Since(start)) // After the response.
	})

	// Secure
	core.Use(func(c *core.Context) {
		c.ResponseWriter.Header().Set("X-Frame-Options", "SAMEORIGIN")
		c.ResponseWriter.Header().Set("X-Content-Type-Options", "nosniff")
		c.ResponseWriter.Header().Set("X-XSS-Protection", "1; mode=block")

		c.Next() // Execute the next handler in the stack (in this case, the response writer).
	})

	// Response
	core.Use(func(c *core.Context) {
		fmt.Fprint(c.ResponseWriter, "Hello, World!")
	})

	// Run server
	core.Run()

A clearer visualization of this serving flow:

	request open
	  |- log start
	  |--- secure start
	  |----- response write
	  |--- secure start
	  |- log end
	request close

When using Run, your app is reachable at http://localhost:8080 by default.

If you need more flexibility, you can make a new handlers stack, which is fully compatible with the net/http.Handler interface:

	hs := core.NewHandlersStack()

	hs.Use(func(c *core.Context) {
		fmt.Fprint(c.ResponseWriter, "Hello, World!")
	})

	http.ListenAndServe(":8080", hs)

Flags

These flags are preset:

	-address
		The address to listen and serving on.
		Value is saved in Address.
	-production
		Run the server in production environment.
		Some third-party handlers may have different behaviors depending on the environment.
		Value is saved in Production.

It's up to you to call
	flag.Parse()
in your main function if you want to use them.

Panic recovering

When using Run, your server always recovers from panics, logs the error with stack, and sends a 500 Internal Server Error.
If you want to use a custom handler on panic, give one to HandlePanic.

Handlers and helpers

No handlers or helpers are bundled in the core: it does one thing and does it well.
That's why you need to import all and only the handlers or helpers you need:

	compress
		Clever response compressing
		https://godoc.org/github.com/volatile/compress
	cors
		Cross-Origin Resource Sharing support
		https://godoc.org/github.com/volatile/cors
	i18n
		Simple internationalization
		https://godoc.org/github.com/volatile/i18n
	log
		Requests logging
		https://godoc.org/github.com/volatile/log
	response
		Readable response helper
		https://godoc.org/github.com/volatile/response
	route
		Flexible routing helper
		https://godoc.org/github.com/volatile/route
	secure
		Quick security wins
		https://godoc.org/github.com/volatile/secure
	static
		Simple assets serving
		https://godoc.org/github.com/volatile/static
*/
package core
<|endoftext|>


<commit_before>// Package chalk is a package for styling terminal/console output.
// There are three main components:
//
//
// Colors
//
// There are eight default colors: black, red, green, yellow, blue,
// magenta, cyan and white. You can use them in two main ways
// (note the need for the reset color if you don't use Color()):
//
//   fmt.Println(chalk.Red, "this is red text", chalk.ResetColor)
//   fmt.Println(chalk.Red.Color("this is red text")
//
//
// TextStyles
//
// There are seven default text styles: bold, dim, italic, underline,
// inverse, hidden and strikethrough. Unlike colors, you should only
// really use TextStyles in the following manner:
//
//   fmt.Println(chalk.Bold.TextStyle("this is bold text"))
//
//
// Styles
//
// Styles are where all the business really is. Styles can have a
// foreground color, a background color and a text style (sweet!).
// They're also pretty simply to make, you just need a starting point:
//
//   blue := chalk.Blue.NewStyle()
//   bold := chalk.Bold.NewStyle()
//
// When a color is your starting point for a style, it will be the
// foreground color, when a style is your starting point, well, yeah,
// it's your style's text style. You can also alter a styles, foreground
// background or style in a builder-esque pattern.
//
//   blueOnWhite := blue.WithBackground(chalk.White)
//   awesomeness := blueOnWhite.WithTextStyle(chalk.Underline)
//
// Like both Colors and TextStyles you can style specific segments of text
// with:
//
//   fmt.Println(awesomeness.Style("this is so pretty!"))
//
// Like Colors, you can also print styles explicitly, but you'll need to
// reset your console's colors with chalk.Reset if you use them this way:
//
//   fmt.Println(awesomeness, "this is so pretty", chalk.Reset)
//
// Be aware though, that this (second) way of using styles will not add the
// text style (as they require more specific end codes). So if you want
// to fully utilize styles, use myStyle.Style().
//
// Have fun!
//
package chalk
<commit_msg>Fix typo and make example more explanatory<commit_after>// Package chalk is a package for styling terminal/console output.
// There are three main components:
//
//
// Colors
//
// There are eight default colors: black, red, green, yellow, blue,
// magenta, cyan and white. You can use them in two main ways
// (note the need for the reset color if you don't use Color()):
//
//   fmt.Println(chalk.Red, "this is red text", chalk.ResetColor)
//   fmt.Println(chalk.Red.Color("this is red text")
//
//
// TextStyles
//
// There are seven default text styles: bold, dim, italic, underline,
// inverse, hidden and strikethrough. Unlike colors, you should only
// really use TextStyles in the following manner:
//
//   fmt.Println(chalk.Bold.TextStyle("this is bold text"))
//
//
// Styles
//
// Styles are where all the business really is. Styles can have a
// foreground color, a background color and a text style (sweet!).
// They're also pretty simply to make, you just need a starting point:
//
//   blue := chalk.Blue.NewStyle()
//   bold := chalk.Bold.NewStyle()
//
// When a color is your starting point for a style, it will be the
// foreground color, when a style is your starting point, well, yeah,
// it's your style's text style. You can also alter a style's foreground,
// background or text style in a builder-esque pattern.
//
//   blueOnWhite := blue.WithBackground(chalk.White)
//   awesomeness := blueOnWhite.WithTextStyle(chalk.Underline).WithForeground(chalk.Green)
//
// Like both Colors and TextStyles you can style specific segments of text
// with:
//
//   fmt.Println(awesomeness.Style("this is so pretty!"))
//
// Like Colors, you can also print styles explicitly, but you'll need to
// reset your console's colors with chalk.Reset if you use them this way:
//
//   fmt.Println(awesomeness, "this is so pretty", chalk.Reset)
//
// Be aware though, that this (second) way of using styles will not add the
// text style (as text styles require more specific end codes). So if you want
// to fully utilize styles, use myStyle.Style() (unless you only care about
// print your text with a specific foreground and background, then printing
// the style is awesome too!).
//
// Have fun!
//
package chalk
<|endoftext|>


<commit_before>/*
Package sjson provides decoding of JSON Text as defined in ECMA-404.

Sjson is designed to be fast and simple, for now it supports only dynamic deserialization.
Simple benchmark test shows ~2x speedup against encoding/json standard parser.
	BenchmarkSimple   300000             10216 ns/op
	BenchmarkStd      200000             22413 ns/op

Links

Some useful links.
	* http://json.org - Info about JSON
	* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf - ECMA-404 specification
	* https://metacpan.org/pod/JSON%3A%3AXS - JSON::XS Perl module

Thanks

Development of the project was sponsored by CP Decision LLC (http://cpdecision.com)
as part of a project on processing statistical data.

Some ideas was borrowed from excellent Marc A. Lehmann's JSON::XS code.

*/
package sjson
<commit_msg>Fix docs again.<commit_after>/*
Package sjson provides decoding of JSON Text as defined in ECMA-404.

Sjson is designed to be fast and simple, for now it supports only dynamic deserialization.
Simple benchmark test shows ~2x speedup against encoding/json standard parser.
	BenchmarkSimple   300000             10216 ns/op
	BenchmarkStd      200000             22413 ns/op

Links

Some useful links.
	* http://json.org - Info about JSON
	* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf - ECMA-404 specification
	* https://metacpan.org/pod/JSON%3A%3AXS - JSON::XS Perl module

Thanks

Development of the project was sponsored by CP Decision Limited (http://cpdecision.com)
as part of a project on processing statistical data.

Some ideas was borrowed from excellent Marc A. Lehmann's JSON::XS code.

*/
package sjson
<|endoftext|>


<commit_before>package env

import (
	"encoding"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// nolint: gochecknoglobals
var (
	// ErrNotAStructPtr is returned if you pass something that is not a pointer to a
	// Struct to Parse
	ErrNotAStructPtr = errors.New("env: expected a pointer to a Struct")

	defaultBuiltInParsers = map[reflect.Kind]ParserFunc{
		reflect.Bool: func(v string) (interface{}, error) {
			return strconv.ParseBool(v)
		},
		reflect.String: func(v string) (interface{}, error) {
			return v, nil
		},
		reflect.Int: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int(i), err
		},
		reflect.Int16: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 16)
			return int16(i), err
		},
		reflect.Int32: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int32(i), err
		},
		reflect.Int64: func(v string) (interface{}, error) {
			return strconv.ParseInt(v, 10, 64)
		},
		reflect.Int8: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 8)
			return int8(i), err
		},
		reflect.Uint: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint(i), err
		},
		reflect.Uint16: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 16)
			return uint16(i), err
		},
		reflect.Uint32: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint32(i), err
		},
		reflect.Uint64: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 64)
			return i, err
		},
		reflect.Uint8: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 8)
			return uint8(i), err
		},
		reflect.Float64: func(v string) (interface{}, error) {
			return strconv.ParseFloat(v, 64)
		},
		reflect.Float32: func(v string) (interface{}, error) {
			f, err := strconv.ParseFloat(v, 32)
			return float32(f), err
		},
	}

	defaultTypeParsers = map[reflect.Type]ParserFunc{
		reflect.TypeOf(url.URL{}): func(v string) (interface{}, error) {
			u, err := url.Parse(v)
			if err != nil {
				return nil, fmt.Errorf("unable to parse URL: %v", err)
			}
			return *u, nil
		},
		reflect.TypeOf(time.Nanosecond): func(v string) (interface{}, error) {
			s, err := time.ParseDuration(v)
			if err != nil {
				return nil, fmt.Errorf("unable to parse duration: %v", err)
			}
			return s, err
		},
	}
)

// ParserFunc defines the signature of a function that can be used within `CustomParsers`
type ParserFunc func(v string) (interface{}, error)

// Options for the parser.
type Options struct {
	// Environment keys and values that will be accessible for the service.
	Environment map[string]string
	// TagName specifies another tagname to use rather than the default env.
	TagName string

	// Sets to true if we have already configured once.
	configured bool
}

// configure will do the basic configurations and defaults.
func configure(opts []Options) []Options {
	// If we have already configured the first item
	// of options will have been configured set to true.
	if len(opts) > 0 && opts[0].configured {
		return opts
	}

	// Created options with defaults.
	opt := Options{
		TagName:     "env",
		Environment: toMap(os.Environ()),
		configured:  true,
	}

	// Loop over all opts structs and set
	// to opt if value is not default/empty.
	for _, item := range opts {
		if item.Environment != nil {
			opt.Environment = item.Environment
		}
		if item.TagName != "" {
			opt.TagName = item.TagName
		}
	}

	return []Options{opt}
}

func toMap(env []string) map[string]string {
	r := map[string]string{}
	for _, e := range env {
		p := strings.SplitN(e, "=", 2)
		r[p[0]] = p[1]
	}
	return r
}

// getTagName returns the tag name.
func getTagName(opts []Options) string {
	return opts[0].TagName
}

// getEnvironment returns the environment map.
func getEnvironment(opts []Options) map[string]string {
	return opts[0].Environment
}

// Parse parses a struct containing `env` tags and loads its values from
// environment variables.
func Parse(v interface{}, opts ...Options) error {
	return ParseWithFuncs(v, map[reflect.Type]ParserFunc{}, opts...)
}

// ParseWithFuncs is the same as `Parse` except it also allows the user to pass
// in custom parsers.
func ParseWithFuncs(v interface{}, funcMap map[reflect.Type]ParserFunc, opts ...Options) error {
	opts = configure(opts)

	ptrRef := reflect.ValueOf(v)
	if ptrRef.Kind() != reflect.Ptr {
		return ErrNotAStructPtr
	}
	ref := ptrRef.Elem()
	if ref.Kind() != reflect.Struct {
		return ErrNotAStructPtr
	}
	var parsers = defaultTypeParsers
	for k, v := range funcMap {
		parsers[k] = v
	}

	return doParse(ref, parsers, opts)
}

func doParse(ref reflect.Value, funcMap map[reflect.Type]ParserFunc, opts []Options) error {
	var refType = ref.Type()

	for i := 0; i < refType.NumField(); i++ {
		refField := ref.Field(i)
		if !refField.CanSet() {
			continue
		}
		if reflect.Ptr == refField.Kind() && !refField.IsNil() {
			err := ParseWithFuncs(refField.Interface(), funcMap, opts...)
			if err != nil {
				return err
			}
			continue
		}
		if reflect.Struct == refField.Kind() && refField.CanAddr() && refField.Type().Name() == "" {
			err := Parse(refField.Addr().Interface(), opts...)
			if err != nil {
				return err
			}
			continue
		}
		refTypeField := refType.Field(i)
		value, err := get(refTypeField, opts)
		if err != nil {
			return err
		}
		if value == "" {
			if reflect.Struct == refField.Kind() {
				if err := doParse(refField, funcMap, opts); err != nil {
					return err
				}
			}
			continue
		}
		if err := set(refField, refTypeField, value, funcMap); err != nil {
			return err
		}
	}
	return nil
}

func get(field reflect.StructField, opts []Options) (val string, err error) {
	var required bool
	var exists bool
	var loadFile bool
	var expand = strings.EqualFold(field.Tag.Get("envExpand"), "true")

	key, tags := parseKeyForOption(field.Tag.Get(getTagName(opts)))

	for _, tag := range tags {
		switch tag {
		case "":
			break
		case "file":
			loadFile = true
		case "required":
			required = true
		default:
			return "", fmt.Errorf("env: tag option %q not supported", tag)
		}
	}

	defaultValue, defExists := field.Tag.Lookup("envDefault")
	if key == "" {
		if defExists {
			return defaultValue, nil
		}
		return "", nil
	}

	val, exists = getOr(key, defaultValue, defExists, getEnvironment(opts))

	if expand {
		val = os.ExpandEnv(val)
	}

	if required && !exists {
		return "", fmt.Errorf(`env: required environment variable %q is not set`, key)
	}

	if loadFile && val != "" {
		filename := val
		val, err = getFromFile(filename)
		if err != nil {
			return "", fmt.Errorf(`env: could not load content of file "%s" from variable %s: %v`, filename, key, err)
		}
	}

	return val, err
}

// split the env tag's key into the expected key and desired option, if any.
func parseKeyForOption(key string) (string, []string) {
	opts := strings.Split(key, ",")
	return opts[0], opts[1:]
}

func getFromFile(filename string) (value string, err error) {
	b, err := ioutil.ReadFile(filename)
	return string(b), err
}

func getOr(key, defaultValue string, defExists bool, envs map[string]string) (value string, exists bool) {
	value, exists = envs[key]
	switch {
	case !exists && defExists:
		return defaultValue, true
	case !exists:
		return "", false
	}

	return value, true
}

func set(field reflect.Value, sf reflect.StructField, value string, funcMap map[reflect.Type]ParserFunc) error {
	var tm = asTextUnmarshaler(field)
	if tm != nil {
		if err := tm.UnmarshalText([]byte(value)); err != nil {
			return newParseError(sf, err)
		}
		return nil
	}

	var typee = sf.Type
	var fieldee = field
	if typee.Kind() == reflect.Ptr {
		typee = typee.Elem()
		fieldee = field.Elem()
	}

	parserFunc, ok := funcMap[typee]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}

		fieldee.Set(reflect.ValueOf(val))
		return nil
	}

	parserFunc, ok = defaultBuiltInParsers[typee.Kind()]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}

		fieldee.Set(reflect.ValueOf(val).Convert(typee))
		return nil
	}

	if field.Kind() == reflect.Slice {
		return handleSlice(field, value, sf, funcMap)
	}

	return newNoParserError(sf)
}

func handleSlice(field reflect.Value, value string, sf reflect.StructField, funcMap map[reflect.Type]ParserFunc) error {
	var separator = sf.Tag.Get("envSeparator")
	if separator == "" {
		separator = ","
	}
	var parts = strings.Split(value, separator)

	var typee = sf.Type.Elem()
	if typee.Kind() == reflect.Ptr {
		typee = typee.Elem()
	}

	if _, ok := reflect.New(typee).Interface().(encoding.TextUnmarshaler); ok {
		return parseTextUnmarshalers(field, parts, sf)
	}

	parserFunc, ok := funcMap[typee]
	if !ok {
		parserFunc, ok = defaultBuiltInParsers[typee.Kind()]
		if !ok {
			return newNoParserError(sf)
		}
	}

	var result = reflect.MakeSlice(sf.Type, 0, len(parts))
	for _, part := range parts {
		r, err := parserFunc(part)
		if err != nil {
			return newParseError(sf, err)
		}
		var v = reflect.ValueOf(r).Convert(typee)
		if sf.Type.Elem().Kind() == reflect.Ptr {
			v = reflect.New(typee)
			v.Elem().Set(reflect.ValueOf(r).Convert(typee))
		}
		result = reflect.Append(result, v)
	}
	field.Set(result)
	return nil
}

func asTextUnmarshaler(field reflect.Value) encoding.TextUnmarshaler {
	if reflect.Ptr == field.Kind() {
		if field.IsNil() {
			field.Set(reflect.New(field.Type().Elem()))
		}
	} else if field.CanAddr() {
		field = field.Addr()
	}

	tm, ok := field.Interface().(encoding.TextUnmarshaler)
	if !ok {
		return nil
	}
	return tm
}

func parseTextUnmarshalers(field reflect.Value, data []string, sf reflect.StructField) error {
	s := len(data)
	elemType := field.Type().Elem()
	slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s)
	for i, v := range data {
		sv := slice.Index(i)
		kind := sv.Kind()
		if kind == reflect.Ptr {
			sv = reflect.New(elemType.Elem())
		} else {
			sv = sv.Addr()
		}
		tm := sv.Interface().(encoding.TextUnmarshaler)
		if err := tm.UnmarshalText([]byte(v)); err != nil {
			return newParseError(sf, err)
		}
		if kind == reflect.Ptr {
			slice.Index(i).Set(sv)
		}
	}

	field.Set(slice)

	return nil
}

func newParseError(sf reflect.StructField, err error) error {
	if err == nil {
		return nil
	}
	return parseError{
		sf:  sf,
		err: err,
	}
}

type parseError struct {
	sf  reflect.StructField
	err error
}

func (e parseError) Error() string {
	return fmt.Sprintf(`env: parse error on field "%s" of type "%s": %v`, e.sf.Name, e.sf.Type, e.err)
}

func newNoParserError(sf reflect.StructField) error {
	return fmt.Errorf(`env: no parser found for field "%s" of type "%s"`, sf.Name, sf.Type)
}
<commit_msg>refactor: improve if<commit_after>package env

import (
	"encoding"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// nolint: gochecknoglobals
var (
	// ErrNotAStructPtr is returned if you pass something that is not a pointer to a
	// Struct to Parse
	ErrNotAStructPtr = errors.New("env: expected a pointer to a Struct")

	defaultBuiltInParsers = map[reflect.Kind]ParserFunc{
		reflect.Bool: func(v string) (interface{}, error) {
			return strconv.ParseBool(v)
		},
		reflect.String: func(v string) (interface{}, error) {
			return v, nil
		},
		reflect.Int: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int(i), err
		},
		reflect.Int16: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 16)
			return int16(i), err
		},
		reflect.Int32: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int32(i), err
		},
		reflect.Int64: func(v string) (interface{}, error) {
			return strconv.ParseInt(v, 10, 64)
		},
		reflect.Int8: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 8)
			return int8(i), err
		},
		reflect.Uint: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint(i), err
		},
		reflect.Uint16: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 16)
			return uint16(i), err
		},
		reflect.Uint32: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint32(i), err
		},
		reflect.Uint64: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 64)
			return i, err
		},
		reflect.Uint8: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 8)
			return uint8(i), err
		},
		reflect.Float64: func(v string) (interface{}, error) {
			return strconv.ParseFloat(v, 64)
		},
		reflect.Float32: func(v string) (interface{}, error) {
			f, err := strconv.ParseFloat(v, 32)
			return float32(f), err
		},
	}

	defaultTypeParsers = map[reflect.Type]ParserFunc{
		reflect.TypeOf(url.URL{}): func(v string) (interface{}, error) {
			u, err := url.Parse(v)
			if err != nil {
				return nil, fmt.Errorf("unable to parse URL: %v", err)
			}
			return *u, nil
		},
		reflect.TypeOf(time.Nanosecond): func(v string) (interface{}, error) {
			s, err := time.ParseDuration(v)
			if err != nil {
				return nil, fmt.Errorf("unable to parse duration: %v", err)
			}
			return s, err
		},
	}
)

// ParserFunc defines the signature of a function that can be used within `CustomParsers`
type ParserFunc func(v string) (interface{}, error)

// Options for the parser.
type Options struct {
	// Environment keys and values that will be accessible for the service.
	Environment map[string]string
	// TagName specifies another tagname to use rather than the default env.
	TagName string

	// Sets to true if we have already configured once.
	configured bool
}

// configure will do the basic configurations and defaults.
func configure(opts []Options) []Options {
	// If we have already configured the first item
	// of options will have been configured set to true.
	if len(opts) > 0 && opts[0].configured {
		return opts
	}

	// Created options with defaults.
	opt := Options{
		TagName:     "env",
		Environment: toMap(os.Environ()),
		configured:  true,
	}

	// Loop over all opts structs and set
	// to opt if value is not default/empty.
	for _, item := range opts {
		if item.Environment != nil {
			opt.Environment = item.Environment
		}
		if item.TagName != "" {
			opt.TagName = item.TagName
		}
	}

	return []Options{opt}
}

func toMap(env []string) map[string]string {
	r := map[string]string{}
	for _, e := range env {
		p := strings.SplitN(e, "=", 2)
		r[p[0]] = p[1]
	}
	return r
}

// getTagName returns the tag name.
func getTagName(opts []Options) string {
	return opts[0].TagName
}

// getEnvironment returns the environment map.
func getEnvironment(opts []Options) map[string]string {
	return opts[0].Environment
}

// Parse parses a struct containing `env` tags and loads its values from
// environment variables.
func Parse(v interface{}, opts ...Options) error {
	return ParseWithFuncs(v, map[reflect.Type]ParserFunc{}, opts...)
}

// ParseWithFuncs is the same as `Parse` except it also allows the user to pass
// in custom parsers.
func ParseWithFuncs(v interface{}, funcMap map[reflect.Type]ParserFunc, opts ...Options) error {
	opts = configure(opts)

	ptrRef := reflect.ValueOf(v)
	if ptrRef.Kind() != reflect.Ptr {
		return ErrNotAStructPtr
	}
	ref := ptrRef.Elem()
	if ref.Kind() != reflect.Struct {
		return ErrNotAStructPtr
	}
	var parsers = defaultTypeParsers
	for k, v := range funcMap {
		parsers[k] = v
	}

	return doParse(ref, parsers, opts)
}

func doParse(ref reflect.Value, funcMap map[reflect.Type]ParserFunc, opts []Options) error {
	var refType = ref.Type()

	for i := 0; i < refType.NumField(); i++ {
		refField := ref.Field(i)
		if !refField.CanSet() {
			continue
		}
		if reflect.Ptr == refField.Kind() && !refField.IsNil() {
			err := ParseWithFuncs(refField.Interface(), funcMap, opts...)
			if err != nil {
				return err
			}
			continue
		}
		if reflect.Struct == refField.Kind() && refField.CanAddr() && refField.Type().Name() == "" {
			err := Parse(refField.Addr().Interface(), opts...)
			if err != nil {
				return err
			}
			continue
		}
		refTypeField := refType.Field(i)
		value, err := get(refTypeField, opts)
		if err != nil {
			return err
		}
		if value == "" {
			if reflect.Struct == refField.Kind() {
				if err := doParse(refField, funcMap, opts); err != nil {
					return err
				}
			}
			continue
		}
		if err := set(refField, refTypeField, value, funcMap); err != nil {
			return err
		}
	}
	return nil
}

func get(field reflect.StructField, opts []Options) (val string, err error) {
	var required bool
	var exists bool
	var loadFile bool
	var expand = strings.EqualFold(field.Tag.Get("envExpand"), "true")

	key, tags := parseKeyForOption(field.Tag.Get(getTagName(opts)))

	for _, tag := range tags {
		switch tag {
		case "":
			break
		case "file":
			loadFile = true
		case "required":
			required = true
		default:
			return "", fmt.Errorf("env: tag option %q not supported", tag)
		}
	}

	defaultValue, defExists := field.Tag.Lookup("envDefault")
	val, exists = getOr(key, defaultValue, defExists, getEnvironment(opts))

	if expand {
		val = os.ExpandEnv(val)
	}

	if required && !exists {
		return "", fmt.Errorf(`env: required environment variable %q is not set`, key)
	}

	if loadFile && val != "" {
		filename := val
		val, err = getFromFile(filename)
		if err != nil {
			return "", fmt.Errorf(`env: could not load content of file "%s" from variable %s: %v`, filename, key, err)
		}
	}

	return val, err
}

// split the env tag's key into the expected key and desired option, if any.
func parseKeyForOption(key string) (string, []string) {
	opts := strings.Split(key, ",")
	return opts[0], opts[1:]
}

func getFromFile(filename string) (value string, err error) {
	b, err := ioutil.ReadFile(filename)
	return string(b), err
}

func getOr(key, defaultValue string, defExists bool, envs map[string]string) (value string, exists bool) {
	value, exists = envs[key]
	switch {
	case (!exists || key == "") && defExists:
		return defaultValue, true
	case !exists:
		return "", false
	}

	return value, true
}

func set(field reflect.Value, sf reflect.StructField, value string, funcMap map[reflect.Type]ParserFunc) error {
	var tm = asTextUnmarshaler(field)
	if tm != nil {
		if err := tm.UnmarshalText([]byte(value)); err != nil {
			return newParseError(sf, err)
		}
		return nil
	}

	var typee = sf.Type
	var fieldee = field
	if typee.Kind() == reflect.Ptr {
		typee = typee.Elem()
		fieldee = field.Elem()
	}

	parserFunc, ok := funcMap[typee]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}

		fieldee.Set(reflect.ValueOf(val))
		return nil
	}

	parserFunc, ok = defaultBuiltInParsers[typee.Kind()]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}

		fieldee.Set(reflect.ValueOf(val).Convert(typee))
		return nil
	}

	if field.Kind() == reflect.Slice {
		return handleSlice(field, value, sf, funcMap)
	}

	return newNoParserError(sf)
}

func handleSlice(field reflect.Value, value string, sf reflect.StructField, funcMap map[reflect.Type]ParserFunc) error {
	var separator = sf.Tag.Get("envSeparator")
	if separator == "" {
		separator = ","
	}
	var parts = strings.Split(value, separator)

	var typee = sf.Type.Elem()
	if typee.Kind() == reflect.Ptr {
		typee = typee.Elem()
	}

	if _, ok := reflect.New(typee).Interface().(encoding.TextUnmarshaler); ok {
		return parseTextUnmarshalers(field, parts, sf)
	}

	parserFunc, ok := funcMap[typee]
	if !ok {
		parserFunc, ok = defaultBuiltInParsers[typee.Kind()]
		if !ok {
			return newNoParserError(sf)
		}
	}

	var result = reflect.MakeSlice(sf.Type, 0, len(parts))
	for _, part := range parts {
		r, err := parserFunc(part)
		if err != nil {
			return newParseError(sf, err)
		}
		var v = reflect.ValueOf(r).Convert(typee)
		if sf.Type.Elem().Kind() == reflect.Ptr {
			v = reflect.New(typee)
			v.Elem().Set(reflect.ValueOf(r).Convert(typee))
		}
		result = reflect.Append(result, v)
	}
	field.Set(result)
	return nil
}

func asTextUnmarshaler(field reflect.Value) encoding.TextUnmarshaler {
	if reflect.Ptr == field.Kind() {
		if field.IsNil() {
			field.Set(reflect.New(field.Type().Elem()))
		}
	} else if field.CanAddr() {
		field = field.Addr()
	}

	tm, ok := field.Interface().(encoding.TextUnmarshaler)
	if !ok {
		return nil
	}
	return tm
}

func parseTextUnmarshalers(field reflect.Value, data []string, sf reflect.StructField) error {
	s := len(data)
	elemType := field.Type().Elem()
	slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s)
	for i, v := range data {
		sv := slice.Index(i)
		kind := sv.Kind()
		if kind == reflect.Ptr {
			sv = reflect.New(elemType.Elem())
		} else {
			sv = sv.Addr()
		}
		tm := sv.Interface().(encoding.TextUnmarshaler)
		if err := tm.UnmarshalText([]byte(v)); err != nil {
			return newParseError(sf, err)
		}
		if kind == reflect.Ptr {
			slice.Index(i).Set(sv)
		}
	}

	field.Set(slice)

	return nil
}

func newParseError(sf reflect.StructField, err error) error {
	if err == nil {
		return nil
	}
	return parseError{
		sf:  sf,
		err: err,
	}
}

type parseError struct {
	sf  reflect.StructField
	err error
}

func (e parseError) Error() string {
	return fmt.Sprintf(`env: parse error on field "%s" of type "%s": %v`, e.sf.Name, e.sf.Type, e.err)
}

func newNoParserError(sf reflect.StructField) error {
	return fmt.Errorf(`env: no parser found for field "%s" of type "%s"`, sf.Name, sf.Type)
}
<|endoftext|>


<commit_before>package yiigo

import (
	"errors"
	"path/filepath"
	"strconv"
	"sync"
	"time"

	toml "github.com/pelletier/go-toml"
)

type env struct {
	tree  *toml.Tree
	mutex sync.RWMutex
}

// Env enviroment
var Env *env

// ErrEnvNil returned when config not found.
var ErrEnvNil = errors.New("config not found")

// loadEnv load env file.
func loadEnv() {
	abs, _ := filepath.Abs("env.toml")
	tomlTree, err := toml.LoadFile(abs)

	if err != nil {
		panic(err)
	}

	Env = &env{tree: tomlTree}
}

// String returns a value of string.
func (e *env) String(key string, defaultValue ...string) string {
	dv := ""

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case string:
		return t
	case int64:
		return strconv.FormatInt(t, 10)
	case uint64:
		return strconv.FormatInt(int64(t), 10)
	case float64:
		return strconv.FormatFloat(t, 'f', -1, 64)
	case bool:
		return strconv.FormatBool(t)
	default:
		return dv
	}
}

// Int returns a value of int.
func (e *env) Int(key string, defaultValue ...int) int {
	dv := 0

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case int64:
		return int(t)
	case uint64:
		return int(t)
	case float64:
		return int(t)
	case string:
		if v, err := strconv.ParseInt(t, 0, 0); err == nil {
			return int(v)
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Int64 returns a value of int64.
func (e *env) Int64(key string, defaultValue ...int64) int64 {
	var dv int64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case int64:
		return t
	case uint64:
		return int64(t)
	case float64:
		return int64(t)
	case string:
		if v, err := strconv.ParseInt(t, 0, 0); err == nil {
			return v
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Float64 returns a value of float64.
func (e *env) Float64(key string, defaultValue ...float64) float64 {
	var dv float64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case float64:
		return t
	case int64:
		return float64(t)
	case uint64:
		return float64(t)
	case string:
		if v, err := strconv.ParseFloat(t, 64); err == nil {
			return v
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Bool returns a value of bool.
func (e *env) Bool(key string, defaultValue ...bool) bool {
	var dv bool

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case bool:
		return t
	case int64:
		if t != 0 {
			return true
		}

		return false
	case uint64:
		if t != 0 {
			return true
		}

		return false
	case string:
		if v, err := strconv.ParseBool(t); err == nil {
			return v
		}

		return dv
	default:
		return dv
	}
}

// Time returns a value of time.Time.
func (e *env) Time(key string, defaultValue ...time.Time) time.Time {
	var dv time.Time

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case time.Time:
		return t
	case string:
		if v, err := time.Parse("2006-01-02 15:04:05", t); err == nil {
			return v
		}

		return dv
	case int64:
		return time.Unix(t, 0)
	case uint64:
		return time.Unix(int64(t), 0)
	default:
		return dv
	}
}

// ToMap returns a value of map[string]interface{}.
func (e *env) ToMap(key string) map[string]interface{} {
	i := e.Get(key)

	if v, ok := i.(*toml.Tree); ok {
		return v.ToMap()
	}

	return nil
}

// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by dest.
func (e *env) Unmarshal(key string, dest interface{}) error {
	i := e.Get(key)

	if i == nil {
		return ErrEnvNil
	}

	if v, ok := i.(*toml.Tree); ok {
		err := v.Unmarshal(dest)

		return err
	}

	return errors.New("value is not a tree of toml")
}

// Get returns a value of interface{}.
func (e *env) Get(key string) interface{} {
	e.mutex.RLock()
	defer e.mutex.RUnlock()

	i := e.tree.Get(key)

	return i
}
<commit_msg>update<commit_after>package yiigo

import (
	"errors"
	"path/filepath"
	"strconv"
	"sync"
	"time"

	toml "github.com/pelletier/go-toml"
)

type env struct {
	tree  *toml.Tree
	mutex sync.RWMutex
}

// Env enviroment
var Env *env

// ErrEnvNil returned when config not found.
var ErrEnvNil = errors.New("yiigo: env config not found")

// loadEnv load env file.
func loadEnv() {
	abs, _ := filepath.Abs("env.toml")
	tomlTree, err := toml.LoadFile(abs)

	if err != nil {
		panic(err)
	}

	Env = &env{tree: tomlTree}
}

// String returns a value of string.
func (e *env) String(key string, defaultValue ...string) string {
	dv := ""

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case string:
		return t
	case int64:
		return strconv.FormatInt(t, 10)
	case uint64:
		return strconv.FormatInt(int64(t), 10)
	case float64:
		return strconv.FormatFloat(t, 'f', -1, 64)
	case bool:
		return strconv.FormatBool(t)
	default:
		return dv
	}
}

// Int returns a value of int.
func (e *env) Int(key string, defaultValue ...int) int {
	dv := 0

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case int64:
		return int(t)
	case uint64:
		return int(t)
	case float64:
		return int(t)
	case string:
		if v, err := strconv.ParseInt(t, 0, 0); err == nil {
			return int(v)
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Int64 returns a value of int64.
func (e *env) Int64(key string, defaultValue ...int64) int64 {
	var dv int64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case int64:
		return t
	case uint64:
		return int64(t)
	case float64:
		return int64(t)
	case string:
		if v, err := strconv.ParseInt(t, 0, 0); err == nil {
			return v
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Float64 returns a value of float64.
func (e *env) Float64(key string, defaultValue ...float64) float64 {
	var dv float64

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case float64:
		return t
	case int64:
		return float64(t)
	case uint64:
		return float64(t)
	case string:
		if v, err := strconv.ParseFloat(t, 64); err == nil {
			return v
		}

		return dv
	case bool:
		if t {
			return 1
		}

		return 0
	default:
		return dv
	}
}

// Bool returns a value of bool.
func (e *env) Bool(key string, defaultValue ...bool) bool {
	var dv bool

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case bool:
		return t
	case int64:
		if t != 0 {
			return true
		}

		return false
	case uint64:
		if t != 0 {
			return true
		}

		return false
	case string:
		if v, err := strconv.ParseBool(t); err == nil {
			return v
		}

		return dv
	default:
		return dv
	}
}

// Time returns a value of time.Time.
func (e *env) Time(key string, defaultValue ...time.Time) time.Time {
	var dv time.Time

	if len(defaultValue) > 0 {
		dv = defaultValue[0]
	}

	i := e.Get(key)

	switch t := i.(type) {
	case time.Time:
		return t
	case string:
		if v, err := time.Parse("2006-01-02 15:04:05", t); err == nil {
			return v
		}

		return dv
	case int64:
		return time.Unix(t, 0)
	case uint64:
		return time.Unix(int64(t), 0)
	default:
		return dv
	}
}

// ToMap returns a value of map[string]interface{}.
func (e *env) ToMap(key string) map[string]interface{} {
	i := e.Get(key)

	if v, ok := i.(*toml.Tree); ok {
		return v.ToMap()
	}

	return nil
}

// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by dest.
func (e *env) Unmarshal(key string, dest interface{}) error {
	i := e.Get(key)

	if i == nil {
		return ErrEnvNil
	}

	if v, ok := i.(*toml.Tree); ok {
		err := v.Unmarshal(dest)

		return err
	}

	return errors.New("yiigo: env config is not a tree of toml")
}

// Get returns a value of interface{}.
func (e *env) Get(key string) interface{} {
	e.mutex.RLock()
	defer e.mutex.RUnlock()

	i := e.tree.Get(key)

	return i
}
<|endoftext|>


<commit_before>package fibgo

import "fmt"

// N return fibonacci number on N position
// N should start from 0, otherwise panic will raised
func N(n int) int {
	if n < 0 {
		panic(fmt.Sprintf("n should be greather than 0, but found %d", n))
	}
	if n < 2 {
		return n
	}

	return N(n-2) + N(n-1)
}

// Seq return
func Seq(length int) []int {
	out := make([]int, length)
	for i := 0; i < length; i++ {
		out[i] = N(i)
	}
	return out
}
<commit_msg>Change the panic wording<commit_after>package fibgo

// N return fibonacci number on N position
// N should start from 0, otherwise panic will raised
func N(n int) int {
	if n < 0 {
		panic("n should not less than 0")
	}
	if n < 2 {
		return n
	}

	return N(n-2) + N(n-1)
}

// Seq return
func Seq(length int) []int {
	out := make([]int, length)
	for i := 0; i < length; i++ {
		out[i] = N(i)
	}
	return out
}
<|endoftext|>


<commit_before>package ftp

import (
	"bufio"
	"net"
	"net/textproto"
	"os"
	"fmt"
	"strconv"
	"strings"
)

const (
	EntryTypeFile = iota
	EntryTypeFolder
	EntryTypeLink
)

type ServerConn struct {
	conn *textproto.Conn
	host string
}

type Response struct {
	conn net.Conn
	c *ServerConn
}

type Entry struct {
	Name string
	EntryType int
	Size uint64
}

// Connect to a ftp server and returns a ServerConn handler.
func Connect(host, user, password string) (*ServerConn, os.Error) {
	conn, err := textproto.Dial("tcp", host)
	if err != nil {
		return nil, err
	}

	a := strings.Split(host, ":", 2)
	c := &ServerConn{conn, a[0]}

	_, _, err = c.conn.ReadCodeLine(StatusReady)
	if err != nil {
		c.Close()
		return nil, err
	}

	c.conn.Cmd("USER %s", user)
	_, _, err = c.conn.ReadCodeLine(StatusUserOK)
	if err != nil {
		c.Close()
		return nil, err
	}

	c.conn.Cmd("PASS %s", password)
	_, _, err = c.conn.ReadCodeLine(StatusLoggedIn)
	if err != nil {
		c.Close()
		return nil, err
	}

	return c, nil
}

// Like Connect() but with anonymous credentials.
func ConnectAnonymous(host string) (*ServerConn, os.Error) {
	return Connect(host, "anonymous", "anonymous")
}

// Enter extended passive mode
func (c *ServerConn) epsv() (port int, err os.Error) {
	c.conn.Cmd("EPSV")
	_, line, err := c.conn.ReadCodeLine(StatusExtendedPassiveMode)
	if err != nil {
		return
	}
	start := strings.Index(line, "|||")
	end := strings.LastIndex(line, "|")
	if start == -1 || end == -1 {
		err = os.NewError("Invalid EPSV response format")
		return
	}
	port, err = strconv.Atoi(line[start+3 : end])
	return
}

// Open a new data connection using extended passive mode
func (c *ServerConn) openDataConnection() (r *Response, err os.Error) {
	port, err := c.epsv()
	if err != nil {
		return
	}

	// Build the new net address string
	addr := fmt.Sprintf("%s:%d", c.host, port)

	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return
	}

	r = &Response{conn, c}
	return
}

func parseListLine(line string) (*Entry, os.Error) {
	fields := strings.Fields(line)
	if len(fields) < 9 {
		return nil, os.NewError("Unsupported LIST line")
	}

	e := &Entry{}
	switch fields[0][0] {
		case '-':
			e.EntryType = EntryTypeFile
		case 'd':
			e.EntryType = EntryTypeFolder
		case 'l':
			e.EntryType = EntryTypeLink
		default:
			return nil, os.NewError("Unknown entry type")
	}

	e.Name = strings.Join(fields[8:], " ")
	return e, nil
}

func (c *ServerConn) List() (entries []*Entry, err os.Error) {
	r, err := c.openDataConnection()
	if err != nil {
		return
	}
	defer r.Close()

	c.conn.Cmd("LIST")
	_, _, err = c.conn.ReadCodeLine(StatusAboutToSend)
	if err != nil {
		return
	}

	bio := bufio.NewReader(r)
	for {
		line, e := bio.ReadString('\n')
		if e == os.EOF {
			break
		} else if e != nil {
			return nil, e
		}
		entry, err := parseListLine(line)
		if err == nil {
			entries = append(entries, entry)
		}
	}
	return
}

func (c *ServerConn) ChangeDir(path string) (err os.Error) {
	c.conn.Cmd("CWD %s", path);
	_, _, err = c.conn.ReadCodeLine(StatusRequestedFileActionOK)
	return
}

func (c *ServerConn) Get(path string) (r *Response, err os.Error) {
	r, err = c.openDataConnection()
	if err != nil {
		return
	}

	c.conn.Cmd("RETR %s", path)
	_, _, err = c.conn.ReadCodeLine(StatusAboutToSend)
	return
}

func (c *ServerConn) Close() {
	c.conn.Cmd("QUIT")
	c.conn.Close()
}

func (r *Response) Read(buf []byte) (int, os.Error) {
	n, err := r.conn.Read(buf)
	if err == os.EOF {
		_, _, err2 := r.c.conn.ReadCodeLine(StatusClosingDataConnection)
		if err2 != nil {
			err = err2
		}
	}
	return n, err
}

func (r *Response) Close() os.Error {
	return r.conn.Close()
}
<commit_msg>List() takes an argument.<commit_after>package ftp

import (
	"bufio"
	"net"
	"net/textproto"
	"os"
	"fmt"
	"strconv"
	"strings"
)

const (
	EntryTypeFile = iota
	EntryTypeFolder
	EntryTypeLink
)

type ServerConn struct {
	conn *textproto.Conn
	host string
}

type Response struct {
	conn net.Conn
	c *ServerConn
}

type Entry struct {
	Name string
	EntryType int
	Size uint64
}

// Connect to a ftp server and returns a ServerConn handler.
func Connect(host, user, password string) (*ServerConn, os.Error) {
	conn, err := textproto.Dial("tcp", host)
	if err != nil {
		return nil, err
	}

	a := strings.Split(host, ":", 2)
	c := &ServerConn{conn, a[0]}

	_, _, err = c.conn.ReadCodeLine(StatusReady)
	if err != nil {
		c.Close()
		return nil, err
	}

	c.conn.Cmd("USER %s", user)
	_, _, err = c.conn.ReadCodeLine(StatusUserOK)
	if err != nil {
		c.Close()
		return nil, err
	}

	c.conn.Cmd("PASS %s", password)
	_, _, err = c.conn.ReadCodeLine(StatusLoggedIn)
	if err != nil {
		c.Close()
		return nil, err
	}

	return c, nil
}

// Like Connect() but with anonymous credentials.
func ConnectAnonymous(host string) (*ServerConn, os.Error) {
	return Connect(host, "anonymous", "anonymous")
}

// Enter extended passive mode
func (c *ServerConn) epsv() (port int, err os.Error) {
	c.conn.Cmd("EPSV")
	_, line, err := c.conn.ReadCodeLine(StatusExtendedPassiveMode)
	if err != nil {
		return
	}
	start := strings.Index(line, "|||")
	end := strings.LastIndex(line, "|")
	if start == -1 || end == -1 {
		err = os.NewError("Invalid EPSV response format")
		return
	}
	port, err = strconv.Atoi(line[start+3 : end])
	return
}

// Open a new data connection using extended passive mode
func (c *ServerConn) openDataConnection() (r *Response, err os.Error) {
	port, err := c.epsv()
	if err != nil {
		return
	}

	// Build the new net address string
	addr := fmt.Sprintf("%s:%d", c.host, port)

	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return
	}

	r = &Response{conn, c}
	return
}

func parseListLine(line string) (*Entry, os.Error) {
	fields := strings.Fields(line)
	if len(fields) < 9 {
		return nil, os.NewError("Unsupported LIST line")
	}

	e := &Entry{}
	switch fields[0][0] {
		case '-':
			e.EntryType = EntryTypeFile
		case 'd':
			e.EntryType = EntryTypeFolder
		case 'l':
			e.EntryType = EntryTypeLink
		default:
			return nil, os.NewError("Unknown entry type")
	}

	e.Name = strings.Join(fields[8:], " ")
	return e, nil
}

func (c *ServerConn) List(path string) (entries []*Entry, err os.Error) {
	r, err := c.openDataConnection()
	if err != nil {
		return
	}
	defer r.Close()

	c.conn.Cmd("LIST %s", path)
	_, _, err = c.conn.ReadCodeLine(StatusAboutToSend)
	if err != nil {
		return
	}

	bio := bufio.NewReader(r)
	for {
		line, e := bio.ReadString('\n')
		if e == os.EOF {
			break
		} else if e != nil {
			return nil, e
		}
		entry, err := parseListLine(line)
		if err == nil {
			entries = append(entries, entry)
		}
	}
	return
}

func (c *ServerConn) ChangeDir(path string) (err os.Error) {
	c.conn.Cmd("CWD %s", path);
	_, _, err = c.conn.ReadCodeLine(StatusRequestedFileActionOK)
	return
}

func (c *ServerConn) Get(path string) (r *Response, err os.Error) {
	r, err = c.openDataConnection()
	if err != nil {
		return
	}

	c.conn.Cmd("RETR %s", path)
	_, _, err = c.conn.ReadCodeLine(StatusAboutToSend)
	return
}

func (c *ServerConn) Close() {
	c.conn.Cmd("QUIT")
	c.conn.Close()
}

func (r *Response) Read(buf []byte) (int, os.Error) {
	n, err := r.conn.Read(buf)
	if err == os.EOF {
		_, _, err2 := r.c.conn.ReadCodeLine(StatusClosingDataConnection)
		if err2 != nil {
			err = err2
		}
	}
	return n, err
}

func (r *Response) Close() os.Error {
	return r.conn.Close()
}
<|endoftext|>


<commit_before>// Package ftp implements a FTP client as described in RFC 959.
package ftp

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net"
	"net/textproto"
	"strconv"
	"strings"
	"time"
)

// EntryType describes the different types of an Entry.
type EntryType int

const (
	EntryTypeFile EntryType = iota
	EntryTypeFolder
	EntryTypeLink
)

// ServerConn represents the connection to a remote FTP server.
type ServerConn struct {
	conn     *textproto.Conn
	host     string
	features map[string]string
}

// Entry describes a file and is returned by List().
type Entry struct {
	Name string
	Type EntryType
	Size uint64
	Time time.Time
}

// response represent a data-connection
type response struct {
	conn net.Conn
	c    *ServerConn
}

// Connect initializes the connection to the specified ftp server address.
//
// It is generally followed by a call to Login() as most FTP commands require
// an authenticated user.
func Connect(addr string) (*ServerConn, error) {
	conn, err := textproto.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	a := strings.SplitN(addr, ":", 2)
	c := &ServerConn{
		conn:     conn,
		host:     a[0],
		features: make(map[string]string),
	}

	_, _, err = c.conn.ReadResponse(StatusReady)
	if err != nil {
		c.Quit()
		return nil, err
	}

	err = c.feat()
	if err != nil {
		c.Quit()
		return nil, err
	}

	return c, nil
}

// Login authenticates the client with specified user and password.
//
// "anonymous"/"anonymous" is a common user/password scheme for FTP servers
// that allows anonymous read-only accounts.
func (c *ServerConn) Login(user, password string) error {
	code, message, err := c.cmd(-1, "USER %s", user)
	if err != nil {
		return err
	}

	switch code {
	case StatusLoggedIn:
	case StatusUserOK:
		_, _, err = c.cmd(StatusLoggedIn, "PASS %s", password)
		if err != nil {
			return err
		}
	default:
		return errors.New(message)
	}

	// Switch to binary mode
	_, _, err = c.cmd(StatusCommandOK, "TYPE I")
	if err != nil {
		return err
	}

	return nil
}

// feat issues a FEAT FTP command to list the additional commands supported by
// the remote FTP server.
// FEAT is described in RFC 2389
func (c *ServerConn) feat() error {
	code, message, err := c.cmd(-1, "FEAT")
	if err != nil {
		return err
	}

	if code != StatusSystem {
		// The server does not support the FEAT command. This is not an
		// error: we consider that there is no additional feature.
		return nil
	}

	lines := strings.Split(message, "\n")
	for _, line := range lines {
		if !strings.HasPrefix(line, " ") {
			continue
		}

		line = strings.TrimSpace(line)
		featureElements := strings.SplitN(line, " ", 2)

		command := featureElements[0]

		var commandDesc string
		if len(featureElements) == 2 {
			commandDesc = featureElements[1]
		}

		c.features[command] = commandDesc
	}

	return nil
}

// epsv issues an "EPSV" command to get a port number for a data connection.
func (c *ServerConn) epsv() (port int, err error) {
	_, line, err := c.cmd(StatusExtendedPassiveMode, "EPSV")
	if err != nil {
		return
	}

	start := strings.Index(line, "|||")
	end := strings.LastIndex(line, "|")
	if start == -1 || end == -1 {
		err = errors.New("Invalid EPSV response format")
		return
	}
	port, err = strconv.Atoi(line[start+3 : end])
	return
}

// pasv issues a "PASV" command to get a port number for a data connection.
func (c *ServerConn) pasv() (port int, err error) {
	_, line, err := c.cmd(StatusPassiveMode, "PASV")
	if err != nil {
		return
	}

	// PASV response format : 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
	start := strings.Index(line, "(")
	end := strings.LastIndex(line, ")")
	if start == -1 || end == -1 {
		err = errors.New("Invalid EPSV response format")
		return
	}

	// We have to split the response string
	pasvData := strings.Split(line[start+1:end], ",")
	// Let's compute the port number
	portPart1, err1 := strconv.Atoi(pasvData[4])
	if err1 != nil {
		err = err1
		return
	}

	portPart2, err2 := strconv.Atoi(pasvData[5])
	if err2 != nil {
		err = err2
		return
	}

	// Recompose port
	port = portPart1*256 + portPart2
	return
}

// openDataConn creates a new FTP data connection.
func (c *ServerConn) openDataConn() (net.Conn, error) {
	var port int
	var err error

	//  If features contains nat6 or EPSV => EPSV
	//  else -> PASV
	_, nat6Supported := c.features["nat6"]
	_, epsvSupported := c.features["EPSV"]
	if nat6Supported || epsvSupported {
		port, err = c.epsv()
		if err != nil {
			return nil, err
		}
	} else {
		port, err = c.pasv()
		if err != nil {
			return nil, err
		}
	}

	// Build the new net address string
	addr := fmt.Sprintf("%s:%d", c.host, port)

	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	return conn, nil
}

// cmd is a helper function to execute a command and check for the expected FTP
// return code
func (c *ServerConn) cmd(expected int, format string, args ...interface{}) (int, string, error) {
	_, err := c.conn.Cmd(format, args...)
	if err != nil {
		return 0, "", err
	}

	code, line, err := c.conn.ReadResponse(expected)
	return code, line, err
}

// cmdDataConn executes a command which require a FTP data connection.
func (c *ServerConn) cmdDataConn(format string, args ...interface{}) (net.Conn, error) {
	conn, err := c.openDataConn()
	if err != nil {
		return nil, err
	}

	_, err = c.conn.Cmd(format, args...)
	if err != nil {
		conn.Close()
		return nil, err
	}

	code, msg, err := c.conn.ReadResponse(-1)
	if err != nil {
		conn.Close()
		return nil, err
	}
	if code != StatusAlreadyOpen && code != StatusAboutToSend {
		conn.Close()
		return nil, &textproto.Error{code, msg}
	}

	return conn, nil
}

// parseListLine parses the various non-standard format returned by the LIST
// FTP command.
func parseListLine(line string) (*Entry, error) {
	fields := strings.Fields(line)
	if len(fields) < 9 {
		return nil, errors.New("Unsupported LIST line")
	}

	e := &Entry{}
	switch fields[0][0] {
	case '-':
		e.Type = EntryTypeFile
	case 'd':
		e.Type = EntryTypeFolder
	case 'l':
		e.Type = EntryTypeLink
	default:
		return nil, errors.New("Unknown entry type")
	}

	if e.Type == EntryTypeFile {
		size, err := strconv.ParseUint(fields[4], 10, 0)
		if err != nil {
			return nil, err
		}
		e.Size = size
	}
	var timeStr string
	if strings.Contains(fields[7], ":") { // this year
		thisYear, _, _ := time.Now().Date()
		timeStr = fields[6] + " " + fields[5] + " " + strconv.Itoa(thisYear)[2:4] + " " + fields[7] + " GMT"
	} else { // not this year
		timeStr = fields[6] + " " + fields[5] + " " + fields[7][2:4] + " " + "00:00" + " GMT"
	}
	t, err := time.Parse("_2 Jan 06 15:04 MST", timeStr)
	if err != nil {
		return nil, err
	}
	e.Time = t

	e.Name = strings.Join(fields[8:], " ")
	return e, nil
}

// NameList issues an NLST FTP command.
func (c *ServerConn) NameList(path string) (entries []string, err error) {
	conn, err := c.cmdDataConn("NLST %s", path)
	if err != nil {
		return
	}

	r := &response{conn, c}
	defer r.Close()

	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		entries = append(entries, scanner.Text())
	}
	if err = scanner.Err(); err != nil {
		return entries, err
	}
	return
}

// List issues a LIST FTP command.
func (c *ServerConn) List(path string) (entries []*Entry, err error) {
	conn, err := c.cmdDataConn("LIST %s", path)
	if err != nil {
		return
	}

	r := &response{conn, c}
	defer r.Close()

	bio := bufio.NewReader(r)
	for {
		line, e := bio.ReadString('\n')
		if e == io.EOF {
			break
		} else if e != nil {
			return nil, e
		}
		entry, err := parseListLine(line)
		if err == nil {
			entries = append(entries, entry)
		}
	}
	return
}

// ChangeDir issues a CWD FTP command, which changes the current directory to
// the specified path.
func (c *ServerConn) ChangeDir(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "CWD %s", path)
	return err
}

// ChangeDirToParent issues a CDUP FTP command, which changes the current
// directory to the parent directory.  This is similar to a call to ChangeDir
// with a path set to "..".
func (c *ServerConn) ChangeDirToParent() error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "CDUP")
	return err
}

// CurrentDir issues a PWD FTP command, which Returns the path of the current
// directory.
func (c *ServerConn) CurrentDir() (string, error) {
	_, msg, err := c.cmd(StatusPathCreated, "PWD")
	if err != nil {
		return "", err
	}

	start := strings.Index(msg, "\"")
	end := strings.LastIndex(msg, "\"")

	if start == -1 || end == -1 {
		return "", errors.New("Unsuported PWD response format")
	}

	return msg[start+1 : end], nil
}

// Retr issues a RETR FTP command to fetch the specified file from the remote
// FTP server.
//
// The returned ReadCloser must be closed to cleanup the FTP data connection.
func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
	conn, err := c.cmdDataConn("RETR %s", path)
	if err != nil {
		return nil, err
	}

	r := &response{conn, c}
	return r, nil
}

// Stor issues a STOR FTP command to store a file to the remote FTP server.
// Stor creates the specified file with the content of the io.Reader.
//
// Hint: io.Pipe() can be used if an io.Writer is required.
func (c *ServerConn) Stor(path string, r io.Reader) error {
	conn, err := c.cmdDataConn("STOR %s", path)
	if err != nil {
		return err
	}

	_, err = io.Copy(conn, r)
	conn.Close()
	if err != nil {
		return err
	}

	_, _, err = c.conn.ReadResponse(StatusClosingDataConnection)
	return err
}

// Rename renames a file on the remote FTP server.
func (c *ServerConn) Rename(from, to string) error {
	_, _, err := c.cmd(StatusRequestFilePending, "RNFR %s", from)
	if err != nil {
		return err
	}

	_, _, err = c.cmd(StatusRequestedFileActionOK, "RNTO %s", to)
	return err
}

// Delete issues a DELE FTP command to delete the specified file from the
// remote FTP server.
func (c *ServerConn) Delete(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "DELE %s", path)
	return err
}

// MakeDir issues a MKD FTP command to create the specified directory on the
// remote FTP server.
func (c *ServerConn) MakeDir(path string) error {
	_, _, err := c.cmd(StatusPathCreated, "MKD %s", path)
	return err
}

// RemoveDir issues a RMD FTP command to remove the specified directory from
// the remote FTP server.
func (c *ServerConn) RemoveDir(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "RMD %s", path)
	return err
}

// NoOp issues a NOOP FTP command.
// NOOP has no effects and is usually used to prevent the remote FTP server to
// close the otherwise idle connection.
func (c *ServerConn) NoOp() error {
	_, _, err := c.cmd(StatusCommandOK, "NOOP")
	return err
}

// Logout issues a REIN FTP command to logout the current user.
func (c *ServerConn) Logout() error {
	_, _, err := c.cmd(StatusLoggedIn, "REIN")
	return err
}

// Quit issues a QUIT FTP command to properly close the connection from the
// remote FTP server.
func (c *ServerConn) Quit() error {
	c.conn.Cmd("QUIT")
	return c.conn.Close()
}

// Read implements the io.Reader interface on a FTP data connection.
func (r *response) Read(buf []byte) (int, error) {
	n, err := r.conn.Read(buf)
	return n, err
}

// Close implements the io.Closer interface on a FTP data connection.
func (r *response) Close() error {
	err := r.conn.Close()
	_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
	if err2 != nil {
		err = err2
	}
	return err
}
<commit_msg>Specify the fields to make govet happy.<commit_after>// Package ftp implements a FTP client as described in RFC 959.
package ftp

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net"
	"net/textproto"
	"strconv"
	"strings"
	"time"
)

// EntryType describes the different types of an Entry.
type EntryType int

const (
	EntryTypeFile EntryType = iota
	EntryTypeFolder
	EntryTypeLink
)

// ServerConn represents the connection to a remote FTP server.
type ServerConn struct {
	conn     *textproto.Conn
	host     string
	features map[string]string
}

// Entry describes a file and is returned by List().
type Entry struct {
	Name string
	Type EntryType
	Size uint64
	Time time.Time
}

// response represent a data-connection
type response struct {
	conn net.Conn
	c    *ServerConn
}

// Connect initializes the connection to the specified ftp server address.
//
// It is generally followed by a call to Login() as most FTP commands require
// an authenticated user.
func Connect(addr string) (*ServerConn, error) {
	conn, err := textproto.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	a := strings.SplitN(addr, ":", 2)
	c := &ServerConn{
		conn:     conn,
		host:     a[0],
		features: make(map[string]string),
	}

	_, _, err = c.conn.ReadResponse(StatusReady)
	if err != nil {
		c.Quit()
		return nil, err
	}

	err = c.feat()
	if err != nil {
		c.Quit()
		return nil, err
	}

	return c, nil
}

// Login authenticates the client with specified user and password.
//
// "anonymous"/"anonymous" is a common user/password scheme for FTP servers
// that allows anonymous read-only accounts.
func (c *ServerConn) Login(user, password string) error {
	code, message, err := c.cmd(-1, "USER %s", user)
	if err != nil {
		return err
	}

	switch code {
	case StatusLoggedIn:
	case StatusUserOK:
		_, _, err = c.cmd(StatusLoggedIn, "PASS %s", password)
		if err != nil {
			return err
		}
	default:
		return errors.New(message)
	}

	// Switch to binary mode
	_, _, err = c.cmd(StatusCommandOK, "TYPE I")
	if err != nil {
		return err
	}

	return nil
}

// feat issues a FEAT FTP command to list the additional commands supported by
// the remote FTP server.
// FEAT is described in RFC 2389
func (c *ServerConn) feat() error {
	code, message, err := c.cmd(-1, "FEAT")
	if err != nil {
		return err
	}

	if code != StatusSystem {
		// The server does not support the FEAT command. This is not an
		// error: we consider that there is no additional feature.
		return nil
	}

	lines := strings.Split(message, "\n")
	for _, line := range lines {
		if !strings.HasPrefix(line, " ") {
			continue
		}

		line = strings.TrimSpace(line)
		featureElements := strings.SplitN(line, " ", 2)

		command := featureElements[0]

		var commandDesc string
		if len(featureElements) == 2 {
			commandDesc = featureElements[1]
		}

		c.features[command] = commandDesc
	}

	return nil
}

// epsv issues an "EPSV" command to get a port number for a data connection.
func (c *ServerConn) epsv() (port int, err error) {
	_, line, err := c.cmd(StatusExtendedPassiveMode, "EPSV")
	if err != nil {
		return
	}

	start := strings.Index(line, "|||")
	end := strings.LastIndex(line, "|")
	if start == -1 || end == -1 {
		err = errors.New("Invalid EPSV response format")
		return
	}
	port, err = strconv.Atoi(line[start+3 : end])
	return
}

// pasv issues a "PASV" command to get a port number for a data connection.
func (c *ServerConn) pasv() (port int, err error) {
	_, line, err := c.cmd(StatusPassiveMode, "PASV")
	if err != nil {
		return
	}

	// PASV response format : 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).
	start := strings.Index(line, "(")
	end := strings.LastIndex(line, ")")
	if start == -1 || end == -1 {
		err = errors.New("Invalid EPSV response format")
		return
	}

	// We have to split the response string
	pasvData := strings.Split(line[start+1:end], ",")
	// Let's compute the port number
	portPart1, err1 := strconv.Atoi(pasvData[4])
	if err1 != nil {
		err = err1
		return
	}

	portPart2, err2 := strconv.Atoi(pasvData[5])
	if err2 != nil {
		err = err2
		return
	}

	// Recompose port
	port = portPart1*256 + portPart2
	return
}

// openDataConn creates a new FTP data connection.
func (c *ServerConn) openDataConn() (net.Conn, error) {
	var port int
	var err error

	//  If features contains nat6 or EPSV => EPSV
	//  else -> PASV
	_, nat6Supported := c.features["nat6"]
	_, epsvSupported := c.features["EPSV"]
	if nat6Supported || epsvSupported {
		port, err = c.epsv()
		if err != nil {
			return nil, err
		}
	} else {
		port, err = c.pasv()
		if err != nil {
			return nil, err
		}
	}

	// Build the new net address string
	addr := fmt.Sprintf("%s:%d", c.host, port)

	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	return conn, nil
}

// cmd is a helper function to execute a command and check for the expected FTP
// return code
func (c *ServerConn) cmd(expected int, format string, args ...interface{}) (int, string, error) {
	_, err := c.conn.Cmd(format, args...)
	if err != nil {
		return 0, "", err
	}

	code, line, err := c.conn.ReadResponse(expected)
	return code, line, err
}

// cmdDataConn executes a command which require a FTP data connection.
func (c *ServerConn) cmdDataConn(format string, args ...interface{}) (net.Conn, error) {
	conn, err := c.openDataConn()
	if err != nil {
		return nil, err
	}

	_, err = c.conn.Cmd(format, args...)
	if err != nil {
		conn.Close()
		return nil, err
	}

	code, msg, err := c.conn.ReadResponse(-1)
	if err != nil {
		conn.Close()
		return nil, err
	}
	if code != StatusAlreadyOpen && code != StatusAboutToSend {
		conn.Close()
		return nil, &textproto.Error{Code: code, Msg: msg}
	}

	return conn, nil
}

// parseListLine parses the various non-standard format returned by the LIST
// FTP command.
func parseListLine(line string) (*Entry, error) {
	fields := strings.Fields(line)
	if len(fields) < 9 {
		return nil, errors.New("Unsupported LIST line")
	}

	e := &Entry{}
	switch fields[0][0] {
	case '-':
		e.Type = EntryTypeFile
	case 'd':
		e.Type = EntryTypeFolder
	case 'l':
		e.Type = EntryTypeLink
	default:
		return nil, errors.New("Unknown entry type")
	}

	if e.Type == EntryTypeFile {
		size, err := strconv.ParseUint(fields[4], 10, 0)
		if err != nil {
			return nil, err
		}
		e.Size = size
	}
	var timeStr string
	if strings.Contains(fields[7], ":") { // this year
		thisYear, _, _ := time.Now().Date()
		timeStr = fields[6] + " " + fields[5] + " " + strconv.Itoa(thisYear)[2:4] + " " + fields[7] + " GMT"
	} else { // not this year
		timeStr = fields[6] + " " + fields[5] + " " + fields[7][2:4] + " " + "00:00" + " GMT"
	}
	t, err := time.Parse("_2 Jan 06 15:04 MST", timeStr)
	if err != nil {
		return nil, err
	}
	e.Time = t

	e.Name = strings.Join(fields[8:], " ")
	return e, nil
}

// NameList issues an NLST FTP command.
func (c *ServerConn) NameList(path string) (entries []string, err error) {
	conn, err := c.cmdDataConn("NLST %s", path)
	if err != nil {
		return
	}

	r := &response{conn, c}
	defer r.Close()

	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		entries = append(entries, scanner.Text())
	}
	if err = scanner.Err(); err != nil {
		return entries, err
	}
	return
}

// List issues a LIST FTP command.
func (c *ServerConn) List(path string) (entries []*Entry, err error) {
	conn, err := c.cmdDataConn("LIST %s", path)
	if err != nil {
		return
	}

	r := &response{conn, c}
	defer r.Close()

	bio := bufio.NewReader(r)
	for {
		line, e := bio.ReadString('\n')
		if e == io.EOF {
			break
		} else if e != nil {
			return nil, e
		}
		entry, err := parseListLine(line)
		if err == nil {
			entries = append(entries, entry)
		}
	}
	return
}

// ChangeDir issues a CWD FTP command, which changes the current directory to
// the specified path.
func (c *ServerConn) ChangeDir(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "CWD %s", path)
	return err
}

// ChangeDirToParent issues a CDUP FTP command, which changes the current
// directory to the parent directory.  This is similar to a call to ChangeDir
// with a path set to "..".
func (c *ServerConn) ChangeDirToParent() error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "CDUP")
	return err
}

// CurrentDir issues a PWD FTP command, which Returns the path of the current
// directory.
func (c *ServerConn) CurrentDir() (string, error) {
	_, msg, err := c.cmd(StatusPathCreated, "PWD")
	if err != nil {
		return "", err
	}

	start := strings.Index(msg, "\"")
	end := strings.LastIndex(msg, "\"")

	if start == -1 || end == -1 {
		return "", errors.New("Unsuported PWD response format")
	}

	return msg[start+1 : end], nil
}

// Retr issues a RETR FTP command to fetch the specified file from the remote
// FTP server.
//
// The returned ReadCloser must be closed to cleanup the FTP data connection.
func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
	conn, err := c.cmdDataConn("RETR %s", path)
	if err != nil {
		return nil, err
	}

	r := &response{conn, c}
	return r, nil
}

// Stor issues a STOR FTP command to store a file to the remote FTP server.
// Stor creates the specified file with the content of the io.Reader.
//
// Hint: io.Pipe() can be used if an io.Writer is required.
func (c *ServerConn) Stor(path string, r io.Reader) error {
	conn, err := c.cmdDataConn("STOR %s", path)
	if err != nil {
		return err
	}

	_, err = io.Copy(conn, r)
	conn.Close()
	if err != nil {
		return err
	}

	_, _, err = c.conn.ReadResponse(StatusClosingDataConnection)
	return err
}

// Rename renames a file on the remote FTP server.
func (c *ServerConn) Rename(from, to string) error {
	_, _, err := c.cmd(StatusRequestFilePending, "RNFR %s", from)
	if err != nil {
		return err
	}

	_, _, err = c.cmd(StatusRequestedFileActionOK, "RNTO %s", to)
	return err
}

// Delete issues a DELE FTP command to delete the specified file from the
// remote FTP server.
func (c *ServerConn) Delete(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "DELE %s", path)
	return err
}

// MakeDir issues a MKD FTP command to create the specified directory on the
// remote FTP server.
func (c *ServerConn) MakeDir(path string) error {
	_, _, err := c.cmd(StatusPathCreated, "MKD %s", path)
	return err
}

// RemoveDir issues a RMD FTP command to remove the specified directory from
// the remote FTP server.
func (c *ServerConn) RemoveDir(path string) error {
	_, _, err := c.cmd(StatusRequestedFileActionOK, "RMD %s", path)
	return err
}

// NoOp issues a NOOP FTP command.
// NOOP has no effects and is usually used to prevent the remote FTP server to
// close the otherwise idle connection.
func (c *ServerConn) NoOp() error {
	_, _, err := c.cmd(StatusCommandOK, "NOOP")
	return err
}

// Logout issues a REIN FTP command to logout the current user.
func (c *ServerConn) Logout() error {
	_, _, err := c.cmd(StatusLoggedIn, "REIN")
	return err
}

// Quit issues a QUIT FTP command to properly close the connection from the
// remote FTP server.
func (c *ServerConn) Quit() error {
	c.conn.Cmd("QUIT")
	return c.conn.Close()
}

// Read implements the io.Reader interface on a FTP data connection.
func (r *response) Read(buf []byte) (int, error) {
	n, err := r.conn.Read(buf)
	return n, err
}

// Close implements the io.Closer interface on a FTP data connection.
func (r *response) Close() error {
	err := r.conn.Close()
	_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
	if err2 != nil {
		err = err2
	}
	return err
}
<|endoftext|>