text:
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2010 The Go Authors.  All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

include ../../Make.protobuf

all:	regenerate

regenerate:
	rm -f test.pb.go
	make test.pb.go

# The following rules are just aids to development. Not needed for typical testing.

diff:	regenerate
	git diff test.pb.go

restore:
	cp test.pb.go.golden test.pb.go

preserve:
	cp test.pb.go test.pb.go.golden

repo_name: dan-v/dosxvpn

repo_language: Go

mime_type: text/x-shellscript


text:
// +build windows
// +build !go1.4

package mousetrap

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

const (
	// defined by the Win32 API
	th32cs_snapprocess uintptr = 0x2
)

var (
	kernel                   = syscall.MustLoadDLL("kernel32.dll")
	CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
	Process32First           = kernel.MustFindProc("Process32FirstW")
	Process32Next            = kernel.MustFindProc("Process32NextW")
)

// ProcessEntry32 structure defined by the Win32 API
type processEntry32 struct {
	dwSize              uint32
	cntUsage            uint32
	th32ProcessID       uint32
	th32DefaultHeapID   int
	th32ModuleID        uint32
	cntThreads          uint32
	th32ParentProcessID uint32
	pcPriClassBase      int32
	dwFlags             uint32
	szExeFile           [syscall.MAX_PATH]uint16
}

func getProcessEntry(pid int) (pe *processEntry32, err error) {
	snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))
	if snapshot == uintptr(syscall.InvalidHandle) {
		err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
		return
	}
	defer syscall.CloseHandle(syscall.Handle(snapshot))

	var processEntry processEntry32
	processEntry.dwSize = uint32(unsafe.Sizeof(processEntry))
	ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
	if ok == 0 {
		err = fmt.Errorf("Process32First: %v", e1)
		return
	}

	for {
		if processEntry.th32ProcessID == uint32(pid) {
			pe = &processEntry
			return
		}

		ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
		if ok == 0 {
			err = fmt.Errorf("Process32Next: %v", e1)
			return
		}
	}
}

func getppid() (pid int, err error) {
	pe, err := getProcessEntry(os.Getpid())
	if err != nil {
		return
	}

	pid = int(pe.th32ParentProcessID)
	return
}

// StartedByExplorer returns true if the program was invoked by the user double-clicking
// on the executable from explorer.exe
//
// It is conservative and returns false if any of the internal calls fail.
// It does not guarantee that the program was run from a terminal. It only can tell you
// whether it was launched from explorer.exe
func StartedByExplorer() bool {
	ppid, err := getppid()
	if err != nil {
		return false
	}

	pe, err := getProcessEntry(ppid)
	if err != nil {
		return false
	}

	name := syscall.UTF16ToString(pe.szExeFile[:])
	return name == "explorer.exe"
}


text:
// +build windows
// +build go1.4

package mousetrap

import (
	"os"
	"syscall"
	"unsafe"
)

func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
	snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
	if err != nil {
		return nil, err
	}
	defer syscall.CloseHandle(snapshot)
	var procEntry syscall.ProcessEntry32
	procEntry.Size = uint32(unsafe.Sizeof(procEntry))
	if err = syscall.Process32First(snapshot, &procEntry); err != nil {
		return nil, err
	}
	for {
		if procEntry.ProcessID == uint32(pid) {
			return &procEntry, nil
		}
		err = syscall.Process32Next(snapshot, &procEntry)
		if err != nil {
			return nil, err
		}
	}
}

// StartedByExplorer returns true if the program was invoked by the user double-clicking
// on the executable from explorer.exe
//
// It is conservative and returns false if any of the internal calls fail.
// It does not guarantee that the program was run from a terminal. It only can tell you
// whether it was launched from explorer.exe
func StartedByExplorer() bool {
	pe, err := getProcessEntry(os.Getppid())
	if err != nil {
		return false
	}
	return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:])
}


text:
// +build !windows

package mousetrap

// StartedByExplorer returns true if the program was invoked by the user
// double-clicking on the executable from explorer.exe
//
// It is conservative and returns false if any of the internal calls fail.
// It does not guarantee that the program was run from a terminal. It only can tell you
// whether it was launched from explorer.exe
//
// On non-Windows platforms, it always returns false.
func StartedByExplorer() bool {
	return false
}


text:
# mousetrap

mousetrap is a tiny library that answers a single question.

On a Windows machine, was the process invoked by someone double clicking on
the executable file while browsing in explorer?

### Motivation

Windows developers unfamiliar with command line tools will often "double-click"
the executable for a tool. Because most CLI tools print the help and then exit
when invoked without arguments, this is often very frustrating for those users.

mousetrap provides a way to detect these invocations so that you can provide
more helpful behavior and instructions on how to run the CLI tool. To see what
this looks like, both from an organizational and a technical perspective, see
https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/

### The interface

The library exposes a single interface:

    func StartedByExplorer() (bool)


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	"bytes"

	. "gopkg.in/check.v1"
)

type codecTestSuite struct{}

var _ = Suite(&codecTestSuite{})

func (s *codecTestSuite) TestFromBytes(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	u1, err := FromBytes(b1)
	c.Assert(err, IsNil)
	c.Assert(u1, Equals, u)

	b2 := []byte{}
	_, err = FromBytes(b2)
	c.Assert(err, NotNil)
}

func (s *codecTestSuite) BenchmarkFromBytes(c *C) {
	bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	for i := 0; i < c.N; i++ {
		FromBytes(bytes)
	}
}

func (s *codecTestSuite) TestMarshalBinary(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	b2, err := u.MarshalBinary()
	c.Assert(err, IsNil)
	c.Assert(bytes.Equal(b1, b2), Equals, true)
}

func (s *codecTestSuite) BenchmarkMarshalBinary(c *C) {
	u := NewV4()
	for i := 0; i < c.N; i++ {
		u.MarshalBinary()
	}
}

func (s *codecTestSuite) TestUnmarshalBinary(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	u1 := UUID{}
	err := u1.UnmarshalBinary(b1)
	c.Assert(err, IsNil)
	c.Assert(u1, Equals, u)

	b2 := []byte{}
	u2 := UUID{}
	err = u2.UnmarshalBinary(b2)
	c.Assert(err, NotNil)
}

func (s *codecTestSuite) TestFromString(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
	s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	s4 := "6ba7b8109dad11d180b400c04fd430c8"
	s5 := "urn:uuid:6ba7b8109dad11d180b400c04fd430c8"

	_, err := FromString("")
	c.Assert(err, NotNil)

	u1, err := FromString(s1)
	c.Assert(err, IsNil)
	c.Assert(u1, Equals, u)

	u2, err := FromString(s2)
	c.Assert(err, IsNil)
	c.Assert(u2, Equals, u)

	u3, err := FromString(s3)
	c.Assert(err, IsNil)
	c.Assert(u3, Equals, u)

	u4, err := FromString(s4)
	c.Assert(err, IsNil)
	c.Assert(u4, Equals, u)

	u5, err := FromString(s5)
	c.Assert(err, IsNil)
	c.Assert(u5, Equals, u)
}

func (s *codecTestSuite) BenchmarkFromString(c *C) {
	str := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	for i := 0; i < c.N; i++ {
		FromString(str)
	}
}

func (s *codecTestSuite) BenchmarkFromStringUrn(c *C) {
	str := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	for i := 0; i < c.N; i++ {
		FromString(str)
	}
}

func (s *codecTestSuite) BenchmarkFromStringWithBrackets(c *C) {
	str := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
	for i := 0; i < c.N; i++ {
		FromString(str)
	}
}

func (s *codecTestSuite) TestFromStringShort(c *C) {
	// Invalid 35-character UUID string
	s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c"

	for i := len(s1); i >= 0; i-- {
		_, err := FromString(s1[:i])
		c.Assert(err, NotNil)
	}
}

func (s *codecTestSuite) TestFromStringLong(c *C) {
	// Invalid 37+ character UUID string
	strings := []string{
		"6ba7b810-9dad-11d1-80b4-00c04fd430c8=",
		"6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
		"{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f",
		"6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8",
	}

	for _, str := range strings {
		_, err := FromString(str)
		c.Assert(err, NotNil)
	}
}

func (s *codecTestSuite) TestFromStringInvalid(c *C) {
	// Invalid UUID string formats
	strings := []string{
		"6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8",
		"urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
		"uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
		"uuid:urn:6ba7b8109dad11d180b400c04fd430c8",
		"6ba7b8109-dad-11d1-80b4-00c04fd430c8",
		"6ba7b810-9dad1-1d1-80b4-00c04fd430c8",
		"6ba7b810-9dad-11d18-0b4-00c04fd430c8",
		"6ba7b810-9dad-11d1-80b40-0c04fd430c8",
		"6ba7b810+9dad+11d1+80b4+00c04fd430c8",
		"(6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
		"{6ba7b810-9dad-11d1-80b4-00c04fd430c8>",
		"zba7b810-9dad-11d1-80b4-00c04fd430c8",
		"6ba7b810-9dad11d180b400c04fd430c8",
		"6ba7b8109dad-11d180b400c04fd430c8",
		"6ba7b8109dad11d1-80b400c04fd430c8",
		"6ba7b8109dad11d180b4-00c04fd430c8",
	}

	for _, str := range strings {
		_, err := FromString(str)
		c.Assert(err, NotNil)
	}
}

func (s *codecTestSuite) TestFromStringOrNil(c *C) {
	u := FromStringOrNil("")
	c.Assert(u, Equals, Nil)
}

func (s *codecTestSuite) TestFromBytesOrNil(c *C) {
	b := []byte{}
	u := FromBytesOrNil(b)
	c.Assert(u, Equals, Nil)
}

func (s *codecTestSuite) TestMarshalText(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")

	b2, err := u.MarshalText()
	c.Assert(err, IsNil)
	c.Assert(bytes.Equal(b1, b2), Equals, true)
}

func (s *codecTestSuite) BenchmarkMarshalText(c *C) {
	u := NewV4()
	for i := 0; i < c.N; i++ {
		u.MarshalText()
	}
}

func (s *codecTestSuite) TestUnmarshalText(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")

	u1 := UUID{}
	err := u1.UnmarshalText(b1)
	c.Assert(err, IsNil)
	c.Assert(u1, Equals, u)

	b2 := []byte("")
	u2 := UUID{}
	err = u2.UnmarshalText(b2)
	c.Assert(err, NotNil)
}

func (s *codecTestSuite) BenchmarkUnmarshalText(c *C) {
	bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	u := UUID{}
	for i := 0; i < c.N; i++ {
		u.UnmarshalText(bytes)
	}
}

var sink string

func (s *codecTestSuite) BenchmarkMarshalToString(c *C) {
	u := NewV4()
	for i := 0; i < c.N; i++ {
		sink = u.String()
	}
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	"bytes"
	"testing"

	. "gopkg.in/check.v1"
)

// Hook up gocheck into the "go test" runner.
func TestUUID(t *testing.T) { TestingT(t) }

type testSuite struct{}

var _ = Suite(&testSuite{})

func (s *testSuite) TestBytes(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	c.Assert(bytes.Equal(u.Bytes(), bytes1), Equals, true)
}

func (s *testSuite) TestString(c *C) {
	c.Assert(NamespaceDNS.String(), Equals, "6ba7b810-9dad-11d1-80b4-00c04fd430c8")
}

func (s *testSuite) TestEqual(c *C) {
	c.Assert(Equal(NamespaceDNS, NamespaceDNS), Equals, true)
	c.Assert(Equal(NamespaceDNS, NamespaceURL), Equals, false)
}

func (s *testSuite) TestVersion(c *C) {
	u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	c.Assert(u.Version(), Equals, V1)
}

func (s *testSuite) TestSetVersion(c *C) {
	u := UUID{}
	u.SetVersion(4)
	c.Assert(u.Version(), Equals, V4)
}

func (s *testSuite) TestVariant(c *C) {
	u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	c.Assert(u1.Variant(), Equals, VariantNCS)

	u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	c.Assert(u2.Variant(), Equals, VariantRFC4122)

	u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	c.Assert(u3.Variant(), Equals, VariantMicrosoft)

	u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	c.Assert(u4.Variant(), Equals, VariantFuture)
}

func (s *testSuite) TestSetVariant(c *C) {
	u := UUID{}
	u.SetVariant(VariantNCS)
	c.Assert(u.Variant(), Equals, VariantNCS)
	u.SetVariant(VariantRFC4122)
	c.Assert(u.Variant(), Equals, VariantRFC4122)
	u.SetVariant(VariantMicrosoft)
	c.Assert(u.Variant(), Equals, VariantMicrosoft)
	u.SetVariant(VariantFuture)
	c.Assert(u.Variant(), Equals, VariantFuture)
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"hash"
	"net"
	"os"
	"sync"
	"time"
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

var (
	global = newDefaultGenerator()

	epochFunc = unixTimeFunc
	posixUID  = uint32(os.Getuid())
	posixGID  = uint32(os.Getgid())
)

// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
	return global.NewV1()
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
	return global.NewV2(domain)
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
	return global.NewV3(ns, name)
}

// NewV4 returns random generated UUID.
func NewV4() UUID {
	return global.NewV4()
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
	return global.NewV5(ns, name)
}

// Generator provides interface for generating UUIDs.
type Generator interface {
	NewV1() UUID
	NewV2(domain byte) UUID
	NewV3(ns UUID, name string) UUID
	NewV4() UUID
	NewV5(ns UUID, name string) UUID
}

// Default generator implementation.
type generator struct {
	storageOnce  sync.Once
	storageMutex sync.Mutex

	lastTime      uint64
	clockSequence uint16
	hardwareAddr  [6]byte
}

func newDefaultGenerator() Generator {
	return &generator{}
}

// NewV1 returns UUID based on current timestamp and MAC address.
func (g *generator) NewV1() UUID {
	u := UUID{}

	timeNow, clockSeq, hardwareAddr := g.getStorage()

	binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)

	copy(u[10:], hardwareAddr)

	u.SetVersion(V1)
	u.SetVariant(VariantRFC4122)

	return u
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func (g *generator) NewV2(domain byte) UUID {
	u := UUID{}

	timeNow, clockSeq, hardwareAddr := g.getStorage()

	switch domain {
	case DomainPerson:
		binary.BigEndian.PutUint32(u[0:], posixUID)
	case DomainGroup:
		binary.BigEndian.PutUint32(u[0:], posixGID)
	}

	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)
	u[9] = domain

	copy(u[10:], hardwareAddr)

	u.SetVersion(V2)
	u.SetVariant(VariantRFC4122)

	return u
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func (g *generator) NewV3(ns UUID, name string) UUID {
	u := newFromHash(md5.New(), ns, name)
	u.SetVersion(V3)
	u.SetVariant(VariantRFC4122)

	return u
}

// NewV4 returns random generated UUID.
func (g *generator) NewV4() UUID {
	u := UUID{}
	g.safeRandom(u[:])
	u.SetVersion(V4)
	u.SetVariant(VariantRFC4122)

	return u
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func (g *generator) NewV5(ns UUID, name string) UUID {
	u := newFromHash(sha1.New(), ns, name)
	u.SetVersion(V5)
	u.SetVariant(VariantRFC4122)

	return u
}

func (g *generator) initStorage() {
	g.initClockSequence()
	g.initHardwareAddr()
}

func (g *generator) initClockSequence() {
	buf := make([]byte, 2)
	g.safeRandom(buf)
	g.clockSequence = binary.BigEndian.Uint16(buf)
}

func (g *generator) initHardwareAddr() {
	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			if len(iface.HardwareAddr) >= 6 {
				copy(g.hardwareAddr[:], iface.HardwareAddr)
				return
			}
		}
	}

	// Initialize hardwareAddr randomly in case
	// of real network interfaces absence
	g.safeRandom(g.hardwareAddr[:])

	// Set multicast bit as recommended in RFC 4122
	g.hardwareAddr[0] |= 0x01
}

func (g *generator) safeRandom(dest []byte) {
	if _, err := rand.Read(dest); err != nil {
		panic(err)
	}
}

// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func (g *generator) getStorage() (uint64, uint16, []byte) {
	g.storageOnce.Do(g.initStorage)

	g.storageMutex.Lock()
	defer g.storageMutex.Unlock()

	timeNow := epochFunc()
	// Clock changed backwards since last UUID generation.
	// Should increase clock sequence.
	if timeNow <= g.lastTime {
		g.clockSequence++
	}
	g.lastTime = timeNow

	return timeNow, g.clockSequence, g.hardwareAddr[:]
}

// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
	return epochStart + uint64(time.Now().UnixNano()/100)
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
	u := UUID{}
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))

	return u
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	. "gopkg.in/check.v1"
)

type sqlTestSuite struct{}

var _ = Suite(&sqlTestSuite{})

func (s *sqlTestSuite) TestValue(c *C) {
	u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	c.Assert(err, IsNil)

	val, err := u.Value()
	c.Assert(err, IsNil)
	c.Assert(val, Equals, u.String())
}

func (s *sqlTestSuite) TestValueNil(c *C) {
	u := UUID{}

	val, err := u.Value()
	c.Assert(err, IsNil)
	c.Assert(val, Equals, Nil.String())
}

func (s *sqlTestSuite) TestNullUUIDValueNil(c *C) {
	u := NullUUID{}

	val, err := u.Value()
	c.Assert(err, IsNil)
	c.Assert(val, IsNil)
}

func (s *sqlTestSuite) TestScanBinary(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	u1 := UUID{}
	err := u1.Scan(b1)
	c.Assert(err, IsNil)
	c.Assert(u, Equals, u1)

	b2 := []byte{}
	u2 := UUID{}

	err = u2.Scan(b2)
	c.Assert(err, NotNil)
}

func (s *sqlTestSuite) TestScanString(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

	u1 := UUID{}
	err := u1.Scan(s1)
	c.Assert(err, IsNil)
	c.Assert(u, Equals, u1)

	s2 := ""
	u2 := UUID{}

	err = u2.Scan(s2)
	c.Assert(err, NotNil)
}

func (s *sqlTestSuite) TestScanText(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")

	u1 := UUID{}
	err := u1.Scan(b1)
	c.Assert(err, IsNil)
	c.Assert(u, Equals, u1)

	b2 := []byte("")
	u2 := UUID{}
	err = u2.Scan(b2)
	c.Assert(err, NotNil)
}

func (s *sqlTestSuite) TestScanUnsupported(c *C) {
	u := UUID{}

	err := u.Scan(true)
	c.Assert(err, NotNil)
}

func (s *sqlTestSuite) TestScanNil(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}

	err := u.Scan(nil)
	c.Assert(err, NotNil)
}

func (s *sqlTestSuite) TestNullUUIDScanValid(c *C) {
	u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"

	u1 := NullUUID{}
	err := u1.Scan(s1)
	c.Assert(err, IsNil)
	c.Assert(u1.Valid, Equals, true)
	c.Assert(u1.UUID, Equals, u)
}

func (s *sqlTestSuite) TestNullUUIDScanNil(c *C) {
	u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true}

	err := u.Scan(nil)
	c.Assert(err, IsNil)
	c.Assert(u.Valid, Equals, false)
	c.Assert(u.UUID, Equals, Nil)
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	"bytes"
	"encoding/hex"
	"fmt"
)

// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
	err = u.UnmarshalBinary(input)
	return
}

// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
	uuid, err := FromBytes(input)
	if err != nil {
		return Nil
	}
	return uuid
}

// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
	err = u.UnmarshalText([]byte(input))
	return
}

// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
	uuid, err := FromString(input)
	if err != nil {
		return Nil
	}
	return uuid
}

// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
	text = []byte(u.String())
	return
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
//   "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
//   "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
//   "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
//   "6ba7b8109dad11d180b400c04fd430c8"
// ABNF for supported UUID text representation follows:
//   uuid := canonical | hashlike | braced | urn
//   plain := canonical | hashlike
//   canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
//   hashlike := 12hexoct
//   braced := '{' plain '}'
//   urn := URN ':' UUID-NID ':' plain
//   URN := 'urn'
//   UUID-NID := 'uuid'
//   12hexoct := 6hexoct 6hexoct
//   6hexoct := 4hexoct 2hexoct
//   4hexoct := 2hexoct 2hexoct
//   2hexoct := hexoct hexoct
//   hexoct := hexdig hexdig
//   hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
//             'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
//             'A' | 'B' | 'C' | 'D' | 'E' | 'F'
func (u *UUID) UnmarshalText(text []byte) (err error) {
	switch len(text) {
	case 32:
		return u.decodeHashLike(text)
	case 36:
		return u.decodeCanonical(text)
	case 38:
		return u.decodeBraced(text)
	case 41:
		fallthrough
	case 45:
		return u.decodeURN(text)
	default:
		return fmt.Errorf("uuid: incorrect UUID length: %s", text)
	}
}

// decodeCanonical decodes UUID string in format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
func (u *UUID) decodeCanonical(t []byte) (err error) {
	if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
		return fmt.Errorf("uuid: incorrect UUID format %s", t)
	}

	src := t[:]
	dst := u[:]

	for i, byteGroup := range byteGroups {
		if i > 0 {
			src = src[1:] // skip dash
		}
		_, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
		if err != nil {
			return
		}
		src = src[byteGroup:]
		dst = dst[byteGroup/2:]
	}

	return
}

// decodeHashLike decodes UUID string in format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeHashLike(t []byte) (err error) {
	src := t[:]
	dst := u[:]

	if _, err = hex.Decode(dst, src); err != nil {
		return err
	}
	return
}

// decodeBraced decodes UUID string in format
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
// "{6ba7b8109dad11d180b400c04fd430c8}".
func (u *UUID) decodeBraced(t []byte) (err error) {
	l := len(t)

	if t[0] != '{' || t[l-1] != '}' {
		return fmt.Errorf("uuid: incorrect UUID format %s", t)
	}

	return u.decodePlain(t[1 : l-1])
}

// decodeURN decodes UUID string in format
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodeURN(t []byte) (err error) {
	total := len(t)

	urn_uuid_prefix := t[:9]

	if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
		return fmt.Errorf("uuid: incorrect UUID format: %s", t)
	}

	return u.decodePlain(t[9:total])
}

// decodePlain decodes UUID string in canonical format
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
// "6ba7b8109dad11d180b400c04fd430c8".
func (u *UUID) decodePlain(t []byte) (err error) {
	switch len(t) {
	case 32:
		return u.decodeHashLike(t)
	case 36:
		return u.decodeCanonical(t)
	default:
		return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
	}
}

// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
	data = u.Bytes()
	return
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
	if len(data) != Size {
		err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
		return
	}
	copy(u[:], data)

	return
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	. "gopkg.in/check.v1"
)

type genTestSuite struct{}

var _ = Suite(&genTestSuite{})

func (s *genTestSuite) TestNewV1(c *C) {
	u := NewV1()
	c.Assert(u.Version(), Equals, V1)
	c.Assert(u.Variant(), Equals, VariantRFC4122)

	u1 := NewV1()
	u2 := NewV1()
	c.Assert(u1, Not(Equals), u2)

	oldFunc := epochFunc
	epochFunc = func() uint64 { return 0 }

	u3 := NewV1()
	u4 := NewV1()
	c.Assert(u3, Not(Equals), u4)

	epochFunc = oldFunc
}

func (s *genTestSuite) BenchmarkNewV1(c *C) {
	for i := 0; i < c.N; i++ {
		NewV1()
	}
}

func (s *genTestSuite) TestNewV2(c *C) {
	u1 := NewV2(DomainPerson)
	c.Assert(u1.Version(), Equals, V2)
	c.Assert(u1.Variant(), Equals, VariantRFC4122)

	u2 := NewV2(DomainGroup)
	c.Assert(u2.Version(), Equals, V2)
	c.Assert(u2.Variant(), Equals, VariantRFC4122)
}

func (s *genTestSuite) BenchmarkNewV2(c *C) {
	for i := 0; i < c.N; i++ {
		NewV2(DomainPerson)
	}
}

func (s *genTestSuite) TestNewV3(c *C) {
	u := NewV3(NamespaceDNS, "www.example.com")
	c.Assert(u.Version(), Equals, V3)
	c.Assert(u.Variant(), Equals, VariantRFC4122)
	c.Assert(u.String(), Equals, "5df41881-3aed-3515-88a7-2f4a814cf09e")

	u = NewV3(NamespaceDNS, "python.org")
	c.Assert(u.String(), Equals, "6fa459ea-ee8a-3ca4-894e-db77e160355e")

	u1 := NewV3(NamespaceDNS, "golang.org")
	u2 := NewV3(NamespaceDNS, "golang.org")
	c.Assert(u1, Equals, u2)

	u3 := NewV3(NamespaceDNS, "example.com")
	c.Assert(u1, Not(Equals), u3)

	u4 := NewV3(NamespaceURL, "golang.org")
	c.Assert(u1, Not(Equals), u4)
}

func (s *genTestSuite) BenchmarkNewV3(c *C) {
	for i := 0; i < c.N; i++ {
		NewV3(NamespaceDNS, "www.example.com")
	}
}

func (s *genTestSuite) TestNewV4(c *C) {
	u := NewV4()
	c.Assert(u.Version(), Equals, V4)
	c.Assert(u.Variant(), Equals, VariantRFC4122)
}

func (s *genTestSuite) BenchmarkNewV4(c *C) {
	for i := 0; i < c.N; i++ {
		NewV4()
	}
}

func (s *genTestSuite) TestNewV5(c *C) {
	u := NewV5(NamespaceDNS, "www.example.com")
	c.Assert(u.Version(), Equals, V5)
	c.Assert(u.Variant(), Equals, VariantRFC4122)

	u = NewV5(NamespaceDNS, "python.org")
	c.Assert(u.String(), Equals, "886313e1-3b8a-5372-9b90-0c9aee199e5d")

	u1 := NewV5(NamespaceDNS, "golang.org")
	u2 := NewV5(NamespaceDNS, "golang.org")
	c.Assert(u1, Equals, u2)

	u3 := NewV5(NamespaceDNS, "example.com")
	c.Assert(u1, Not(Equals), u3)

	u4 := NewV5(NamespaceURL, "golang.org")
	c.Assert(u1, Not(Equals), u4)
}

func (s *genTestSuite) BenchmarkNewV5(c *C) {
	for i := 0; i < c.N; i++ {
		NewV5(NamespaceDNS, "www.example.com")
	}
}


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid

import (
	"bytes"
	"encoding/hex"
)

// Size of a UUID in bytes.
const Size = 16

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [Size]byte

// UUID versions
const (
	_ byte = iota
	V1
	V2
	V3
	V4
	V5
)

// UUID layout variants.
const (
	VariantNCS byte = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// UUID DCE domains.
const (
	DomainPerson = iota
	DomainGroup
	DomainOrg
)

// String parse helpers.
var (
	urnPrefix  = []byte("urn:uuid:")
	byteGroups = []int{8, 4, 4, 4, 12}
)

// Nil is special form of UUID that is specified to have all
// 128 bits set to zero.
var Nil = UUID{}

// Predefined namespace UUIDs.
var (
	NamespaceDNS  = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
	NamespaceURL  = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
	NamespaceOID  = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
	NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
)

// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
	return bytes.Equal(u1[:], u2[:])
}

// Version returns algorithm version used to generate UUID.
func (u UUID) Version() byte {
	return u[6] >> 4
}

// Variant returns UUID layout variant.
func (u UUID) Variant() byte {
	switch {
	case (u[8] >> 7) == 0x00:
		return VariantNCS
	case (u[8] >> 6) == 0x02:
		return VariantRFC4122
	case (u[8] >> 5) == 0x06:
		return VariantMicrosoft
	case (u[8] >> 5) == 0x07:
		fallthrough
	default:
		return VariantFuture
	}
}

// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
	return u[:]
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
	buf := make([]byte, 36)

	hex.Encode(buf[0:8], u[0:4])
	buf[8] = '-'
	hex.Encode(buf[9:13], u[4:6])
	buf[13] = '-'
	hex.Encode(buf[14:18], u[6:8])
	buf[18] = '-'
	hex.Encode(buf[19:23], u[8:10])
	buf[23] = '-'
	hex.Encode(buf[24:], u[10:])

	return string(buf)
}

// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// SetVariant sets variant bits.
func (u *UUID) SetVariant(v byte) {
	switch v {
	case VariantNCS:
		u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
	case VariantRFC4122:
		u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
	case VariantMicrosoft:
		u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
	case VariantFuture:
		fallthrough
	default:
		u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
	}
}

// Must is a helper that wraps a call to a function returning (UUID, error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
//	var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
func Must(u UUID, err error) UUID {
	if err != nil {
		panic(err)
	}
	return u
}


text:
# UUID package for Go language

[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid)
[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid)
[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid)

This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.

With 100% test coverage and benchmarks out of box.

Supported versions:
* Version 1, based on timestamp and MAC address (RFC 4122)
* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
* Version 3, based on MD5 hashing (RFC 4122)
* Version 4, based on random numbers (RFC 4122)
* Version 5, based on SHA-1 hashing (RFC 4122)

## Installation

Use the `go` command:

	$ go get github.com/satori/go.uuid

## Requirements

UUID package requires Go >= 1.2.

## Example

```go
package main

import (
	"fmt"
	"github.com/satori/go.uuid"
)

func main() {
	// Creating UUID Version 4
	u1 := uuid.NewV4()
	fmt.Printf("UUIDv4: %s\n", u1)

	// Parsing UUID from string input
	u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	if err != nil {
		fmt.Printf("Something gone wrong: %s", err)
	}
	fmt.Printf("Successfully parsed: %s", u2)
}
```

## Documentation

[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project.

## Links
* [RFC 4122](http://tools.ietf.org/html/rfc4122)
* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01)

## Copyright

Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>.

UUID package released under MIT License.
See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.


text:
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// 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 uuid

import (
	"database/sql/driver"
	"fmt"
)

// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
	return u.String(), nil
}

// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
	switch src := src.(type) {
	case []byte:
		if len(src) == Size {
			return u.UnmarshalBinary(src)
		}
		return u.UnmarshalText(src)

	case string:
		return u.UnmarshalText([]byte(src))
	}

	return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}

// NullUUID can be used with the standard sql package to represent a
// UUID value that can be NULL in the database
type NullUUID struct {
	UUID  UUID
	Valid bool
}

// Value implements the driver.Valuer interface.
func (u NullUUID) Value() (driver.Value, error) {
	if !u.Valid {
		return nil, nil
	}
	// Delegate to UUID Value function
	return u.UUID.Value()
}

// Scan implements the sql.Scanner interface.
func (u *NullUUID) Scan(src interface{}) error {
	if src == nil {
		u.UUID, u.Valid = Nil, false
		return nil
	}

	// Delegate to UUID Scan function
	u.Valid = true
	return u.UUID.Scan(src)
}


text:
package doclient

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"time"

	"github.com/digitalocean/godo"
	"golang.org/x/oauth2"
)

type Client struct {
	token    string
	doClient *godo.Client
}

func New(token string) *Client {
	ctx := context.Background()
	httpClient := &http.Client{
		Timeout: 10 * time.Second,
		Transport: &http.Transport{
			DialContext: (&net.Dialer{
				Timeout: 10 * time.Second,
			}).DialContext,
		},
	}
	ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
	oauthClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}))
	client := &Client{
		token:    token,
		doClient: godo.NewClient(oauthClient),
	}
	return client
}

func (c *Client) WaitForDropletIP(dropletID int) (ip string, err error) {
	for attempt := 1; ip == ""; attempt++ {
		time.Sleep(time.Duration(attempt) * time.Second) // linear backoff

		droplet, _, err := c.doClient.Droplets.Get(context.TODO(), dropletID)
		if err != nil {
			return "", err
		}

		for _, nv4 := range droplet.Networks.V4 {
			if nv4.IPAddress != "" {
				ip = nv4.IPAddress
			}
		}
		if attempt >= 10 {
			return "", fmt.Errorf("Timeout waiting for provisioning of droplet %v", dropletID)
		}
	}
	return ip, nil
}

func (c *Client) CreateSSHKey(name, publicKey string) (id int, err error) {
	createRequest := &godo.KeyCreateRequest{
		Name:      "dosxvpn",
		PublicKey: publicKey,
	}
	key, _, err := c.doClient.Keys.Create(context.TODO(), createRequest)
	if err != nil {
		return 0, err
	}
	return key.ID, nil
}

func (c *Client) CreateDroplet(name, region, size, userData, image string) (id int, err error) {
	createRequest := &godo.DropletCreateRequest{
		Name:     name,
		Region:   region,
		Size:     size,
		UserData: userData,
		Image: godo.DropletCreateImage{
			Slug: image,
		},
		IPv6: true,
	}

	accountSSHKeys, err := c.GetAccountSSHKeys()
	if err != nil {
		return 0, err
	}
	for _, key := range accountSSHKeys {
		keyToAdd := godo.DropletCreateSSHKey{ID: key.ID}
		createRequest.SSHKeys = append(createRequest.SSHKeys, keyToAdd)
	}

	droplet, _, err := c.doClient.Droplets.Create(context.TODO(), createRequest)
	if err != nil {
		return 0, err
	}
	return droplet.ID, nil
}

func (c *Client) CreateFirewall(name string, dropletID int) error {
	fwRequest := &godo.FirewallRequest{
		Name:          name,
		DropletIDs:    []int{dropletID},
		InboundRules:  c.generateInboundFirewallRules(),
		OutboundRules: c.generateOutboundFirewallRules(),
	}
	_, _, err := c.doClient.Firewalls.Create(context.TODO(), fwRequest)
	if err != nil {
		return err
	}
	return nil
}

func (c *Client) ListDroplets() (droplets []godo.Droplet, err error) {
	droplets, _, err = c.doClient.Droplets.List(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	return droplets, nil
}

func (c *Client) ListRegions() (regions map[string]string, err error) {
	r, _, err := c.doClient.Regions.List(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	regions = make(map[string]string)
	for _, region := range r {
		regions[region.Slug] = region.Name
	}
	return regions, nil
}

func (c *Client) DeleteDroplet(dropletID int) error {
	_, err := c.doClient.Droplets.Delete(context.TODO(), dropletID)
	if err != nil {
		return fmt.Errorf("Failed to remove droplet %v. %v", dropletID, err)
	}
	return nil
}

func (c *Client) ListFirewalls() (firewalls []godo.Firewall, err error) {
	firewalls, _, err = c.doClient.Firewalls.List(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	return firewalls, nil
}

func (c *Client) DeleteFirewall(firewallID string) error {
	_, err := c.doClient.Firewalls.Delete(context.TODO(), firewallID)
	if err != nil {
		return fmt.Errorf("Failed to remove droplet %v. %v", firewallID, err)
	}
	return nil
}

func (c *Client) GetAccountSSHKeys() ([]godo.Key, error) {
	keys, _, err := c.doClient.Keys.List(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	return keys, nil
}

func (c *Client) generateInboundFirewallRules() []godo.InboundRule {
	return []godo.InboundRule{
		{
			Protocol: "icmp",
			Sources: &godo.Sources{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
		{
			Protocol:  "tcp",
			PortRange: "22",
			Sources: &godo.Sources{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
		{
			Protocol:  "udp",
			PortRange: "500",
			Sources: &godo.Sources{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
		{
			Protocol:  "udp",
			PortRange: "4500",
			Sources: &godo.Sources{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
	}
}
func (c *Client) generateOutboundFirewallRules() []godo.OutboundRule {
	return []godo.OutboundRule{
		{
			Protocol: "icmp",
			Destinations: &godo.Destinations{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
		{
			Protocol:  "tcp",
			PortRange: "all",
			Destinations: &godo.Destinations{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
		{
			Protocol:  "udp",
			PortRange: "all",
			Destinations: &godo.Destinations{
				Addresses: []string{"0.0.0.0/0", "::/0"},
			},
		},
	}
}


text:
package vpn

import (
	"fmt"
	"os/exec"
	"os/user"
)

func OSXAddVPN(mobileConfigPath string) error {
	user, err := user.Current()
	if err != nil {
		return err
	}
	cmd := exec.Command("profiles", "-U", user.Username, "-I", "-F", mobileConfigPath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Failed to add VPN. Output: %s. Error: %v", output, err)
	}

	exec.Command("open", "/System/Library/CoreServices/Menu Extras/VPN.menu/").Start()

	return nil
}

func OSXRemoveVPN(name string) error {
	user, err := user.Current()
	if err != nil {
		return err
	}

	cmd := exec.Command("profiles", "-U", user.Username, "-R", "-p", "com.github.dan-v.dosxvpn."+name)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Failed to remove VPN. Output: %s. Error: %v", output, err)
	}
	return nil
}


text:
package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

var RootCmd = &cobra.Command{
	Use:   "dosxvpn",
	Short: "One click personal VPN server on DigitalOcean",
}

func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	fmt.Println(`
___  ____ ____ _  _ _  _ ___  _  _
|  \ |  | [__   \/  |  | |__] |\ |
|__/ |__| ___] _/\_  \/  |    | \|

`)
}


text:
package cmd

import (
	"log"
	"os"
)

func digitalOceanTokenEnvSet() bool {
	token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
	if token == "" {
		return false
	}
	return true
}

func getCliToken() string {
	token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
	if token == "" {
		log.Fatal("Must have environment variable DIGITALOCEAN_ACCESS_TOKEN set")
	}
	return token
}


text:
package cmd

import (
	"log"

	"github.com/spf13/cobra"

	"github.com/dan-v/dosxvpn/deploy"
)

var name string
var removeProfile bool

var rmCmd = &cobra.Command{
	Use:   "rm",
	Short: "Remove dosxvpn VPN server",
	Args: func(cmd *cobra.Command, args []string) error {
		if name == "" {
			return errorMissingName
		}
		if !digitalOceanTokenEnvSet() {
			return errorMissingToken
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		_, err := deploy.RemoveVPN(getCliToken(), name, removeProfile)
		if err != nil {
			log.Fatal(err)
		}
		log.Println("Successfully removed", name)
	},
}

func init() {
	RootCmd.AddCommand(rmCmd)
	rmCmd.Flags().StringVar(&name, "name", "", "Name of droplet to remove")
	rmCmd.Flags().BoolVar(&removeProfile, "remove-profile", false, "Remove VPN profile as well (only for OSX).")
}


text:
package cmd

import (
	"log"

	"github.com/spf13/cobra"

	"github.com/dan-v/dosxvpn/deploy"
)

var listCmd = &cobra.Command{
	Use:   "ls",
	Short: "List dosxvpn VPN servers",
	Args: func(cmd *cobra.Command, args []string) error {
		if !digitalOceanTokenEnvSet() {
			return errorMissingToken
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		token := getCliToken()
		droplets, err := deploy.ListVpns(token)
		if err != nil {
			log.Fatalln(err)
		}
		log.Println(droplets)
	},
}

func init() {
	RootCmd.AddCommand(listCmd)
}


text:
package cmd

import (
	"log"

	"github.com/dan-v/dosxvpn/deploy"
	"github.com/spf13/cobra"
)

var region string
var autoConfigure bool

var deployCmd = &cobra.Command{
	Use:   "deploy",
	Short: "Deploy dosxvpn VPN server",
	Args: func(cmd *cobra.Command, args []string) error {
		if region == "" {
			return errorMissingRegion
		}
		if !digitalOceanTokenEnvSet() {
			return errorMissingToken
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		deployment, err := deploy.New(getCliToken(), region, autoConfigure)
		if err != nil {
			log.Fatal("Deployment failed:", err)
		}
		err = deployment.Run()
		if err != nil {
			log.Fatal("Deployment failed:", err)
		}
	},
}

func init() {
	RootCmd.AddCommand(deployCmd)

	deployCmd.Flags().StringVar(&region, "region", "", "Region to deploy droplet (e.g. ams2,ams3,nyc1,nyc2,nyc3,sfo1,sfo2).")
	deployCmd.Flags().BoolVar(&autoConfigure, "auto-configure", false, "Auto configure VPN (only for OSX).")
}


text:
package cmd

import (
	"github.com/spf13/cobra"

	"github.com/dan-v/dosxvpn/web"
)

var webCmd = &cobra.Command{
	Use:   "web",
	Short: "Run web installer",

	Run: func(cmd *cobra.Command, args []string) {
		cleanup := false
		if len(args) > 0 {
			cleanup = true
		}
		web.Run(cleanup)
	},
}

func init() {
	RootCmd.AddCommand(webCmd)
}


text:
package cmd

import "errors"

var (
	errorMissingToken  = errors.New("need to have environment variable DIGITALOCEAN_ACCESS_TOKEN set")
	errorMissingRegion = errors.New("need to specify region")
	errorMissingName   = errors.New("need to specify name")
)


text:
#!/bin/sh

./dosxvpn web cleanup


text:
#!/bin/bash

./platypus -y --admin-privileges --quit-after-execution --app-icon 'appicon.icns'  --name 'dosxvpn'  --interface-type 'None'  --interpreter '/bin/sh'  --bundled-file '../build/osx/x86-64/dosxvpn' --bundled-file '../static'  'run.sh' ../build/osx/x86-64/dosxvpn


text:
include AUTHORS
include LICENSE
include DESCRIPTION
include CHANGELOG.txt
include README.md
recursive-include registration_email *.py *.txt *.html *.mo *.po *.css
prune registration_email/.ropeproject
exclude *.orig *.pyc

repo_name: bitlabstudio/django-registration-email

repo_language: Python

mime_type: text/html


text:
=== 0.10.X (to be released as 0.11) ===

=== 0.10 ===

- Updated urls.py to be compatible with recent Django versions (
  no longer using `patterns`)

=== 0.9 ===

- Fixed all auth_urls - we have to keep the original URL names because Django
  uses them internally. You might want to search for `auth_` in your templates
  and only keep it for `auth_login` and `auth_logout` but remove it from the
  other URLs

=== 0.8 ===

- Fixed password_change_done URL name

=== 0.7.2 ===

- Prepared for Python 3 and fixed email validator import

=== 0.7.1 ===

- Added title block to all templates

=== 0.7 ===

- Added login_remember_me view function
- Added remember_me field to EmailLoginForm

=== 0.6 ===

- Changed URL settings due to misuse of get_success_url function in
  django-registration app
- updated to support django-registration's new class based views

=== 0.5.4 ===

- updated Manifest.in to include missing style sheet

=== 0.5.3 ===

- stripping whitespace from email string in registration form

=== 0.5.2 ===

- Changed deprecated import

=== 0.5.1 ===

- using hashlib instead of deprecated md5 module

=== 0.5 ===

- Added dutch translation

=== 0.4.1 ===

- Fixed a bad <p> tag

=== 0.4 ===

- Added registration_base.html template.

=== 0.3 ===

- making sure to save emails as lower case all the time

=== 0.2.4 ===

- BUGFIX!! Fixed typo in urls.py. Thanks to `DmitryGit` for reporting this!

=== 0.2.3 ===

- Replaced usage of `direct_to_template` with `TemplateView` because the former
  doesn't exist in Django 1.5 any more.

=== 0.2.2 ===

- made username generation more robust to avoid name clashes

=== 0.2.1 ===

- Added method `generate_username` in `forms.py` so you can re-use it in your
  own apps.

=== 0.2.0 ===

- Added new settings: REGISTRATION_EMAIL_REGISTER_SUCCESS_URL and
  REGISTRATION_EMAIL_ACTIVATE_SUCCESS_URL. This allows to override the standard
  redirect without overriding the urls.py.

=== 0.1.0 ===

- Added URLs for the simple backend of django-registration.

=== 0.0.1 ===

- Initial commit


text:
Current or previous core committers

* Martin Brochhaus

Contributors (in alphabetical order)

* Alper Cugun (alper)
* Brian Thorne
* Emiliano Dalla Verde Marcozzi (edvm)
* Gijs Nijholt
* Julien Poissonnier (julienp)
* Kars (kaeru)
* Mystic-Mirage
* nanthony
* Pascal Jürgens (trifle)
* Viator (viatoriche)


text:
import os

from setuptools import setup, find_packages

import registration_email

def read(fname):
    try:
        return open(os.path.join(os.path.dirname(__file__), fname)).read()
    except IOError:
        return ''

setup(
    name="django-registration-email",
    version=registration_email.__version__,
    description=read('DESCRIPTION'),
    long_description=read('README.md'),
    keywords='django, registration, email, backend',
    packages=find_packages(),
    author='Martin Brochhaus',
    author_email='martin.brochhaus@gmail.com',
    url="http://github.com/bitmazk/django-registration-email",
    include_package_data=True,
    test_suite='registration_email.tests.runtests.runtests',
)


text:
Important
=========

This app has been discontinued due to the give-up of django-registration. Also there are a lot of well developed and more extensive alternatives on the market.

Why don't you check out ``django-allauth``: https://github.com/pennersr/django-allauth

It's already integrated in our project template (incl. templates & settings): https://github.com/bitmazk/django-project-template/
It's configured the way we used this app.

django-registration-email
==========================

We use
[django-registration](https://bitbucket.org/ubernostrum/django-registration/overview)
in almost all our projects. However, we don't like Django's limited username
and would like to allow our users to sign up via email.

This project provides a custom authentication backend which allows users to
authenticate via email. We also provide an EmailRegistrationForm which
checks if an email has already been taken.

Since we still have to store a username and since emails can easily be longer
than 30 characters, the username will be computed as a md5 hexdigest of the
email address.

We included a ``urls.py`` that overrides all URLs of django-registration
and Django's auth with a clean and sane structure and you will find a default
set of all necessary templates.

Usage
======

Install this package::

    pip install -e git://github.com/bitmazk/django-registration-email#egg=registration_email

Add ``registration`` and ``registration_email`` to your ``INSTALLED_APPS``::

    INSTALLED_APPS = [
        # all your other apps
        'registration',
        'registration_email',
    ]

Update your ``urls.py``::

    url(r'^accounts/', include('registration_email.backends.default.urls')),

Add some settings to your ``settings.py``::

    ACCOUNT_ACTIVATION_DAYS = 7
    AUTHENTICATION_BACKENDS = (
        'registration_email.auth.EmailBackend',
    )
    LOGIN_REDIRECT_URL = '/'

Run ``syncdb``::

    ./manage.py syncdb

Settings
========

django-registration-email introduces a new setting:

REGISTRATION_EMAIL_ACTIVATE_SUCCESS_URL
---------------------------------------

Default: ``lambda request, user: '/'``

Function to return the URL to redirect to after a successful account
activation. If you leave this at ``lambda request, user: '/'`` it will direct
to your base URL.

REGISTRATION_EMAIL_REGISTER_SUCCESS_URL
---------------------------------------

Default: ``lambda request, user: '/'``

Function to return the URL to redirect to after a successful account
registration. If you leave this at ``lambda request, user: '/'`` it will direct
to your base URL.

How to use a custom form
========================

Let's say you want to collect the user's first name and last name when he
registers. In order to achieve that, you need to do the following:

__1. Create a custom form__

Create a new app `my_registration` in your project and give it a `forms.py`
where you override our `EmailRegistrationForm` and your desired extra
fields:

    from django import forms
    from registration_email.forms import EmailRegistrationForm

    class CustomEmailRegistrationForm(EmailRegistrationForm):
        first_name = forms.CharField()
        last_name = forms.CharField()

Do NOT override the form's `save()` method.

__2. Override the URL__

Now you need to tell the registration view that it is supposed to use the
custom form:

    # your main urls.py
    ...
    from django.conf import settings
    from registration.backends.simple.views import RegistrationView
    from my_registration.forms import CustomEmailRegistrationForm

    urlpatterns = [
        ...
        url(
            r'^accounts/register/$',
            RegistrationView.as_view(
                template_name='registration/registration_form.html',
                form_class=CustomEmailRegistrationForm,
                get_success_url=getattr(
                    settings, 'REGISTRATION_EMAIL_REGISTER_SUCCESS_URL',
                    lambda request, user: '/'),
            ),
            name='registration_register',
        ),

        url(r'^accounts/', include('registration_email.backends.default.urls')),
        ...
    ]

__3. Create a signal handler__

In the `urls.py` above I'm using the `SimpleBackend`. When you have a look
at that [backend](https://github.com/nathanborror/django-registration/blob/master/registration/backends/simple/__init__.py#L30)
you will see that the backend sends a signal after creating and logging in the
user. The signal will get all parameters that we need in order to access the
data that has been validated and sent by the form, so let's build a signal
handler:

    # in my_registration.models.py
    from django.dispatch import receiver
    from registration.signals import user_registered

    @receiver(user_registered)
    def user_registered_handler(sender, user, request, **kwargs):
        user.first_name = request.POST.get('first_name')
        user.last_name = request.POST.get('last_name')
        user.save()

This method has the drawback that you save the user two times in a row. If
you have concerns about performance you would have to create your own
`my_registration.backends.CustomRegistrationBackend` class. That class would
inherit `registration.backends.simple.SimpleBackend` and override the
`register` method.

But really, we are talking about registration here, I can't imagine how saving
the user twice could do any harm.

Troubleshooting
================

If you had another value for ``AUTHENTICATION_BACKENDS`` in your
``settings.py`` before it might be that it is saved in your ``django_session``
table. I found no other way around this than to delete the rows in that table.

TODO
=====

* Password reset link points to original django template


text:
"""Views for the registration_email app."""
from django.contrib.auth.views import login

def login_remember_me(request, *args, **kwargs):
    """Custom login view that enables "remember me" functionality."""
    if request.method == 'POST':
        if not request.POST.get('remember_me', None):
            request.session.set_expiry(0)
    return login(request, *args, **kwargs)


text:
# -*- coding: utf-8 -*-
__version__ = '0.10'


text:
"""
Re-definition of Django's auth URLs.

This is done for convenience. It allows us to save all registration and auth
related templates in the same `/templates/registration/` folder.

"""
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from registration_email.forms import EmailAuthenticationForm

from .views import login_remember_me

urlpatterns = [
    url(
        r'^login/$',
        login_remember_me,
        {'template_name': 'registration/login.html',
         'authentication_form': EmailAuthenticationForm, },
        name='auth_login',
    ),
    url(
        r'^logout/$',
        auth_views.logout,
        {'template_name': 'registration/logout.html'},
        name='auth_logout',
    ),
    url(
        r'^password/change/$',
        auth_views.password_change,
        {'template_name': 'registration/password_change_form_custom.html'},
        name='password_change',
    ),
    url(
        r'^password/change/done/$',
        auth_views.password_change_done,
        {'template_name': 'registration/password_change_done_custom.html'},
        name='password_change_done',
        # must be named like this because get's reversed in Django views.py
    ),
    url(
        r'^password/reset/$',
        auth_views.password_reset,
        {'template_name': 'registration/password_reset_form.html'},
        name='password_reset',
    ),
    url(
        r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
        auth_views.password_reset_confirm,
        {'template_name': 'registration/password_reset_confirm.html'},
        name='password_reset_confirm',
    ),
    url(
        r'^password/reset/complete/$',
        auth_views.password_reset_complete,
        {'template_name': 'registration/password_reset_complete.html'},  # NOQA
        name='password_reset_complete',
    ),
    url(
        r'^password/reset/done/$',
        auth_views.password_reset_done,
        {'template_name': 'registration/password_reset_done.html'},
        name='password_reset_done',
    ),
]


text:
"""
Custom authentication backends.

Inspired by http://djangosnippets.org/snippets/2463/

"""
from django.contrib.auth.backends import ModelBackend
from django.core.validators import validate_email

try:
    from django.contrib.auth import get_user_model
    User = get_user_model()
except ImportError:
    from django.contrib.auth.models import User

class EmailBackend(ModelBackend):
    """
    Custom authentication backend that allows to login with an email address.

    """

    supports_object_permissions = True
    supports_anonymous_user = False
    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        try:
            validate_email(username)
        except:
            username_is_email = False
        else:
            username_is_email = True
        if username_is_email:
            try:
                user = User.objects.get(email=username)
            except User.DoesNotExist:
                return None
        else:
            # We have a non-email address username we should try username
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                return None
        if user.check_password(password):
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None


text:
"""Custom registration forms that expects an email address as a username."""
import hashlib
import os

from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

try:
    from django.contrib.auth import get_user_model
    User = get_user_model()
except ImportError:
    from django.contrib.auth.models import User

# I put this on all required fields, because it's easier to pick up
# on them with CSS or JavaScript if they have a class of "required"
# in the HTML. Your mileage may vary. If/when Django ticket #3515
# lands in trunk, this will no longer be necessary.
attrs_dict = {'class': 'required'}

def get_md5_hexdigest(email):
    """
    Returns an md5 hash for a given email.

    The length is 30 so that it fits into Django's ``User.username`` field.

    """
    if isinstance(email, str):  # for py3
        email = email.encode('utf-8')
    return hashlib.md5(email).hexdigest()[0:30]

def generate_username(email):
    """
    Generates a unique username for the given email.

    The username will be an md5 hash of the given email. If the username exists
    we just append `a` to the email until we get a unique md5 hash.

    """
    try:
        User.objects.get(email=email)
        raise Exception('Cannot generate new username. A user with this email'
                        'already exists.')
    except User.DoesNotExist:
        pass

    username = get_md5_hexdigest(email)
    found_unique_username = False
    while not found_unique_username:
        try:
            User.objects.get(username=username)
            email = '{0}a'.format(email.lower())
            username = get_md5_hexdigest(email)
        except User.DoesNotExist:
            found_unique_username = True
            return username

class EmailAuthenticationForm(AuthenticationForm):
    remember_me = forms.BooleanField(
        required=False,
        label=_('Remember me'),
    )

    def __init__(self, *args, **kwargs):
        super(EmailAuthenticationForm, self).__init__(*args, **kwargs)
        self.fields['username'] = forms.CharField(
            label=_("Email"), max_length=256)

    def clean_username(self):
        """Prevent case-sensitive erros in email/username."""
        return self.cleaned_data['username'].lower()

class EmailRegistrationForm(forms.Form):
    """
    Form for registering a new user account.

    Validates that the requested username is not already in use, and
    requires the password to be entered twice to catch typos.

    Subclasses should feel free to add any additional validation they
    need, but should avoid defining a ``save()`` method -- the actual
    saving of collected user data is delegated to the active
    registration backend.

    """
    email = forms.EmailField(
        widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=256)),
        label=_("Email")
    )
    password1 = forms.CharField(
        widget=forms.PasswordInput(attrs=attrs_dict, render_value=False),
        label=_("Password")
    )
    password2 = forms.CharField(
        widget=forms.PasswordInput(attrs=attrs_dict, render_value=False),
        label=_("Password (repeat)"))
    your_name = forms.CharField(required=False)

    def clean_email(self):
        """
        Validate that the username is alphanumeric and is not already
        in use.

        """
        email = self.cleaned_data['email'].strip()
        try:
            User.objects.get(email__iexact=email)
        except User.DoesNotExist:
            return email.lower()
        raise forms.ValidationError(
            _('A user with that email already exists.'))

    def clean(self):
        """
        Verifiy that the values entered into the two password fields match.

        Note that an error here will end up in ``non_field_errors()`` because
        it doesn't apply to a single field.

        """
        data = self.cleaned_data
        if data.get('your_name'):
            # Bot protection. The name field is not visible for human users.
            raise forms.ValidationError(_('Please enter a valid name.'))
        if not 'email' in data:
            return data
        if ('password1' in data and 'password2' in data):

            if data['password1'] != data['password2']:
                raise forms.ValidationError(
                    _("The two password fields didn't match."))

        self.cleaned_data['username'] = generate_username(data['email'])
        return self.cleaned_data

    class Media:
        css = {
            'all': (os.path.join(
                settings.STATIC_URL, 'registration_email/css/auth.css'), )
        }


text:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2013
# This file is distributed under the same license as the PACKAGE package.
# MARCIN SPOCZYŃSKI <marcin@spoczynski.com>, 2013.
#
#, sandlbn
msgid ""
msgstr ""
"Project-Id-Version: 0.6\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-31 23:57+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Marcin Spoczynski <marcin@spoczynski.com>\n"
"Language-Team: PL <marcin@spoczynski.com>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"

#: forms.py:60 forms.py:82 templates/registration/login.html:15
msgid "Email"
msgstr "Email"

#: forms.py:86
msgid "Password"
msgstr "Hasło"

#: forms.py:90
msgid "Password (repeat)"
msgstr "Hasło (powtórz)"

#: forms.py:105
msgid "A user with that email already exists."
msgstr "Użytkownik o tym adresie email już istnieje."

#: forms.py:118
msgid "Please enter a valid name."
msgstr "Proszę wprowadź poprawną nazwę"

#: forms.py:125
msgid "The two password fields didn't match."
msgstr "Podane dwa hasła nie pasują do siebie."

#: templates/registration/activate.html:6
msgid "Activation failure"
msgstr "Błąd aktywacji"

#: templates/registration/activate.html:10
msgid "We are sorry but something went wrong!"
msgstr "Przepraszamy, ale coś poszło nie tak !"

#: templates/registration/activate.html:11
msgid "The activation link you provided is broken or was already used."
msgstr "Link aktywacji który wprowadziłeś jest zepsuty lub był już użyty"

#: templates/registration/activation_complete.html:6
msgid "Activation complete"
msgstr "Aktywacja zakończona"

#: templates/registration/activation_complete.html:10
msgid "You may now login with your username and password."
msgstr "Teraz zaloguj się za pomocą swojej nazwy użytkownika i hasła"

#: templates/registration/activation_complete.html:12
msgid "Login now"
msgstr "Zaloguj się"

#: templates/registration/activation_complete.html:14
msgid "Home"
msgstr "Start"

#: templates/registration/activation_email.txt:5
#, python-format
msgid ""
"\n"
"You have asked to register an account at %(site_name)s.\n"
"If this wasn't you, please ignore this email.\n"
"\n"
"To activate this account, please click the following link within the next\n"
"%(expiration_days)s days:\n"
msgstr ""
"\n"
"Poprosiłeś o rejestrację konta na stronie %(site_name)s.\n"
"Jeśli to nie byłeś Ty, proszę zignoruj tą wiadomość.\n"
"\n"
"Aby aktywować konto. proszę kliknij to łącze w ciągu\n"
"%(expiration_days)s dni:\n"

#: templates/registration/activation_email.txt:15
msgid "Sincerely,"
msgstr "Drogi"

#: templates/registration/activation_email_subject.txt:2
msgid "Account Request"
msgstr "Aktywacja konta"

#: templates/registration/login.html:6 templates/registration/login.html:28
#: templates/registration/password_reset_complete.html:11
msgid "Login"
msgstr "Login"

#: templates/registration/login.html:24
msgid "Forgot your password?"
msgstr "Zapomniałeś swoje hasło"

#: templates/registration/login.html:25
msgid "Register a new account"
msgstr "Zarejestruj nowe konto"

#: templates/registration/logout.html:6
msgid "Logout"
msgstr "Wyloguj"

#: templates/registration/logout.html:10
msgid "You have been logged out."
msgstr "Zostałeś wylogowany"

#: templates/registration/password_change_done.html:6
msgid "Password change successful"
msgstr "Hasło zostało pomyślnie zmienione"

#: templates/registration/password_change_done.html:10
msgid "Your password has been changed."
msgstr "Twoje hasło zostało zmienione."

#: templates/registration/password_change_done.html:11
msgid "Back to dashboard"
msgstr "Powróć do panelu"

#: templates/registration/password_change_form.html:6
msgid "Password change"
msgstr "Hasło zmienione"

#: templates/registration/password_change_form.html:10
msgid "Please enter your old password, then enter your new password twice."
msgstr "Proszę wprowadź swoje stare hasło, a następnie powtórz dwa razy nowe hasło."

#: templates/registration/password_change_form.html:21
msgid "Save"
msgstr "Zapisz"

#: templates/registration/password_change_form.html:22
#: templates/registration/password_reset_form.html:20
msgid "Reset password"
msgstr "Zresetuj hasło"

#: templates/registration/password_reset_complete.html:6
msgid "Password reset complete"
msgstr "Resetowanie hasła zakończone"

#: templates/registration/password_reset_complete.html:10
msgid "Please login with your new password."
msgstr "Proszę zaloguj się swoim nowym hasłem."

#: templates/registration/password_reset_confirm.html:7
msgid "Enter new password"
msgstr "Wprowadź nowe hasło"

#: templates/registration/password_reset_confirm.html:9
msgid "Error resetting password"
msgstr "Błąd resetowania hasła"

#: templates/registration/password_reset_confirm.html:15
msgid "Please enter your new password twice."
msgstr "Wprowadź swoje nowe hasło dwa razy."

#: templates/registration/password_reset_confirm.html:26
msgid "Change my password"
msgstr "Zmień moje hasło"

#: templates/registration/password_reset_confirm.html:29
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used. Please request a new password reset."
msgstr ""
"Link do zresetowania hasła jest błędny, prawdopodobnie już został "
"wykorzystany. Proszę ponów procedurę resetu hasła"

#: templates/registration/password_reset_done.html:6
msgid "Password reset successful"
msgstr "Hasło zresetowane"

#: templates/registration/password_reset_done.html:10
msgid "We have sent you instructions for setting your password."
msgstr "Przesłaliśmy Tobie instrukcję do ustawienia hasła."

#: templates/registration/password_reset_email.html:2
#, python-format
msgid ""
"You're receiving this e-mail because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
"Dostałeś tę wiadomość ponieważ, zarządałeś zresetowania hasła"
"do Twojego konta na stronie %(site_name)s."

#: templates/registration/password_reset_email.html:4
msgid "Please go to the following page and choose a new password:"
msgstr "Proszę przejdź na tą stronę i ustaw nowe hasło:"

#: templates/registration/password_reset_email.html:9
msgid "Thanks for using our site!"
msgstr "Dziękujemy za używanie naszej strony!"

#: templates/registration/password_reset_email.html:11
#, python-format
msgid "The %(site_name)s team"
msgstr "Zespół %(site_name)s team"

#: templates/registration/password_reset_form.html:5
msgid "Password reset"
msgstr "Reset hasła"

#: templates/registration/password_reset_form.html:9
msgid ""
"Enter your e-mail address below, and we will send instructions for setting a "
"new one."
msgstr ""
"Wprowadź Twój adres email poniżej, prześlemy na niego instrukcję"
"do ustawienia nowego hasła"

#: templates/registration/registration_closed.html:6
msgid "Registration closed"
msgstr "Rejestracja zamknięta"

#: templates/registration/registration_closed.html:10
msgid "We are sorry but registration is temporarily closed."
msgstr "Przepraszamy, ale rejestracja jest chwilowo zamknięta"

#: templates/registration/registration_closed.html:11
msgid ""
"Please come back shortly and try again. We apologize for the inconvenience."
msgstr "Prosimy wrócić niebawem i spróbować ponownie. Przepraszamy za utrudnienia."

#: templates/registration/registration_complete.html:6
msgid "Registration complete"
msgstr "Rejestracja zakończona"

#: templates/registration/registration_complete.html:10
msgid "Thank you for your registration!"
msgstr "Dziękujemy za rejestrację!"

#: templates/registration/registration_complete.html:11
msgid "You will receive an email with an activation link shortly."
msgstr "Powinieneś niedługo dostać wiadomość z linkiem aktywacyjnym."

#: templates/registration/registration_form.html:6
msgid "Registration form"
msgstr "Formularz rejestracyjny"

#: templates/registration/registration_form.html:20
msgid "Register"
msgstr "Rejestracja"


text:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-01 13:35+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Alper Cugun <alper@hubbub.eu>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"

#: forms.py:58 forms.py:76 templates/registration/login.html:15
msgid "Email"
msgstr "E-mail"

#: forms.py:80
msgid "Password"
msgstr "Wachtwoord"

#: forms.py:84
msgid "Password (repeat)"
msgstr "Wachtwoord (nog een keer)"

#: forms.py:98
msgid "A user with that email already exists."
msgstr "Een gebruiker met dat e-mailadres bestaat al."

#: forms.py:115
msgid "The two password fields didn't match."
msgstr "De twee wachtwoord-velden komen niet overeen."

#: templates/registration/activate.html:6
msgid "Activation failure"
msgstr "Activatie mislukt"

#: templates/registration/activate.html:10
msgid "We are sorry but something went wrong!"
msgstr "Tot onze spijt is er iets misgegaan."

#: templates/registration/activate.html:11
msgid "The activation link you provided is broken or was already used."
msgstr "De activatie-link is al gebruikt of heeft een ander mankement."

#: templates/registration/activation_complete.html:6
msgid "Activation complete"
msgstr "Activatie voltooid"

#: templates/registration/activation_complete.html:10
msgid "You may now login with your username and password."
msgstr "Je kunt nu inloggen met je gebruikersnaam en wachtwoord."

#: templates/registration/activation_complete.html:12
msgid "Login now"
msgstr "Log nu in"

#: templates/registration/activation_complete.html:14
msgid "Home"
msgstr "Home"

#: templates/registration/activation_email.txt:5
#, python-format
msgid ""
"\n"
"You have asked to register an account at %(site_name)s.\n"
"If this wasn't you, please ignore this email.\n"
"\n"
"To activate this account, please click the following link within the next\n"
"%(expiration_days)s days:\n"
msgstr ""
"\n"
"Je hebt je aangemeld voor een account bij site %(site_name)s.\n"
"Als je dit niet gedaan hebt, kun je deze e-mail negeren."
"\n"
"Klik binnen %(expiration_days)s dagen op de volgende link om\n"
"dit account te activeren:\n"

#: templates/registration/activation_email.txt:15
msgid "Sincerely,"
msgstr "Met vriendelijke groet,"

#: templates/registration/activation_email_subject.txt:2
msgid "Account Request"
msgstr "Accountverzoek"

#: templates/registration/login.html:6 templates/registration/login.html:28
#: templates/registration/password_reset_complete.html:11
msgid "Login"
msgstr "Log in"

#: templates/registration/login.html:24
msgid "Forgot your password?"
msgstr "Wachtwoord vergeten?"

#: templates/registration/login.html:25
msgid "Register a new account"
msgstr "Registreer een nieuw account"

#: templates/registration/logout.html:6
msgid "Logout"
msgstr "Log uit"

#: templates/registration/logout.html:10
msgid "You have been logged out."
msgstr "Je bent uitgelogd."

#: templates/registration/password_change_done.html:6
msgid "Password change successful"
msgstr "Wachtwoord succesvol gewijzigd"

#: templates/registration/password_change_done.html:10
msgid "Your password has been changed."
msgstr "Je wachtwoord is gewijzigd."

#: templates/registration/password_change_done.html:11
msgid "Back to dashboard"
msgstr "Terug naar het dashboard"

#: templates/registration/password_change_form.html:6
msgid "Password change"
msgstr "Wachtwoordwijziging"

#: templates/registration/password_change_form.html:10
msgid "Please enter your old password, then enter your new password twice."
msgstr "Vul alsjeblieft je oude wachtwoord in en daarna twee keer het nieuwe wachtwoord."

#: templates/registration/password_change_form.html:21
msgid "Save"
msgstr "Sla op"

#: templates/registration/password_change_form.html:22
#: templates/registration/password_reset_form.html:20
msgid "Reset password"
msgstr "Reset wachtwoord"

#: templates/registration/password_reset_complete.html:6
msgid "Password reset complete"
msgstr "Wachtwoord gereset"

#: templates/registration/password_reset_complete.html:10
msgid "Please login with your new password."
msgstr "Log in met je nieuwe wachtwoord."

#: templates/registration/password_reset_confirm.html:7
msgid "Enter new password"
msgstr "Voer een nieuw wachtwoord in"

#: templates/registration/password_reset_confirm.html:9
msgid "Error resetting password"
msgstr "Fout bij het resetten van het wachtwoord"

#: templates/registration/password_reset_confirm.html:15
msgid "Please enter your new password twice."
msgstr "Vul je nieuwe wachtwoord twee keer in."

#: templates/registration/password_reset_confirm.html:26
msgid "Change my password"
msgstr "Verander mijn wachtwoord"

#: templates/registration/password_reset_confirm.html:29
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used. Please request a new password reset."
msgstr ""
"De link om het wachtwoord te resetten was niet geldig, mogelijk omdat het"
"al gebruikt is. Vraag een nieuwe reset aan."

#: templates/registration/password_reset_done.html:6
msgid "Password reset successful"
msgstr "Wachtwoord succesvol gereset"

#: templates/registration/password_reset_done.html:10
msgid "We have sent you instructions for setting your password."
msgstr "We hebben instructies gestuurd om je wachtwoord te resetten."

#: templates/registration/password_reset_email.html:2
#, python-format
msgid ""
"You're receiving this e-mail because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
"Je ontvangt deze e-mail omdat je je wachtwoord bij %(site_name)s opnieuw wilde"
"instellen."

#: templates/registration/password_reset_email.html:4
msgid "Please go to the following page and choose a new password:"
msgstr "Ga alsjeblieft naar de volgende pagina en kies een nieuw wachtwoord:"

#: templates/registration/password_reset_email.html:9
msgid "Thanks for using our site!"
msgstr "Bedankt voor de moeite!"

#: templates/registration/password_reset_email.html:11
#, python-format
msgid "The %(site_name)s team"
msgstr "Namens het %(site_name) team"

#: templates/registration/password_reset_form.html:5
msgid "Password reset"
msgstr "Reset wachtwoord"

#: templates/registration/password_reset_form.html:9
msgid ""
"Enter your e-mail address below, and we will send instructions for setting a "
"new one."
msgstr ""
"Vul je e-mail adres in en we sturen je instructies om je wachtwoord"
"opnieuw in te stellen."

#: templates/registration/registration_closed.html:6
msgid "Registration closed"
msgstr "Registratie gesloten"

#: templates/registration/registration_closed.html:10
msgid "We are sorry but registration is temporarily closed."
msgstr "Het spijt ons maar de registratie is op dit moment gesloten."

#: templates/registration/registration_closed.html:11
msgid ""
"Please come back shortly and try again. We apologize for the inconvenience."
msgstr ""
"Probeer het binnenkort nog eens. Onze excuses voor het ongemak."

#: templates/registration/registration_complete.html:6
msgid "Registration complete"
msgstr "Registratie voltooid"

#: templates/registration/registration_complete.html:10
msgid "Thank you for your registration!"
msgstr "Bedankt voor je aanmelding!"

#: templates/registration/registration_complete.html:11
msgid "You will receive an email with an activation link shortly."
msgstr "Je krijgt spoedig een e-mail met daarin de activatielink."

#: templates/registration/registration_form.html:6
msgid "Registration form"
msgstr "Registratieformulier"

#: templates/registration/registration_form.html:20
msgid "Register"
msgstr "Registreer"


text:
"""
URLconf for registration and activation, using django-registration's
one-step backend.

If the default behavior of these views is acceptable to you, simply
use a line like this in your root URLconf to set up the default URLs
for registration::

    (r'^accounts/', include('registration_email.backends.simple.urls')),

This will also automatically set up the views in
``django.contrib.auth`` at sensible default locations.

If you'd like to customize registration behavior, feel free to set up
your own URL patterns for these views instead.

"""
from django.conf import settings
from django.conf.urls import include, url
from django.views.generic.base import TemplateView

from registration.backends.simple.views import RegistrationView
from registration_email.forms import EmailRegistrationForm

urlpatterns = [
    url(r'^register/$',
        RegistrationView.as_view(
            form_class=EmailRegistrationForm,
            get_success_url=getattr(
                settings, 'REGISTRATION_EMAIL_REGISTER_SUCCESS_URL',
                lambda request, user: '/'),
        ),
        name='registration_register'),
    url(r'^register/closed/$',
        TemplateView.as_view(
            template_name='registration/registration_closed.html'),
        name='registration_disallowed'),
    (r'', include('registration_email.auth_urls')),
]


text:
"""Custom urls.py for django-registration."""
from django.conf import settings
from django.conf.urls import include, url
from django.views.generic import TemplateView

from registration.backends.default.views import (
    ActivationView,
    RegistrationView,
)
from registration_email.forms import EmailRegistrationForm

urlpatterns = [
    # django-registration views
    url(r'^activate/complete/$',
        TemplateView.as_view(
            template_name='registration/activation_complete.html'),
        name='registration_activation_complete'),
    url(r'^activate/(?P<activation_key>\w+)/$',
        ActivationView.as_view(
            template_name='registration/activate.html',
            get_success_url=getattr(
                settings, 'REGISTRATION_EMAIL_ACTIVATE_SUCCESS_URL',
                lambda request, user: '/'),
        ),
        name='registration_activate'),
    url(r'^register/$',
        RegistrationView.as_view(
            form_class=EmailRegistrationForm,
            get_success_url=getattr(
                settings, 'REGISTRATION_EMAIL_REGISTER_SUCCESS_URL',
                lambda request, user: '/'),
        ),
        name='registration_register'),
    url(r'^register/complete/$',
        TemplateView.as_view(
            template_name='registration/registration_complete.html'),
        name='registration_complete'),
    url(r'^register/closed/$',
        TemplateView.as_view(
            template_name='registration/registration_closed.html'),
        name='registration_disallowed'),

    # django auth urls
    url(r'', include('registration_email.auth_urls')),
]


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Password reset successful" %}{% endblock %}

{% block masthead %}

{% trans "Password reset successful" %}

{% endblock %}

{% block content %}

{% trans "We have sent you instructions for setting your password." %}

{% endblock %}


text:
{% load i18n %}
{% load url from future %}

{% blocktrans with site.name as site_name %}
You have asked to register an account at {{ site_name }}.
If this wasn't you, please ignore this email.

To activate this account, please click the following link within the next
{{ expiration_days }} days:
{% endblocktrans %}

http://{{ site.domain }}{% url "registration_activate" activation_key=activation_key %}

{% trans "Sincerely," %}
{{ site.name }}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}
{% if validlink %}{% trans "Enter new password" %}{% else %}{% trans "Error resetting password" %}{% endif %}
{% endblock %}

{% block masthead %}
{% if validlink %}

{% trans "Enter new password" %}

{% else %}

{% trans "Error resetting password" %}

{% endif %}
{% endblock %}

{% block content %}
{% if validlink %}

{% trans "Please enter your new password twice." %}

    <form method="post" action=".">
        {% csrf_token %}
        {{ form.non_field_errors }}
        {% for field in form %}

                {{ field.errors }}
                {{ field.label_tag }}
                {{ field }}

        {% endfor %}
        <input type="submit" value="{% trans 'Change my password' %}">
    </form>
{% else %}

{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}

{% endif %}
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Logout" %}{% endblock %}

{% block masthead %}

{% trans "Logout" %}

{% endblock %}

{% block content %}

{% trans "You have been logged out." %}

{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Registration complete" %}{% endblock %}

{% block masthead %}

{% trans "Registration complete" %}

{% endblock %}

{% block content %}

{% trans "Thank you for your registration!" %}

{% trans "You will receive an email with an activation link shortly." %}

{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Registration closed" %}{% endblock %}

{% block masthead %}

{% trans "Registration closed" %}

{% endblock %}

{% block content %}

{% trans "We are sorry but registration is temporarily closed." %}

{% trans "Please come back shortly and try again. We apologize for the inconvenience." %}

{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load i18n %}

{% block title %}{% trans "Password reset" %}{% endblock %}

{% block masthead %}

{% trans "Password reset" %}

{% endblock %}

{% block content %}

{% trans "Enter your e-mail address below, and we will send instructions for setting a new one." %}

<form action="." method="post">
    {% csrf_token %}
    {{ form.non_field_errors }}
    {% for field in form %}

            {{ field.errors }}
            {{ field.label_tag }}
            {{ field }}

    {% endfor %}
    <input type="submit" value="{% trans "Reset password" %}" />
</form>
{% endblock %}


text:
{% load i18n %}{% load url from future %}{% autoescape off %}
{% blocktrans %}You're receiving this e-mail because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}

{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{% endblock %}

{% trans "Thanks for using our site!" %}

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

{% endautoescape %}


text:
{% load i18n %}
{{ site.name }} {% trans "Account Request" %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Registration form" %}{% endblock %}

{% block masthead %}

{% trans "Registration form" %}

{% endblock %}

{% block content %}
<form method="post" action=".">
    {% csrf_token %}
    {{ form.non_field_errors }}
    {% for field in form %}

        {{ field.errors }}
        {{ field.label_tag }}
        {{ field }}

    {% endfor %}
    <input type="submit" value="{% trans "Register" %}">
</form>
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Login" %}{% endblock %}

{% block masthead %}

{% trans "Login" %}

{% endblock %}

{% block content %}
<form method="post" action=".">
    {% csrf_token %}
    {{ form.non_field_errors }}

        {{ form.username.errors }}
        {% trans "Email" %}
        {{ form.username }}

        {{ form.password.errors }}
        {{ form.password.label_tag }}
        {{ form.password }}

        {{ form.remember_me.errors }}
        {{ form.remember_me.label_tag }}
        {{ form.remember_me }}

        {% trans "Forgot your password?" %}
        {% trans "Register a new account" %}?

    <input type="hidden" name="next" value="{{ next }}" />
    <input type="submit" value="{% trans "Login" %}">
</form>
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Password reset complete" %}{% endblock %}

{% block masthead %}

{% trans "Password reset complete" %}

{% endblock %}

{% block content %}

{% trans "Please login with your new password." %}

{% trans "Login" %}
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Password change" %}{% endblock %}

{% block masthead %}

{% trans "Password change" %}

{% endblock %}

{% block content %}

{% trans "Please enter your old password, then enter your new password twice." %}

<form method="post" action=".">
    {% csrf_token %}
    {{ form.non_field_errors }}
    {% for field in form %}

            {{ field.errors }}
            {{ field.label_tag }}
            {{ field }}

    {% endfor %}
    <input type="submit" value="{% trans "Save" %}">

{% trans "Reset password" %}

</form>
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Activation complete" %}{% endblock %}

{% block masthead %}

{% trans "Activation complete" %}

{% endblock %}

{% block content %}

{% trans "You may now login with your username and password." %}

{% if not user.is_authenticated %}
    {% trans "Login now" %}
{% else %}
    {% trans "Home" %}
{% endif %}
{% endblock %}


text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Activation failure" %}{% endblock %}

{% block masthead %}

{% trans "Activation failure" %}

{% endblock %}

{% block content %}

{% trans "We are sorry but something went wrong!" %}

{% trans "The activation link you provided is broken or was already used." %}

{% endblock %}


text:
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}

{% block extracss %}
{{ form.media.css }}
{% endblock %}

{% block main %}
    {% block masthead %}{% endblock %}
    {% block content %}{% endblock %}
{% endblock %}