7da08fce0b971cad8be4d25b470f5e0e30983e8b — Evan J 1 year, 2 months ago 9b9bc66
Fix(security.go): Improving error handling logic.
46 files changed, 6870 insertions(+), 4 deletions(-)

M go.sum
M security.go
A vendor/github.com/Pallinder/go-randomdata/.gitignore
A vendor/github.com/Pallinder/go-randomdata/.travis.yml
A vendor/github.com/Pallinder/go-randomdata/CHANGELOG.md
A vendor/github.com/Pallinder/go-randomdata/LICENSE
A vendor/github.com/Pallinder/go-randomdata/README.md
A vendor/github.com/Pallinder/go-randomdata/fullprofile.go
A vendor/github.com/Pallinder/go-randomdata/jsondata.go
A vendor/github.com/Pallinder/go-randomdata/postalcodes.go
A vendor/github.com/Pallinder/go-randomdata/random_data.go
A vendor/github.com/dgrijalva/jwt-go/.gitignore
A vendor/github.com/dgrijalva/jwt-go/.travis.yml
A vendor/github.com/dgrijalva/jwt-go/LICENSE
A vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
A vendor/github.com/dgrijalva/jwt-go/README.md
A vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md
A vendor/github.com/dgrijalva/jwt-go/claims.go
A vendor/github.com/dgrijalva/jwt-go/doc.go
A vendor/github.com/dgrijalva/jwt-go/ecdsa.go
A vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go
A vendor/github.com/dgrijalva/jwt-go/errors.go
A vendor/github.com/dgrijalva/jwt-go/hmac.go
A vendor/github.com/dgrijalva/jwt-go/map_claims.go
A vendor/github.com/dgrijalva/jwt-go/none.go
A vendor/github.com/dgrijalva/jwt-go/parser.go
A vendor/github.com/dgrijalva/jwt-go/rsa.go
A vendor/github.com/dgrijalva/jwt-go/rsa_pss.go
A vendor/github.com/dgrijalva/jwt-go/rsa_utils.go
A vendor/github.com/dgrijalva/jwt-go/signing_method.go
A vendor/github.com/dgrijalva/jwt-go/token.go
A vendor/golang.org/x/crypto/AUTHORS
A vendor/golang.org/x/crypto/CONTRIBUTORS
A vendor/golang.org/x/crypto/LICENSE
A vendor/golang.org/x/crypto/PATENTS
A vendor/golang.org/x/crypto/bcrypt/base64.go
A vendor/golang.org/x/crypto/bcrypt/bcrypt.go
A vendor/golang.org/x/crypto/blowfish/block.go
A vendor/golang.org/x/crypto/blowfish/cipher.go
A vendor/golang.org/x/crypto/blowfish/const.go
A vendor/gopkg.in/go-playground/assert.v1/.gitignore
A vendor/gopkg.in/go-playground/assert.v1/LICENSE
A vendor/gopkg.in/go-playground/assert.v1/README.md
A vendor/gopkg.in/go-playground/assert.v1/assert.go
A vendor/gopkg.in/go-playground/assert.v1/doc.go
A vendor/modules.txt
M go.sum => go.sum +1 -0
@@ 8,6 8,7 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=

M security.go => security.go +14 -4
@@ 101,18 101,28 @@ func (sec Security) TokenCreate(val TokenMap) (string, error) { // nolint
func (sec Security) TokenFrom(tokenString string) (_ret TokenMap, recoverErr error) {
	defer func() {
		if recover() != nil {
			// That's right, jwt will pnic on bad input. Don't do this.
			// That's right, jwt will panic on bad input. Don't do this.
			recoverErr = fmt.Errorf("hash has no value")

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		return []byte(sec.secret), nil
	if val, ok := token.Claims.(TokenMap); ok && token.Valid {
		return val, nil
	if err != nil {
		return TokenMap{}, err

	val, ok := token.Claims.(TokenMap)
	if !ok {
		return TokenMap{}, fmt.Errorf("corrupted token")
	return TokenMap{}, err
	if !token.Valid {
		return TokenMap{}, fmt.Errorf("token is invalid")

	return val, nil

A vendor/github.com/Pallinder/go-randomdata/.gitignore => vendor/github.com/Pallinder/go-randomdata/.gitignore +30 -0
@@ 0,0 1,30 @@
# git ignore for idea (IntelliJ, Gogland,...)

# Compiled Object files, Static and Dynamic libs (Shared Objects)

# Folders

# Architecture specific extensions/prefixes




# Testing specific
\ No newline at end of file

A vendor/github.com/Pallinder/go-randomdata/.travis.yml => vendor/github.com/Pallinder/go-randomdata/.travis.yml +1 -0
@@ 0,0 1,1 @@
language: go
\ No newline at end of file

A vendor/github.com/Pallinder/go-randomdata/CHANGELOG.md => vendor/github.com/Pallinder/go-randomdata/CHANGELOG.md +35 -0
@@ 0,0 1,35 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2019-06-02
### Added
- Spaces in postal code for GB.
- Add functionality to randomly generate alphanumeric text.

### Fixed
- Fix race condition that was introduced by relying on privateRand.
- Fix title with random gender not actually generating a title

## [1.1.0] - 2018-10-31

### Added
- Generate random locale strings
- Country localised street names
- Country localised provinces

### Fixed
- Generating dates will respect varying number of days in a month

## [1.0.0] - 2018-10-30

### Added
- This CHANGELOG file to hopefully serve as an evolving example of a
  standardized open source project CHANGELOG.
- Enforcing Semver compatability in releases

### Changed
- Update README.md to include information about release strategy
- Update README.md to link to CHANGELOG.md

A vendor/github.com/Pallinder/go-randomdata/LICENSE => vendor/github.com/Pallinder/go-randomdata/LICENSE +20 -0
@@ 0,0 1,20 @@
The MIT License (MIT)

Copyright (c) 2013 David Pallinder

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.


A vendor/github.com/Pallinder/go-randomdata/README.md => vendor/github.com/Pallinder/go-randomdata/README.md +200 -0
@@ 0,0 1,200 @@
# go-randomdata

[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/Pallinder/go-randomdata/issues)
[![Build Status](https://travis-ci.org/Pallinder/go-randomdata.png)](https://travis-ci.org/Pallinder/go-randomdata)
[![Go Report Card](https://goreportcard.com/badge/github.com/Pallinder/go-randomdata)](https://goreportcard.com/report/github.com/Pallinder/go-randomdata)

randomdata is a tiny help suite for generating random data such as

* first names (male or female)
* last names
* full names (male or female)
* country names (full name or iso 3166.1 alpha-2 or alpha-3)
* locales / language tags (bcp-47)
* random email address
* city names
* American state names (two chars or full)
* random numbers (in an interval)
* random paragraphs
* random bool values
* postal- or zip-codes formatted for a range of different countries.
* american sounding addresses / street names
* silly names - suitable for names of things
* random days
* random months
* random full date
* random full profile
* random date inside range
* random phone number

## Installation

```go get github.com/Pallinder/go-randomdata```

## Usage


package main

import (

func main() {
    // Print a random silly name

    // Print a male title

    // Print a female title

    // Print a title with random gender

    // Print a male first name

    // Print a female first name

    // Print a last name

    // Print a male name

    // Print a female name

    // Print a name with random gender

    // Print an email

    // Print a country with full text representation

    // Print a country using ISO 3166-1 alpha-2

    // Print a country using ISO 3166-1 alpha-3
    // Print BCP 47 language tag

    // Print a currency using ISO 4217

    // Print the name of a random city

    // Print the name of a random american state

    // Print the name of a random american state using two chars

    // Print an american sounding street name

    // Print an american sounding address

    // Print a random number >= 10 and < 20
    fmt.Println(randomdata.Number(10, 20))

    // Print a number >= 0 and < 20

    // Print a random float >= 0 and < 20 with decimal point 3
    fmt.Println(randomdata.Decimal(0, 20, 3))

    // Print a random float >= 10 and < 20
    fmt.Println(randomdata.Decimal(10, 20))

    // Print a random float >= 0 and < 20

    // Print a bool

    // Print a paragraph

    // Print a postal code

    // Print a set of 2 random numbers as a string
    fmt.Println(randomdata.StringNumber(2, "-"))

    // Print a set of 2 random 3-Digits numbers as a string
    fmt.Println(randomdata.StringNumberExt(2, "-", 3))

    // Print a random string sampled from a list of strings
    fmt.Println(randomdata.StringSample("my string 1", "my string 2", "my string 3"))

    // Print a valid random IPv4 address

    // Print a valid random IPv6 address

    // Print a browser's user agent string

    // Print a day

    // Print a month

    // Print full date like Monday 22 Aug 2016

    // Print full date <= Monday 22 Aug 2016

    // Print full date >= Monday 01 Aug 2016 and <= Monday 22 Aug 2016
    fmt.Println(randomdata.FullDateInRange("2016-08-01", "2016-08-22"))

    // Print phone number according to e.164

    // Get a complete and randomised profile of data generally used for users
    // There are many fields in the profile to use check the Profile struct definition in fullprofile.go
    profile := randomdata.GenerateProfile(randomdata.Male | randomdata.Female | randomdata.RandomGender)
    fmt.Printf("The new profile's username is: %s and password (md5): %s\n", profile.Login.Username, profile.Login.Md5)

    // Get a random country-localised street name for Great Britain
    // Get a random country-localised street name for USA

    // Get a random country-localised province for Great Britain
    // Get a random country-localised province for USA


## Versioning / Release Strategy
Go-Randomdata follows [Semver](https://www.semver.org)

You can find current releases tagged under the [releases section](https://github.com/Pallinder/go-randomdata/releases).

The [CHANGELOG.md](CHANGELOG.md) file contains the changelog of the project.

## Contributors

* [jteeuwen](https://github.com/jteeuwen)
* [n1try](https://github.com/n1try)

All the other contributors are listed [here](https://github.com/Pallinder/go-randomdata/graphs/contributors).

A vendor/github.com/Pallinder/go-randomdata/fullprofile.go => vendor/github.com/Pallinder/go-randomdata/fullprofile.go +139 -0
@@ 0,0 1,139 @@
package randomdata

import (

var letterRunes = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
var portraitDirs = []string{"men", "women"}

type Profile struct {
	Gender string `json:"gender"`
	Name   struct {
		First string `json:"first"`
		Last  string `json:"last"`
		Title string `json:"title"`
	} `json:"name"`
	Location struct {
		Street   string `json:"street"`
		City     string `json:"city"`
		State    string `json:"state"`
		Postcode int    `json:"postcode"`
	} `json:"location"`

	Email string `json:"email"`
	Login struct {
		Username string `json:"username"`
		Password string `json:"password"`
		Salt     string `json:"salt"`
		Md5      string `json:"md5"`
		Sha1     string `json:"sha1"`
		Sha256   string `json:"sha256"`
	} `json:"login"`

	Dob        string `json:"dob"`
	Registered string `json:"registered"`
	Phone      string `json:"phone"`
	Cell       string `json:"cell"`

	ID struct {
		Name  string      `json:"name"`
		Value interface{} `json:"value"`
	} `json:"id"`

	Picture struct {
		Large     string `json:"large"`
		Medium    string `json:"medium"`
		Thumbnail string `json:"thumbnail"`
	} `json:"picture"`
	Nat string `json:"nat"`

func RandStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[privateRand.Intn(len(letterRunes))]
	return string(b)

func getMD5Hash(text string) string {
	hasher := md5.New()
	return hex.EncodeToString(hasher.Sum(nil))

func getSha1(text string) string {
	hasher := sha1.New()
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha

func getSha256(text string) string {
	hasher := sha256.New()
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha

func GenerateProfile(gender int) *Profile {
	profile := &Profile{}
	if gender == Male {
		profile.Gender = "male"
	} else if gender == Female {
		profile.Gender = "female"
	} else {
		gender = privateRand.Intn(2)
		if gender == Male {
			profile.Gender = "male"
		} else {
			profile.Gender = "female"
	profile.Name.Title = Title(gender)
	profile.Name.First = FirstName(gender)
	profile.Name.Last = LastName()
	profile.ID.Name = "SSN"
	profile.ID.Value = fmt.Sprintf("%d-%d-%d",
		Number(101, 999),
		Number(01, 99),
		Number(100, 9999),

	profile.Email = strings.ToLower(profile.Name.First) + "." + strings.ToLower(profile.Name.Last) + "@example.com"
	profile.Cell = PhoneNumber()
	profile.Phone = PhoneNumber()
	profile.Dob = FullDate()
	profile.Registered = FullDate()
	profile.Nat = "US"

	profile.Location.City = City()
	i, _ := strconv.Atoi(PostalCode("US"))
	profile.Location.Postcode = i
	profile.Location.State = State(2)
	profile.Location.Street = StringNumber(1, "") + " " + Street()

	profile.Login.Username = SillyName()
	pass := SillyName()
	salt := RandStringRunes(16)
	profile.Login.Password = pass
	profile.Login.Salt = salt
	profile.Login.Md5 = getMD5Hash(pass + salt)
	profile.Login.Sha1 = getSha1(pass + salt)
	profile.Login.Sha256 = getSha256(pass + salt)

	pic := privateRand.Intn(35)
	profile.Picture.Large = fmt.Sprintf("https://randomuser.me/api/portraits/%s/%d.jpg", portraitDirs[gender], pic)
	profile.Picture.Medium = fmt.Sprintf("https://randomuser.me/api/portraits/med/%s/%d.jpg", portraitDirs[gender], pic)
	profile.Picture.Thumbnail = fmt.Sprintf("https://randomuser.me/api/portraits/thumb/%s/%d.jpg", portraitDirs[gender], pic)

	return profile

A vendor/github.com/Pallinder/go-randomdata/jsondata.go => vendor/github.com/Pallinder/go-randomdata/jsondata.go +2896 -0
@@ 0,0 1,2896 @@
package randomdata

var data = []byte(`{
    "adjectives": [
    "nouns": [
    "firstNamesMale": [
    "firstNamesFemale": [
    "lastNames": [
    "domains": [
    "people": [
    "streetTypes": [
    "paragraphs": [
        "The Nellie, a cruising yawl, swung to her anchor without a flutter of the sails, and was at rest.",
        "The sun set; the dusk fell on the stream, and lights began to appear along the shore. The Chapman light–house, a three–legged thing erect on a mud–flat, shone strongly.",
        "He spoke of the happiness that was now certainly theirs, of the folly of not breaking sooner out of that magnificent prison of latter-day life, of the old romantic days that had passed from the world for ever.",
        "One dog rolled before him, well-nigh slashed in half; but a second had him by the thigh, a third gripped his collar be- hind, and a fourth had the blade of the sword between its teeth, tasting its own blood.",
        "She stared at him in astonishment, and as she read something of the significant hieroglyphic of his battered face, her lips whitened.",
        "He completely abandoned the child of his marriage with Adelaida Ivanovna, not from malice, nor because of his matrimoni- al grievances, but simply because he forgot him.",
        "It was at this time that the meeting, or, rather gathering of the mem- bers of this inharmonious family took place in the cell of the elder who had such an extraordinary influence on Alyosha.",
        "The secular cooling that must someday overtake our planet has already gone far indeed with our neighbour.",
        "Near it in the field, I remember, were three faint points of light, three telescopic stars infinitely remote, and all around it was the unfathomable darkness of empty space.",
		"It is no doubt an optimistic enterprise. But it is good for awhile to be free from the carping note that must needs be audible when we discuss our present imperfections, to release ourselves from practical difficulties and the tangle of ways and means. It is good to stop by the track for a space, put aside the knapsack, wipe the brows, and talk a little of the upper slopes of the mountain we think we are climbing, would but the trees let us see it",
		"But what sort of language would we have the world speak, if we were told the miracle of Babel was presently to be reversed?",
		"I protest, even warmly, that neither he nor his sorrows were in my intention.",
		"Have I come to Utopia to hear this sort of thing?",
		"Then followed a battle of looks between them, but the captain soon knuckled under, put up his weapon, and resumed his seat, grumbling like a beaten dog.",
		"And with that he went off to see my father, taking me with him by the arm.",
		"It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.",
		"I am all in a sea of wonders. I doubt; I fear; I think strange things, which I dare not confess to my own soul. God keep me, if only for the sake of those dear to me!"
    "countries": [
        "American Samoa",
        "Antigua and Barbuda",
        "Bahamas, The",
        "Bosnia and Herzegovina",
        "Brunei Darussalam",
        "Burkina Faso",
        "Cape Verde",
        "Cayman Islands",
        "Central African Republic",
        "Channel Islands",
        "Congo, Dem. Rep.",
        "Congo, Rep.",
        "Costa Rica",
        "Côte dIvoire",
        "Czech Republic",
        "Dominican Republic",
        "Egypt, Arab Rep.",
        "El Salvador",
        "Equatorial Guinea",
        "Faeroe Islands",
        "French Polynesia",
        "Gambia, The",
        "Hong Kong, China",
        "Iran, Islamic Rep.",
        "Isle of Man",
        "Korea, Dem. Rep.",
        "Korea, Rep.",
        "Kyrgyz Republic",
        "Lao PDR",
        "Macao, China",
        "Macedonia, FYR",
        "Marshall Islands",
        "Micronesia, Fed. Sts.",
        "Netherlands Antilles",
        "New Caledonia",
        "New Zealand",
        "Northern Mariana Islands",
        "Papua New Guinea",
        "Puerto Rico",
        "Russian Federation",
        "San Marino",
        "São Tomé and Principe",
        "Saudi Arabia",
        "Sierra Leone",
        "Slovak Republic",
        "Solomon Islands",
        "South Africa",
        "Sri Lanka",
        "St. Kitts and Nevis",
        "St. Lucia",
        "St. Vincent and the Grenadines",
        "Syrian Arab Republic",
        "Trinidad and Tobago",
        "United Arab Emirates",
        "United Kingdom",
        "United States",
        "Venezuela, RB",
        "Virgin Islands (U.S.)",
        "West Bank and Gaza",
        "Yemen, Rep.",
    "countriesThreeChars": [
    "countriesTwoChars": [
    "currencies": [
    "cities": [
        "Derby Center",
        "New Deal",
        "Cienega Springs",
        "Ransom Canyon",
        "San Martin",
        "Buffalo City",
        "Skidaway Island",
    "states": [
        "New Hampshire",
        "New Jersey",
        "New Mexico",
        "New York",
        "North Carolina",
        "North Dakota",
        "Rhode Island",
        "South Carolina",
        "South Dakota",
        "West Virginia",
    "statesSmall": [
    "days" : [
    "months": [
    "femaleTitles": [
    "maleTitles": [
    "timezones": [
    "locales": [
    "countryCallingCodes" : [
        "886",  "93",  "355",  "213",  "1 684",  "376",  "244",  "1 264",  "672",  "1 268",  "54",  "374",  "297",  "61",  "43",  "994",  "1 242",  "973",  "880",  "1 246",  "375",  "32",  "501",  "229",  "1 441",  "975",  "591",  "599",  "387",  "267",  "47",  "55",  "246",  "1 284",  "673",  "359",  "226",  "257",  "238",  "855",  "237",  "1",  "1 345",  "236",  "235",  "56",  "86",  "852",  "853",  "61",  "61",  "57",  "269",  "242",  "682",  "506",  "385",  "53",  "599",  "357",  "420",  "225",  "850",  "243",  "45",  "253",  "1 767",  "1 809,1 829,1 849",  "593",  "20",  "503",  "240",  "291",  "372",  "251",  "500",  "298",  "679",  "358",  "33",  "594",  "689",  "262",  "241",  "220",  "995",  "49",  "233",  "350",  "30",  "299",  "1 473",  "590",  "1 671",  "502",  "44",  "224",  "245",  "592",  "509",  "672",  "39 06",  "504",  "36",  "354",  "91",  "62",  "98",  "964",  "353",  "44",  "972",  "39",  "1 876",  "81",  "44",  "962",  "7",  "254",  "686",  "965",  "996",  "856",  "371",  "961",  "266",  "231",  "218",  "423",  "370",  "352",  "261",  "265",  "60",  "960",  "223",  "356",  "692",  "596",  "222",  "230",  "262",  "52",  "691",  "377",  "976",  "382",  "1 664",  "212",  "258",  "95",  "264",  "674",  "977",  "31",  "687",  "64",  "505",  "227",  "234",  "683",  "672",  "1 670",  "47",  "968",  "92",  "680",  "507",  "675",  "595",  "51",  "63",  "870",  "48",  "351",  "1",  "974",  "82",  "373",  "40",  "7",  "250",  "262",  "590",  "290",  "1 869",  "1 758",  "590",  "508",  "1 784",  "685",  "378",  "239",  "966",  "221",  "381",  "248",  "232",  "65",  "1 721",  "421",  "386",  "677",  "252",  "27",  "500",  "211",  "34",  "94",  "970",  "249",  "597",  "47",  "268",  "46",  "41",  "963",  "992",  "66",  "389",  "670",  "228",  "690",  "676",  "1 868",  "216",  "90",  "993",  "1 649",  "688",  "256",  "380",  "971",  "44",  "255",  " ",  "1 340",  "1",  "598",  "998",  "678",  "58",  "84",  "681",  "212",  "967",  "260",  "263",  "358"
    "userAgents": [
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0",
        "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0",
        "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)",
        "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
        "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55",
        "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
        "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4",
        "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
        "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/60.0.3112.78 Chrome/60.0.3112.78 Safari/537.36",
        "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0",
        "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172",
        "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62",
        "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36",
        "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)",
        "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30",
        "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1",
        "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36",
        "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
    "provincesGB": [
		"City of London",
		"East Lothian",
		"East Riding of Yorkshire",
		"East Sussex",
		"Greater London",
		"Greater Manchester",
		"Isle of Wight",
		"North Yorkshire",
		"South Yorkshire",
		"Tyne and Wear",
		"West Lothian",
		"West Midlands",
		"West Sussex",
		"West Yorkshire",
    "streetNameGB": [
    "streetTypesGB": [

A vendor/github.com/Pallinder/go-randomdata/postalcodes.go => vendor/github.com/Pallinder/go-randomdata/postalcodes.go +246 -0
@@ 0,0 1,246 @@
package randomdata

import (

// Supported formats obtained from:
// * http://www.geopostcodes.com/GeoPC_Postal_codes_formats

// PostalCode yields a random postal/zip code for the given 2-letter country code.
// These codes are not guaranteed to refer to actually locations.
// They merely follow the correct format as far as letters and digits goes.
// Where possible, the function enforces valid ranges of letters and digits.
func PostalCode(countrycode string) string {
	switch strings.ToUpper(countrycode) {
	case "LS", "MG", "IS", "OM", "PG":
		return Digits(3)

	case "AM", "GE", "NZ", "NE", "NO", "PY", "ZA", "MZ", "SJ", "LI", "AL",
		"BD", "CV", "GL":
		return Digits(4)

	case "DZ", "BA", "KH", "DO", "EG", "EE", "GP", "GT", "ID", "IL", "JO",
		"KW", "MQ", "MX", "LK", "SD", "TR", "UA", "US", "CR", "IQ", "KV", "MY",
		"MN", "ME", "PK", "SM", "MA", "UY", "EH", "ZM":
		return Digits(5)

	case "BY", "CN", "IN", "KZ", "KG", "NG", "RO", "RU", "SG", "TJ", "TM", "UZ", "VN":
		return Digits(6)

	case "CL":
		return Digits(7)

	case "IR":
		return Digits(10)

	case "FO":
		return "FO " + Digits(3)

	case "AF":
		return BoundedDigits(2, 10, 43) + BoundedDigits(2, 1, 99)

	case "AU", "AT", "BE", "BG", "CY", "DK", "ET", "GW", "HU", "LR", "MK", "PH",
		"CH", "TN", "VE":
		return BoundedDigits(4, 1000, 9999)

	case "SV":
		return "CP " + BoundedDigits(4, 1000, 9999)

	case "HT":
		return "HT" + Digits(4)

	case "LB":
		return Digits(4) + " " + Digits(4)

	case "LU":
		return BoundedDigits(4, 6600, 6999)

	case "MD":
		return "MD-" + BoundedDigits(4, 1000, 9999)

	case "HR":
		return "HR-" + Digits(5)

	case "CU":
		return "CP " + BoundedDigits(5, 10000, 99999)

	case "FI":
		// Last digit is usually 0 but can, in some cases, be 1 or 5.
		switch privateRand.Intn(2) {
		case 0:
			return Digits(4) + "0"
		case 1:
			return Digits(4) + "1"

		return Digits(4) + "5"

	case "FR", "GF", "PF", "YT", "MC", "RE", "BL", "MF", "PM", "RS", "TH":
		return BoundedDigits(5, 10000, 99999)

	case "DE":
		return BoundedDigits(5, 1000, 99999)

	case "GR":
		return BoundedDigits(3, 100, 999) + " " + Digits(2)

	case "HN":
		return "CM" + Digits(4)

	case "IT", "VA":
		return BoundedDigits(5, 10, 99999)

	case "KE":
		return BoundedDigits(5, 100, 99999)

	case "LA":
		return BoundedDigits(5, 1000, 99999)

	case "MH":
		return BoundedDigits(5, 96960, 96970)

	case "FM":
		return "FM" + BoundedDigits(5, 96941, 96944)

	case "MM":
		return BoundedDigits(2, 1, 14) + Digits(3)

	case "NP":
		return BoundedDigits(5, 10700, 56311)

	case "NC":
		return "98" + Digits(3)

	case "PW":
		return "PW96940"

	case "PR":
		return "PR " + Digits(5)

	case "SA":
		return BoundedDigits(5, 10000, 99999) + "-" + BoundedDigits(4, 1000, 9999)

	case "ES":
		return BoundedDigits(2, 1, 52) + BoundedDigits(3, 100, 999)

	case "WF":
		return "986" + Digits(2)

	case "SZ":
		return Letters(1) + Digits(3)

	case "BM":
		return Letters(2) + Digits(2)

	case "AD":
		return Letters(2) + Digits(3)

	case "BN", "AZ", "VG", "PE":
		return Letters(2) + Digits(4)

	case "BB":
		return Letters(2) + Digits(5)

	case "EC":
		return Letters(2) + Digits(6)

	case "MT":
		return Letters(3) + Digits(4)

	case "JM":
		return "JM" + Letters(3) + Digits(2)

	case "AR":
		return Letters(1) + Digits(4) + Letters(3)

	case "CA":
		return Letters(1) + Digits(1) + Letters(1) + Digits(1) + Letters(1) + Digits(1)

	case "FK", "TC":
		return Letters(4) + Digits(1) + Letters(2)

	case "GG", "IM", "JE":
		return Letters(2) + Digits(2) + Letters(2)

	case "GB":
		return Letters(2) + Digits(1) + " " + Digits(1) + Letters(2)

	case "KY":
		return Letters(2) + Digits(1) + "-" + Digits(4)

	case "JP":
		return Digits(3) + "-" + Digits(4)

	case "LV", "SI":
		return Letters(2) + "-" + Digits(4)

	case "LT":
		return Letters(2) + "-" + Digits(5)

	case "SE", "TW":
		return Digits(5)

	case "MV":
		return Digits(2) + "-" + Digits(2)

	case "PL":
		return Digits(2) + "-" + Digits(3)

	case "NI":
		return Digits(3) + "-" + Digits(3) + "-" + Digits(1)

	case "KR":
		return Digits(3) + "-" + Digits(3)

	case "PT":
		return Digits(4) + "-" + Digits(3)

	case "NL":
		return Digits(4) + Letters(2)

	case "BR":
		return Digits(5) + "-" + Digits(3)

	return ""

// Letters generates a string of N random leters (A-Z).
func Letters(letters int) string {
	list := make([]byte, letters)

	for i := range list {
		list[i] = byte(privateRand.Intn('Z'-'A') + 'A')

	return string(list)

// Digits generates a string of N random digits, padded with zeros if necessary.
func Digits(digits int) string {
	max := int(math.Pow10(digits)) - 1
	num := privateRand.Intn(max)
	format := fmt.Sprintf("%%0%dd", digits)
	return fmt.Sprintf(format, num)

// BoundedDigits generates a string of N random digits, padded with zeros if necessary.
// The output is restricted to the given range.
func BoundedDigits(digits, low, high int) string {
	if low > high {
		low, high = high, low

	max := int(math.Pow10(digits)) - 1
	if high > max {
		high = max

	num := privateRand.Intn(high-low+1) + low
	format := fmt.Sprintf("%%0%dd", digits)
	return fmt.Sprintf(format, num)

A vendor/github.com/Pallinder/go-randomdata/random_data.go => vendor/github.com/Pallinder/go-randomdata/random_data.go +443 -0
@@ 0,0 1,443 @@
// Package randomdata implements a bunch of simple ways to generate (pseudo) random data
package randomdata

import (

const (
	Male         int = 0
	Female       int = 1
	RandomGender int = 2

const (
	Small int = 0
	Large int = 1

const (
	FullCountry      = 0
	TwoCharCountry   = 1
	ThreeCharCountry = 2

const (
	DateInputLayout  = "2006-01-02"
	DateOutputLayout = "Monday 2 Jan 2006"

const ALPHANUMERIC = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

type jsonContent struct {
	Adjectives          []string `json:"adjectives"`
	Nouns               []string `json:"nouns"`
	FirstNamesFemale    []string `json:"firstNamesFemale"`
	FirstNamesMale      []string `json:"firstNamesMale"`
	LastNames           []string `json:"lastNames"`
	Domains             []string `json:"domains"`
	People              []string `json:"people"`
	StreetTypes         []string `json:"streetTypes"` // Taken from https://github.com/tomharris/random_data/blob/master/lib/random_data/locations.rb
	Paragraphs          []string `json:"paragraphs"`  // Taken from feedbooks.com and www.gutenberg.org
	Countries           []string `json:"countries"`   // Fetched from the world bank at http://siteresources.worldbank.org/DATASTATISTICS/Resources/CLASS.XLS
	CountriesThreeChars []string `json:"countriesThreeChars"`
	CountriesTwoChars   []string `json:"countriesTwoChars"`
	Currencies          []string `json:"currencies"` //https://github.com/OpenBookPrices/country-data
	Cities              []string `json:"cities"`
	States              []string `json:"states"`
	StatesSmall         []string `json:"statesSmall"`
	Days                []string `json:"days"`
	Months              []string `json:"months"`
	FemaleTitles        []string `json:"femaleTitles"`
	MaleTitles          []string `json:"maleTitles"`
	Timezones           []string `json:"timezones"`           // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
	Locales             []string `json:"locales"`             // https://tools.ietf.org/html/bcp47
	UserAgents          []string `json:"userAgents"`          // http://techpatterns.com/downloads/firefox/useragentswitcher.xml
	CountryCallingCodes []string `json:"countryCallingCodes"` // from https://github.com/datasets/country-codes/blob/master/data/country-codes.csv
	ProvincesGB         []string `json:"provincesGB"`
	StreetNameGB        []string `json:"streetNameGB"`
	StreetTypesGB       []string `json:"streetTypesGB"`

type pRand struct {
	pr *rand.Rand
	mu *sync.Mutex

func (r *pRand) Intn(n int) int {
	defer r.mu.Unlock()
	return r.pr.Intn(n)

func (r *pRand) Float64() float64 {
	defer r.mu.Unlock()
	return r.pr.Float64()

var jsonData = jsonContent{}
var privateRand *pRand

func init() {
	privateRand = &pRand{rand.New(rand.NewSource(time.Now().UnixNano())), &sync.Mutex{}}
	jsonData = jsonContent{}

	err := json.Unmarshal(data, &jsonData)

	if err != nil {

func CustomRand(randToUse *rand.Rand) {
	privateRand.pr = randToUse

// Returns a random part of a slice
func randomFrom(source []string) string {
	return source[privateRand.Intn(len(source))]

// Title returns a random title, gender decides the gender of the name
func Title(gender int) string {
	switch gender {
	case Male:
		return randomFrom(jsonData.MaleTitles)
	case Female:
		return randomFrom(jsonData.FemaleTitles)
		return Title(privateRand.Intn(2))

// FirstName returns a random first name, gender decides the gender of the name
func FirstName(gender int) string {
	var name = ""
	switch gender {
	case Male:
		name = randomFrom(jsonData.FirstNamesMale)
	case Female:
		name = randomFrom(jsonData.FirstNamesFemale)
		name = FirstName(rand.Intn(2))
	return name

// LastName returns a random last name
func LastName() string {
	return randomFrom(jsonData.LastNames)

// FullName returns a combination of FirstName LastName randomized, gender decides the gender of the name
func FullName(gender int) string {
	return FirstName(gender) + " " + LastName()

// Email returns a random email
func Email() string {
	return strings.ToLower(FirstName(RandomGender)+LastName()) + StringNumberExt(1, "", 3) + "@" + randomFrom(jsonData.Domains)

// Country returns a random country, countryStyle decides what kind of format the returned country will have
func Country(countryStyle int64) string {
	country := ""
	switch countryStyle {


	case FullCountry:
		country = randomFrom(jsonData.Countries)

	case TwoCharCountry:
		country = randomFrom(jsonData.CountriesTwoChars)

	case ThreeCharCountry:
		country = randomFrom(jsonData.CountriesThreeChars)
	return country

// Currency returns a random currency under ISO 4217 format
func Currency() string {
	return randomFrom(jsonData.Currencies)

// City returns a random city
func City() string {
	return randomFrom(jsonData.Cities)

// ProvinceForCountry returns a randomly selected province (state, county,subdivision ) name for a supplied country.
// If the country is not supported it will return an empty string.
func ProvinceForCountry(countrycode string) string {
	switch countrycode {
	case "US":
		return randomFrom(jsonData.States)
	case "GB":
		return randomFrom(jsonData.ProvincesGB)
	return ""

// State returns a random american state
func State(typeOfState int) string {
	if typeOfState == Small {
		return randomFrom(jsonData.StatesSmall)
	return randomFrom(jsonData.States)

// Street returns a random fake street name
func Street() string {
	return fmt.Sprintf("%s %s", randomFrom(jsonData.People), randomFrom(jsonData.StreetTypes))

// StreetForCountry returns a random fake street name typical to the supplied country.
// If the country is not supported it will return an empty string.
func StreetForCountry(countrycode string) string {
	switch countrycode {
	case "US":
		return Street()
	case "GB":
		return fmt.Sprintf("%s %s", randomFrom(jsonData.StreetNameGB), randomFrom(jsonData.StreetTypesGB))
	return ""

// Address returns an american style address
func Address() string {
	return fmt.Sprintf("%d %s,\n%s, %s, %s", Number(100), Street(), City(), State(Small), PostalCode("US"))

// Paragraph returns a random paragraph
func Paragraph() string {
	return randomFrom(jsonData.Paragraphs)

// Number returns a random number, if only one integer (n1) is supplied it returns a number in [0,n1)
// if a second argument is supplied it returns a number in [n1,n2)
func Number(numberRange ...int) int {
	nr := 0
	if len(numberRange) > 1 {
		nr = 1
		nr = privateRand.Intn(numberRange[1]-numberRange[0]) + numberRange[0]
	} else {
		nr = privateRand.Intn(numberRange[0])
	return nr

func Decimal(numberRange ...int) float64 {
	nr := 0.0
	if len(numberRange) > 1 {
		nr = 1.0
		nr = privateRand.Float64()*(float64(numberRange[1])-float64(numberRange[0])) + float64(numberRange[0])
	} else {
		nr = privateRand.Float64() * float64(numberRange[0])

	if len(numberRange) > 2 {
		sf := strconv.FormatFloat(nr, 'f', numberRange[2], 64)
		nr, _ = strconv.ParseFloat(sf, 64)
	return nr

func StringNumberExt(numberPairs int, separator string, numberOfDigits int) string {
	numberString := ""

	for i := 0; i < numberPairs; i++ {
		for d := 0; d < numberOfDigits; d++ {
			numberString += fmt.Sprintf("%d", Number(0, 9))

		if i+1 != numberPairs {
			numberString += separator

	return numberString

// StringNumber returns a random number as a string
func StringNumber(numberPairs int, separator string) string {
	return StringNumberExt(numberPairs, separator, 2)

// StringSample returns a random string from a list of strings
func StringSample(stringList ...string) string {
	str := ""
	if len(stringList) > 0 {
		str = stringList[Number(0, len(stringList))]
	return str

// Alphanumeric returns a random alphanumeric string consits of [0-9a-zA-Z].
func Alphanumeric(length int) string {
	list := make([]byte, length)

	for i := range list {
		list[i] = ALPHANUMERIC[privateRand.Intn(len(ALPHANUMERIC))]

	return string(list)

func Boolean() bool {
	nr := privateRand.Intn(2)
	return nr != 0

// Noun returns a random noun
func Noun() string {
	return randomFrom(jsonData.Nouns)

// Adjective returns a random adjective
func Adjective() string {
	return randomFrom(jsonData.Adjectives)

func uppercaseFirstLetter(word string) string {
	a := []rune(word)
	a[0] = unicode.ToUpper(a[0])
	return string(a)

func lowercaseFirstLetter(word string) string {
	a := []rune(word)
	a[0] = unicode.ToLower(a[0])
	return string(a)

// SillyName returns a silly name, useful for randomizing naming of things
func SillyName() string {
	return uppercaseFirstLetter(Noun()) + Adjective()

// IpV4Address returns a valid IPv4 address as string
func IpV4Address() string {
	blocks := []string{}
	for i := 0; i < 4; i++ {
		number := privateRand.Intn(255)
		blocks = append(blocks, strconv.Itoa(number))

	return strings.Join(blocks, ".")

// IpV6Address returns a valid IPv6 address as net.IP
func IpV6Address() string {
	var ip net.IP
	for i := 0; i < net.IPv6len; i++ {
		number := uint8(privateRand.Intn(255))
		ip = append(ip, number)
	return ip.String()

// MacAddress returns an mac address string
func MacAddress() string {
	blocks := []string{}
	for i := 0; i < 6; i++ {
		number := fmt.Sprintf("%02x", privateRand.Intn(255))
		blocks = append(blocks, number)

	return strings.Join(blocks, ":")

// Day returns random day
func Day() string {
	return randomFrom(jsonData.Days)

// Month returns random month
func Month() string {
	return randomFrom(jsonData.Months)

// FullDate returns full date
func FullDate() string {
	timestamp := time.Now()
	year := timestamp.Year()
	month := Number(1, 13)
	maxDay := time.Date(year, time.Month(month+1), 0, 0, 0, 0, 0, time.UTC).Day()
	day := Number(1, maxDay+1)
	date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
	return date.Format(DateOutputLayout)

// FullDateInRange returns a date string within a given range, given in the format "2006-01-02".
// If no argument is supplied it will return the result of randomdata.FullDate().