| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | package middleware
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"bytes"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Less returns <0 when a is less than b, 0 when they are equal and
 | 
					
						
							|  |  |  | // >0 when a is larger than b.
 | 
					
						
							| 
									
										
										
										
											2016-03-30 20:13:48 +01:00
										 |  |  | // The function orders names in DNSSEC canonical order: RFC 4034s section-6.1
 | 
					
						
							| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | //
 | 
					
						
							|  |  |  | // See http://bert-hubert.blogspot.co.uk/2015/10/how-to-do-fast-canonical-ordering-of.html
 | 
					
						
							| 
									
										
										
										
											2016-04-04 09:10:07 +00:00
										 |  |  | // for a blog article on this implementation.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | //
 | 
					
						
							|  |  |  | // The values of a and b are *not* lowercased before the comparison!
 | 
					
						
							| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | func Less(a, b string) int {
 | 
					
						
							|  |  |  | 	i := 1
 | 
					
						
							|  |  |  | 	aj := len(a)
 | 
					
						
							|  |  |  | 	bj := len(b)
 | 
					
						
							|  |  |  | 	for {
 | 
					
						
							| 
									
										
										
										
											2016-03-30 16:45:02 +00:00
										 |  |  | 		ai, oka := dns.PrevLabel(a, i)
 | 
					
						
							|  |  |  | 		bi, okb := dns.PrevLabel(b, i)
 | 
					
						
							|  |  |  | 		if oka && okb {
 | 
					
						
							|  |  |  | 			return 0
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 		// sadly this []byte will allocate... TODO(miek): check if this is needed
 | 
					
						
							|  |  |  | 		// for a name, otherwise compare the strings.
 | 
					
						
							| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | 		ab := []byte(a[ai:aj])
 | 
					
						
							|  |  |  | 		bb := []byte(b[bi:bj])
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 		doDDD(ab)
 | 
					
						
							|  |  |  | 		doDDD(bb)
 | 
					
						
							| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		res := bytes.Compare(ab, bb)
 | 
					
						
							|  |  |  | 		if res != 0 {
 | 
					
						
							|  |  |  | 			return res
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		i++
 | 
					
						
							|  |  |  | 		aj, bj = ai, bi
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return 0
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | func doDDD(b []byte) {
 | 
					
						
							| 
									
										
										
										
											2016-03-29 23:20:26 +01:00
										 |  |  | 	lb := len(b)
 | 
					
						
							|  |  |  | 	for i := 0; i < lb; i++ {
 | 
					
						
							|  |  |  | 		if i+3 < lb && b[i] == '\\' && isDigit(b[i+1]) && isDigit(b[i+2]) && isDigit(b[i+3]) {
 | 
					
						
							|  |  |  | 			b[i] = dddToByte(b[i:])
 | 
					
						
							|  |  |  | 			for j := i + 1; j < lb-3; j++ {
 | 
					
						
							|  |  |  | 				b[j] = b[j+3]
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			lb -= 3
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func isDigit(b byte) bool     { return b >= '0' && b <= '9' }
 | 
					
						
							|  |  |  | func dddToByte(s []byte) byte { return byte((s[1]-'0')*100 + (s[2]-'0')*10 + (s[3] - '0')) }
 |