Documentation ¶
Overview ¶
Package hostpital provides functions to assist in the maintenance of hosts files.
## Usage
```go import "github.com/KEINOS/go-hostpital/hostpital" ```
## Example Usage
- [Package examples](https://pkg.go.dev/github.com/KEINOS/go-hostpital/hostpital#pkg-examples) | godoc @ pkg.go.dev
Index ¶
- Constants
- func FileExists(path string) bool
- func FindFile(patternFile, pathDirSearch string) ([]string, error)
- func IsCommentLine(line string) bool
- func IsCompatibleIDNA2008(hostName string) bool
- func IsCompatibleRFC6125(host string) bool
- func IsCompatibleRFC6125Pattern(host string) bool
- func IsExistingFile(path string) bool
- func IsIPAddress(hostName string) bool
- func PickRandom(items []string) string
- func ReverseDNS(hostName string) string
- func SleepRandom(secMax int)
- func TransformToASCII(hostName string) (string, error)
- func TransformToUnicode(hostASCII string) (string, error)
- func TrimComment(line string) (string, error)
- func TrimDNSByLevel(host string, level int) string
- func TrimIPAdd(line string) string
- func TrimWordGaps(input string) string
- type Parser
- type Validator
Examples ¶
- FileExists
- FindFile
- IsCommentLine
- IsCompatibleIDNA2008
- IsCompatibleRFC6125
- IsCompatibleRFC6125Pattern
- IsExistingFile
- IsIPAddress
- Parser
- Parser.ParseFileTo
- Parser.ParseString
- PickRandom
- ReverseDNS
- TransformToASCII
- TransformToUnicode
- TrimComment
- TrimDNSByLevel
- TrimIPAdd
- TrimWordGaps
- Validator
- Validator.ValidateFile
- Validator.ValidateLine
Constants ¶
const ( // DelimComnt is the delimiter for comments. DelimComnt = '#' // DelimDNS is the delimiter for DNS labels. DelimDNS = '.' // LF is the line feed, "\n". LF = int32(0x0a) // CR is the carriage return, "\r". CR = int32(0x0d) // Cutset is the set of characters for trimming white spaces. Cutset = "\t\n\v\f\r " )
Variables ¶
This section is empty.
Functions ¶
func FileExists ¶
FileExists returns true if the file exists and is not a directory.
Example ¶
package main import ( "fmt" "os" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // FileExists returns true if the file exists. if ok := hostpital.FileExists("examples_test.go"); ok { fmt.Println("given path exists and is a file") } // FileExists returns false if the path is a directory even if the path exists. if ok := hostpital.FileExists(os.TempDir()); !ok { fmt.Println("given path is a directory") } // FileExists returns false if the path does not exist. if ok := hostpital.FileExists("unknown.txt"); !ok { fmt.Println("given path does not exist") } }
Output: given path exists and is a file given path is a directory given path does not exist
func FindFile ¶
FindFile returns a list of file paths found under the given directory. It will not include directories even if it matches. If no files are found, it will return an fs.ErrNotExist error.
e.g. FindFile("hosts*", "/home/user") will return:
["/home/user/.ssh/hosts", "/home/user/.ssh/hosts.deny", "/home/user/.ssh/hosts.allow"]
Example ¶
package main import ( "fmt" "log" "path/filepath" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { patternSearch := "hosts*" pathDirSearch := filepath.Join("testdata", "search_me") foundFiles, err := hostpital.FindFile(patternSearch, pathDirSearch) if err != nil { log.Fatalf("failed to find files: %v", err) } for _, file := range foundFiles { fmt.Println(filepath.ToSlash(file)) } }
Output: testdata/search_me/dir1/hosts testdata/search_me/dir2/hosts.txt testdata/search_me/dir2/subdir2/hosts testdata/search_me/hosts/hosts
func IsCommentLine ¶
IsCommentLine returns true if the given line is a comment line.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, line := range []string{ "# This is a comment line", " # This is a comment line with spaces.", "\t\t\t# This is a comment line with tabs.", // white spaces are trimmed "example.com # This is an in-line comment.", // has a non-comment info } { // IsCommentLine returns true if the line is a single comment line. // It returns false if the line contains a non-comment info. fmt.Printf("#%d: %v\n", index+1, hostpital.IsCommentLine(line)) } }
Output: #1: true #2: true #3: true #4: false
func IsCompatibleIDNA2008 ¶
IsCompatibleIDNA2008 returns true if the given hostName is properly formatted for registration and is in ASCII/Punycode. False if it contains hosts or labels in Unicode or not IDNA2008 compatible.
Use TransformASCII() to convert raw punycode to IDNA2008 compatible ASCII.
Note that this function returns false if the label (host name or part of the subdomain) contains "_" (underscore).
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, sample := range []struct { input string want bool }{ // Golden cases {input: "example.com", want: true}, {input: "0.0.0.0", want: true}, {input: "xn--fa-hia.com", want: true}, // IDNA2008 compatible and is ASCII/punycoded {input: "xn--gpher-jua.com", want: true}, // same as above // Wrong cases {input: "27--m01police.55fifayellow.com", want: false}, // Double hyphen with mal-formed punycode is not allowed {input: "my_host1.example.com", want: false}, // Host contains under score {input: "faß.com", want: false}, // Must be in punycode/ASCII. Use TransformToASCII() {input: "www.аррӏе.com", want: false}, // Same as above {input: "*.faß.com", want: false}, // Wildcard is not allowed. Use IsCompatibleRFC6125Pattern() {input: ".example.com", want: false}, // Must not start with a dot } { // True if host name is ready for registration. False if it is a raw // punycode or not IDNA2008 compatible. got := hostpital.IsCompatibleIDNA2008(sample.input) if got != sample.want { log.Fatalf("failed test #%d. input: %s, want: %v, got: %v", index+1, sample.input, sample.want, got) } fmt.Printf("IsCompatibleIDNA2008(%#v) --> %v\n", sample.input, sample.want) } }
Output: IsCompatibleIDNA2008("example.com") --> true IsCompatibleIDNA2008("0.0.0.0") --> true IsCompatibleIDNA2008("xn--fa-hia.com") --> true IsCompatibleIDNA2008("xn--gpher-jua.com") --> true IsCompatibleIDNA2008("27--m01police.55fifayellow.com") --> false IsCompatibleIDNA2008("my_host1.example.com") --> false IsCompatibleIDNA2008("faß.com") --> false IsCompatibleIDNA2008("www.аррӏе.com") --> false IsCompatibleIDNA2008("*.faß.com") --> false IsCompatibleIDNA2008(".example.com") --> false
func IsCompatibleRFC6125 ¶
IsCompatibleRFC6125 returns true if the given host name can be matched or matched against according to RFC 6125 2.2, with some leniency to accommodate legacy values.
Note: This function is a copy of the internal function from the crypto/x509 package under BSD-3-Clause license. Please see the source code in "is_valid_hostname.go" for more information.
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, test := range []struct { host string want bool }{ // Golden cases {host: "example.com", want: true}, {host: "eXample123-.com", want: true}, {host: "example.com.", want: true}, {host: "exa_mple.com", want: true}, {host: "127.0.0.1", want: true}, // Wrong cases {host: "0.0.0.0 example.com", want: false}, // no space allowed {host: "-eXample123-.com", want: false}, {host: "", want: false}, {host: ".", want: false}, {host: "example..com", want: false}, {host: ".example.com", want: false}, {host: "*.example.com.", want: false}, {host: "*foo.example.com", want: false}, {host: "foo.*.example.com", want: false}, {host: "foo,bar", want: false}, {host: "project-dev:us-central1:main", want: false}, } { got := hostpital.IsCompatibleRFC6125(test.host) if got != test.want { log.Fatalf("failed test #%d: IsCompatibleRFC6125(%#v) --> %v, want: %v", index+1, test.host, got, test.want) } } fmt.Println("OK") }
Output: OK
func IsCompatibleRFC6125Pattern ¶
IsCompatibleRFC6125Pattern is similar to IsValidHostname but it also allows wildcard patterns.
Note: This function is a copy of the internal function from the crypto/x509 package under BSD-3-Clause license. Please see the source code in "is_valid_hostname.go" for more information.
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, test := range []struct { host string want bool }{ // Golden cases {host: "example.com", want: true}, {host: "eXample123-.com", want: true}, {host: "exa_mple.com", want: true}, {host: "127.0.0.1", want: true}, {host: "*.example.com", want: true}, // wildcard is allowed // Wrong cases {host: "0.0.0.0 example.com", want: false}, // no space allowed {host: "example.com.", want: false}, // dot at the end is not allowed {host: "-eXample123-.com", want: false}, {host: "", want: false}, {host: ".", want: false}, {host: "example..com", want: false}, {host: ".example.com", want: false}, {host: "*.example.com.", want: false}, {host: "*foo.example.com", want: false}, {host: "foo.*.example.com", want: false}, {host: "foo,bar", want: false}, {host: "project-dev:us-central1:main", want: false}, } { got := hostpital.IsCompatibleRFC6125Pattern(test.host) if got != test.want { log.Fatalf("failed test #%d: IsCompatibleRFC6125Pattern(%#v) --> %v, want: %v", index+1, test.host, got, test.want) } } fmt.Println("OK") }
Output: OK
func IsExistingFile ¶
IsExistingFile returns true if the path is an existing file. It returns false if the path is a directory or does not exist.
Example ¶
package main import ( "fmt" "log" "path/filepath" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, sample := range []struct { nameFile string want bool }{ {nameFile: "hosts.txt", want: true}, {nameFile: "hosts_not_exists.txt", want: false}, {nameFile: "", want: false}, // is directory } { pathFile := filepath.Join("testdata", sample.nameFile) got := hostpital.IsExistingFile(pathFile) if got != sample.want { log.Fatalf("failed test #%d. input: %s, want: %v, got: %v", index+1, pathFile, sample.want, got) } } fmt.Println("OK") }
Output: OK
func IsIPAddress ¶
IsIPAddress returns true if the given string is a valid IPv4 or IPv6 address. Note that white spaces are not allowed.
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, test := range []struct { input string want bool }{ // Golden cases {input: "0.0.0.0", want: true}, {input: "::", want: true}, // Wrong cases {input: "0.0.0.0.0", want: false}, } { // Detects IP address (IPV4 and IPV6) got := hostpital.IsIPAddress(test.input) if got != test.want { log.Fatalf("test #%v failed. IsIPAddress(%#v) --> %v (want: %v)", index+1, test.input, got, test.want) } fmt.Printf("IsIPAddress(%#v) --> %v\n", test.input, got) } }
Output: IsIPAddress("0.0.0.0") --> true IsIPAddress("::") --> true IsIPAddress("0.0.0.0.0") --> false
func PickRandom ¶
PickRandom returns a random item from the given slice.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { items := []string{ "one.example.com", "two.example.com", "three.example.com", "four.example.com", "five.example.com", } changed := false picked1st := hostpital.PickRandom(items) // Pick 10 times since the number of items is too few. for i := 0; i < 10; i++ { // Sleep for a random time from 0 to 999 milliseconds to avoid the same // seed for the random number generator. The CI server is too fast. hostpital.SleepRandom(1) pickedCurr := hostpital.PickRandom(items) if pickedCurr != picked1st { changed = true } } fmt.Println("changed:", changed) }
Output: changed: true
func ReverseDNS ¶
ReverseDNS converts the DNS labels in the reverse order.
For example, "www.google.com" will be converted to "com.google.www".
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // ReverseDNS reverses the order of the labels in a domain name. // Useful for grouping hosts by domain name. fmt.Println(hostpital.ReverseDNS("www.example.com")) fmt.Println(hostpital.ReverseDNS("com.example.www")) }
Output: com.example.www www.example.com
func SleepRandom ¶
func SleepRandom(secMax int)
SleepRandom sleeps for a random amount of time. If secMax is 0 or 1, it sleeps for a random amount of time between 0 and 999 milliseconds.
func TransformToASCII ¶
TransformToASCII converts the given hostName in UNICODE to ASCII/punycode.
It does the opposite of TransformToUnicode().
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // Unicode --> ASCII/Punycode conversion. // For the opposite, see TransformToUnicode(). hostASCII, err := hostpital.TransformToASCII("göpher.com") fmt.Println("TransformToASCII(\"göpher.com\") -->", hostASCII, err) }
Output: TransformToASCII("göpher.com") --> xn--gpher-jua.com <nil>
func TransformToUnicode ¶
TransformToUnicode converts the given punycoded host name in ASCII to UNICODE format.
It does the opposite of TransformToASCII().
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // ASCII/Punycode --> Unicode conversion. It will error if the input is not // convertable to Unicode. For the opposite, see TransformToASCII(). hostPunycode, err := hostpital.TransformToUnicode("xn--gpher-jua.com") fmt.Println("TransformToUnicode(\"xn--gpher-jua.com\") -->", hostPunycode, err) }
Output: TransformToUnicode("xn--gpher-jua.com") --> göpher.com <nil>
func TrimComment ¶
TrimComment removes hash ("#") comments from the given string and trailing spaces.
This function expects the given string to be a line from a hosts file and will error if the given line contains a line break.
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { line := "127.0.0.0 localhost # this is a line comment" // Trim a comment from a line hostTrimmed, err := hostpital.TrimComment(line) if err != nil { log.Fatal(err) } fmt.Println(hostTrimmed) }
Output: 127.0.0.0 localhost
func TrimDNSByLevel ¶
TrimDNSByLevel returns the host name with the specified number of DNS levels.
E.g.
TrimDNSByLevel("www.example.com", 0) returns "com". Such as the top level domain. TrimDNSByLevel("www.example.com", 1) returns "example.com". Such as the second level domain. TrimDNSByLevel("www.example.com", 5) returns "www.example.com". As is.
Example ¶
package main import ( "fmt" "log" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, test := range []struct { host string want string level int }{ {host: "www.example.com", level: 0, want: "com"}, {host: "www.example.com", level: 1, want: "example.com"}, {host: "www.example.com", level: 2, want: "www.example.com"}, {host: "www.example.com", level: 5, want: "www.example.com"}, } { got := hostpital.TrimDNSByLevel(test.host, test.level) if got != test.want { log.Fatalf("failed test #%d: host: %s, level: %d, want: %s, got: %s", index, test.host, test.level, test.want, got) } fmt.Printf("Level %d: %s --> %s\n", test.level, test.host, got) } }
Output: Level 0: www.example.com --> com Level 1: www.example.com --> example.com Level 2: www.example.com --> www.example.com Level 5: www.example.com --> www.example.com
func TrimIPAdd ¶
TrimIPAdd removes the leading IP address from the given string.
Note that this function expects the given string to be a line from a hosts file. e.g. "0.0.0.0 example.com".
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, line := range []struct { input string want string }{ {"", ""}, {" ", ""}, {"123.123.123.123", ""}, {"example.com", "example.com"}, {"\texample.com", "example.com"}, {" example.com", "example.com"}, {"123.123.123.123 example.com ", "example.com"}, {"123.123.123.123 example.com ", "example.com"}, {"123.123.123.123\texample.com ", "example.com"}, { "123.123.123.123 0.0.0.0 sub1.example.com sub2.example.com", "sub1.example.com sub2.example.com", }, } { expect := line.want actual := hostpital.TrimIPAdd(line.input) fmt.Printf("#%d: %q --> %q ... ", index+1, line.input, actual) if actual != expect { fmt.Printf("FAIL (want: %q, got: %q)\n", expect, actual) } else { fmt.Println("PASS") } } }
Output: #1: "" --> "" ... PASS #2: " " --> "" ... PASS #3: "123.123.123.123" --> "" ... PASS #4: "example.com" --> "example.com" ... PASS #5: "\texample.com" --> "example.com" ... PASS #6: " example.com" --> "example.com" ... PASS #7: "123.123.123.123 example.com " --> "example.com" ... PASS #8: "123.123.123.123 example.com " --> "example.com" ... PASS #9: "123.123.123.123\texample.com " --> "example.com" ... PASS #10: "123.123.123.123 0.0.0.0 sub1.example.com sub2.example.com" --> "sub1.example.com sub2.example.com" ... PASS
func TrimWordGaps ¶
TrimWordGaps reduces redundant and repetitive whitespace in the input string. It removes the line breaks, tabs, leading and trailing spaces as well.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { for index, input := range []string{ "0.0.0.0 example.com", "0.0.0.0\texample.com", " \t\n\t 127.0.0.1\texample.com\n\n\t# inline comment", "127.0.0.1\t example.com # inline\tcomment", } { result := hostpital.TrimWordGaps(input) fmt.Printf("#%d: %q\n", index+1, result) } }
Output: #1: "0.0.0.0 example.com" #2: "0.0.0.0 example.com" #3: "127.0.0.1 example.com # inline comment" #4: "127.0.0.1 example.com # inline comment"
Types ¶
type Parser ¶
type Parser struct { UseIPAddress string // If not empty and 'TrimIPAddress' is true, use this IP address instead (default: ""). IDNACompatible bool // If true, punycode is converted to IDNA2008 compatible (default: true). OmitEmptyLine bool // If true, empty lines are omitted (default: true). SortAfterParse bool // If true, sort the lines after parsing (default: false). SortAsReverseDNS bool // If true, sort the lines as reversed DNS hosts (default: false). TrimComment bool // If true, comment is trimmed (default: true). TrimIPAddress bool // If true, leading IP address is trimmed (default: true). TrimLeadingSpace bool // If true, leading spaces are trimmed (default: true). TrimTrailingSpace bool // If true, trailing spaces are trimmed (default: true). // contains filtered or unexported fields }
Parser holds the settings and the rules for the parsing. To simply validate the hostfile, use the methods in the Validator type instead.
Example ¶
This example parses the hosts file as a DNS sinkhole. Which all the hosts will point to 0.0.0.0 and will not be able to connect to the Internet.
package main import ( "fmt" "log" "path/filepath" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { pathFile := filepath.Join("testdata", "default.txt") // For the default settings, see the NewValidator() example. parser := hostpital.NewParser() // Set the IP address to use for all the hosts. parser.UseIPAddress = "0.0.0.0" parsed, err := parser.ParseFile(pathFile) if err != nil { log.Fatal(err) } fmt.Println(parsed) }
Output: 0.0.0.0 dummy1.example.com 0.0.0.0 dummy2.example.com 0.0.0.0 dummy3.example.com 0.0.0.0 dummy4.example.com 0.0.0.0 dummy5.example.com dummy6.example.com
func NewParser ¶
func NewParser() *Parser
NewParser returns a new Parser instance with the default values.
func (*Parser) CountLines ¶
CountLines counts the number of lines in the file.
func (*Parser) ParseFile ¶
ParseFile reads the file from pathFile and returns the parsed lines as a string according to the settings in the Parser.
func (*Parser) ParseFileTo ¶
ParseFileTo reads the file from pathFileIn and writes the parsed lines to fileOut.
Example ¶
package main import ( "bytes" "fmt" "log" "path/filepath" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { pathFile := filepath.Join("testdata", "default.txt") parser := hostpital.NewParser() // Set property to sort after parsing parser.SortAfterParse = true // Create a buffer to store the parsed hosts file var buf bytes.Buffer // Execute ParseFileTo if err := parser.ParseFileTo(pathFile, &buf); err != nil { log.Fatal(err) } fmt.Println(buf.String()) }
Output: dummy1.example.com dummy2.example.com dummy3.example.com dummy4.example.com dummy5.example.com dummy6.example.com
func (*Parser) ParseLine ¶
ParseLine parses the given line and returns the parsed line as a string according to the settings in the Parser.
func (*Parser) ParseString ¶
ParseString parses the given string and returns the parsed lines as a string according to the settings in the Parser.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { hosts := `# this is a comment badboy5.example.com badboy6.example.com # this is another comment 123.123.123.120 badboy4.example.com 123.123.123.121 badboy3.example.com 123.123.123.122 badboy2.example.com 123.123.123.123 badboy1.example.com ` parser := hostpital.NewParser() // Set property for user custom settings parser.SortAfterParse = true parser.UseIPAddress = "0.0.0.0" parsed := parser.ParseString(hosts) fmt.Println(parsed) }
Output: 0.0.0.0 badboy1.example.com 0.0.0.0 badboy2.example.com 0.0.0.0 badboy3.example.com 0.0.0.0 badboy4.example.com 0.0.0.0 badboy5.example.com badboy6.example.com
type Validator ¶
type Validator struct { AllowComment bool // If true, the line can be a comment (default: false). AllowEmptyLine bool // If true, empty line returns true (default: true). AllowHyphen bool // If true, the label can begin with hyphen (default: false). AllowHyphenDouble bool // If true, unconvertable punycode with double hyphen is allowed (default: false). AllowIndent bool // If true, the line can be indented (default: false). AllowIPAddressOnly bool // If true, the line can be only an IP address (default: false). AllowTrailingSpace bool // If true, the line can have trailing spaces (default: false). AllowUnderscore bool // If true, the label can have underscore (default: false). IDNACompatible bool // If true, the host must be compatible to IDNA2008 and false to RFC 6125 2.2 (default: true). // contains filtered or unexported fields }
Validator holds the settings and the rules for the validation. To clean up the hostfile, use the methods in the Parser type instead.
It is recommended to use NewValidator() to create a new Validator due to the default values.
Example ¶
package main import ( "fmt" "github.com/Code-Hex/dd" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { validator := hostpital.NewValidator() // Print default settings fmt.Println(dd.Dump(validator)) }
Output: &hostpital.Validator{ mutx: sync.Mutex{ state: 0, sema: 0, }, AllowComment: false, AllowEmptyLine: true, AllowHyphen: false, AllowHyphenDouble: false, AllowIndent: false, AllowIPAddressOnly: false, AllowTrailingSpace: false, AllowUnderscore: false, IDNACompatible: true, isInitialized: true, }
func NewValidator ¶
func NewValidator() *Validator
NewValidator returns a new Validator instance with the default values.
func (*Validator) ValidateFile ¶
ValidateFile returns true if the file is valid according to the settings.
Example ¶
package main import ( "fmt" "path/filepath" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // Validator with default settings validator := hostpital.NewValidator() // Want RFC 6125 2.2 compatibility. If true, IDNA2008 compatible. validator.IDNACompatible = false // Allow comment lines in the hostfile. validator.AllowComment = true // Allow labels to begin with hyphen. // This setting is useful to manage hosts file for DNS sinkhole. "traditional // domain name" does not allow hyphen in the first character position of // their labels. Such as "m.-www99a.abc.example.com" for example. Usually // it is blocked by the client side's router, browser, etc. However, some // malicious domains owns their name server configured to resolve it to find // out web clients who doesn't care about it. validator.AllowHyphen = true // Validate a file pathFile := filepath.Join("testdata", "hosts.txt") if validator.ValidateFile(pathFile) { fmt.Println("The hostfile is valid.") } }
Output: The hostfile is valid.
func (*Validator) ValidateLine ¶
ValidateLine returns nil if the line is valid according to the settings.
Example ¶
package main import ( "fmt" "github.com/KEINOS/go-hostpital/hostpital" ) func main() { // Validator with default settings // AllowComment: false // AllowEmptyLine: true // AllowHyphen: false // AllowHyphenDouble: false // AllowIndent: false // AllowIPAddressOnly: false // AllowTrailingSpace: false // AllowUnderscore: false // IDNACompatible: true validator := hostpital.NewValidator() // User custom settings validator.AllowTrailingSpace = true for index, line := range []string{ // Valid cases according to the settings. "example.com", "example.com ", "", // Invalid cases according to the settings. " example.com", "123.123.123.123", "# This is a comment line", "example.com # This is an in-line comment", " ", // false. Empty line is allowed but indent is not allowed. } { err := validator.ValidateLine(line) fmt.Printf("#%d: %v\n", index+1, err) } }
Output: #1: <nil> #2: <nil> #3: <nil> #4: failed to trim line: indent is not allowed #5: IP address only line is not allowed #6: failed to validate chunk/part of line: "#" is not IDNA2008 compatible: idna: disallowed rune U+0023 #7: failed to validate chunk/part of line: "#" is not IDNA2008 compatible: idna: disallowed rune U+0023 #8: failed to trim line: indent is not allowed
Source Files ¶
- Is_compatible_rfc6125.go
- file_exists.go
- find_file.go
- hostpital.go
- is_comment_line.go
- is_compatible_idna2008.go
- is_existing_file.go
- is_ip_address.go
- parser.go
- pick_random.go
- reverse_dns.go
- sleep_random.go
- transform_to_ascii.go
- transform_to_unicode.go
- trim_comment.go
- trim_dns_by_level.go
- trim_ipadd.go
- trim_word_gaps.go
- validator.go