2013-05-13 00:15:52 +10:00
|
|
|
// Copyright 2011 Miek Gieben. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2012-01-11 01:55:52 +11:00
|
|
|
package dns
|
|
|
|
|
|
|
|
// Holds a bunch of helper functions for dealing with labels.
|
|
|
|
|
|
|
|
// SplitLabels splits a domainname string into its labels.
|
2012-02-12 21:34:28 +11:00
|
|
|
// www.miek.nl. returns []string{"www", "miek", "nl"}
|
2012-02-15 08:43:04 +11:00
|
|
|
// The root label (.) returns nil.
|
2012-01-11 01:55:52 +11:00
|
|
|
func SplitLabels(s string) []string {
|
2013-06-21 06:36:13 +10:00
|
|
|
// TODO(miek): make this use Split
|
2012-02-24 05:37:08 +11:00
|
|
|
if s == "." {
|
|
|
|
return nil
|
|
|
|
}
|
2012-02-15 08:26:18 +11:00
|
|
|
|
2012-01-11 01:55:52 +11:00
|
|
|
k := 0
|
2012-01-11 02:34:14 +11:00
|
|
|
labels := make([]string, 0)
|
2012-01-28 10:35:37 +11:00
|
|
|
last := byte('.')
|
|
|
|
lastlast := byte('.')
|
2012-01-11 02:34:14 +11:00
|
|
|
s = Fqdn(s) // Make fully qualified
|
2012-01-11 01:55:52 +11:00
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
if s[i] == '.' {
|
2012-01-28 10:35:37 +11:00
|
|
|
if last == '\\' {
|
|
|
|
if lastlast != '\\' {
|
|
|
|
// do nothing
|
|
|
|
continue
|
|
|
|
}
|
2012-01-11 01:55:52 +11:00
|
|
|
}
|
2012-01-11 02:34:14 +11:00
|
|
|
labels = append(labels, s[k:i])
|
2012-01-11 01:55:52 +11:00
|
|
|
k = i + 1 // + dot
|
|
|
|
}
|
2012-01-28 10:35:37 +11:00
|
|
|
lastlast = last
|
|
|
|
last = s[i]
|
2012-01-11 01:55:52 +11:00
|
|
|
}
|
|
|
|
return labels
|
|
|
|
}
|
|
|
|
|
2013-06-21 06:36:13 +10:00
|
|
|
// CompareLabels compares the names s1 and s2 and
|
2012-01-11 02:04:32 +11:00
|
|
|
// returns how many labels they have in common starting from the right.
|
2012-09-05 04:08:55 +10:00
|
|
|
// The comparison stops at the first inequality. The labels are not downcased
|
|
|
|
// before the comparison.
|
2012-01-11 02:04:32 +11:00
|
|
|
//
|
2012-02-12 21:34:28 +11:00
|
|
|
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
|
|
|
// www.miek.nl. and www.bla.nl. have one label in common: nl
|
2012-01-11 01:55:52 +11:00
|
|
|
func CompareLabels(s1, s2 string) (n int) {
|
2013-06-21 06:36:13 +10:00
|
|
|
s1 = Fqdn(s1)
|
|
|
|
s2 = Fqdn(s2)
|
|
|
|
l1 := Split(s1)
|
|
|
|
l2 := Split(s2)
|
2012-01-11 01:55:52 +11:00
|
|
|
|
2013-06-21 06:36:13 +10:00
|
|
|
// the first check
|
|
|
|
if l1 == nil || l2 == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
j1 := len(l1) - 1 // end
|
|
|
|
i1 := len(l1) - 2 // start
|
|
|
|
j2 := len(l2) - 1
|
|
|
|
i2 := len(l2) - 2
|
|
|
|
// the second check can be done here, before we fall through into the for-loop below
|
|
|
|
if s1[l1[j1]:] == s2[l2[j2]:] {
|
|
|
|
n++
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
2012-01-11 01:55:52 +11:00
|
|
|
for {
|
2013-06-21 06:36:13 +10:00
|
|
|
if i1 < 0 || i2 < 0 {
|
2012-01-11 02:34:14 +11:00
|
|
|
break
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
|
2012-01-11 02:34:14 +11:00
|
|
|
n++
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
j1--
|
|
|
|
i1--
|
|
|
|
j2--
|
|
|
|
i2--
|
2012-01-11 02:34:14 +11:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2012-07-16 16:51:39 +10:00
|
|
|
|
2013-06-21 06:36:13 +10:00
|
|
|
// LenLabels returns the number of labels in the string s
|
|
|
|
func LenLabels(s string) (labels int) {
|
2012-07-16 16:51:39 +10:00
|
|
|
if s == "." {
|
|
|
|
return
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
s = Fqdn(s) // TODO(miek): annoyed I need this
|
|
|
|
off := 0
|
|
|
|
end := false
|
|
|
|
for {
|
|
|
|
off, end = nextLabel(s, off)
|
|
|
|
labels++
|
|
|
|
if end {
|
|
|
|
return
|
2012-07-16 16:51:39 +10:00
|
|
|
}
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
|
2012-07-16 16:51:39 +10:00
|
|
|
}
|
2013-06-20 16:49:18 +10:00
|
|
|
|
2013-06-21 06:36:13 +10:00
|
|
|
// Split splits a name s into its label indexes.
|
|
|
|
// www.miek.nl. returns []int{0, 4, 9}. The root name (.) returns nil.
|
|
|
|
func Split(s string) []int {
|
2013-06-21 00:24:14 +10:00
|
|
|
if s == "." {
|
2013-06-21 06:36:13 +10:00
|
|
|
return nil
|
2013-06-21 00:24:14 +10:00
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
s = Fqdn(s) // Grrr!
|
|
|
|
idx := []int{0} // TODO(miek): could allocate more (10) and then extend when needed
|
2013-06-21 00:24:14 +10:00
|
|
|
off := 0
|
|
|
|
end := false
|
2013-06-21 06:36:13 +10:00
|
|
|
|
2013-06-21 00:24:14 +10:00
|
|
|
for {
|
2013-06-21 06:36:13 +10:00
|
|
|
off, end = nextLabel(s, off)
|
2013-06-21 00:24:14 +10:00
|
|
|
if end {
|
2013-06-21 06:36:13 +10:00
|
|
|
return idx
|
2013-06-21 00:24:14 +10:00
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
idx = append(idx, off)
|
2013-06-21 00:24:14 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 06:36:13 +10:00
|
|
|
// nextLabel returns the index of the start of the next label in the
|
|
|
|
// string s. The bool end is true when the end of the string has been
|
2013-06-20 16:49:18 +10:00
|
|
|
// reached.
|
|
|
|
func nextLabel(s string, offset int) (i int, end bool) {
|
2013-06-21 06:36:13 +10:00
|
|
|
// The other label function are quite generous with memory,
|
2013-06-20 16:49:18 +10:00
|
|
|
// this one does not allocate.
|
|
|
|
quote := false
|
2013-06-21 06:36:13 +10:00
|
|
|
for i = offset; i < len(s)-1; i++ {
|
2013-06-20 16:49:18 +10:00
|
|
|
switch s[i] {
|
|
|
|
case '\\':
|
2013-06-21 00:24:14 +10:00
|
|
|
quote = !quote
|
2013-06-20 16:49:18 +10:00
|
|
|
default:
|
|
|
|
quote = false
|
|
|
|
case '.':
|
|
|
|
if quote {
|
|
|
|
quote = !quote
|
|
|
|
continue
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
return i + 1, false
|
2013-06-20 16:49:18 +10:00
|
|
|
}
|
|
|
|
}
|
2013-06-21 06:36:13 +10:00
|
|
|
return i + 1, true
|
2013-06-20 16:49:18 +10:00
|
|
|
}
|