Class: Dnsruby::Name
- Inherits:
-
Object
- Object
- Dnsruby::Name
- Defined in:
- lib/Dnsruby/name.rb
Overview
Dnsruby::Name class
A representation of a DNS name (RFC1035, section 3.1)
methods
-
Name::create(namestring)
-
Name#absolute?
-
Name#wild?
-
Name#subdomain_of?(other)
-
Name#labels
Defined Under Namespace
Classes: Label
Constant Summary collapse
- MaxNameLength =
255
Instance Attribute Summary collapse
-
#labels ⇒ Object
readonly
Returns the value of attribute labels.
Class Method Summary collapse
-
.create(arg) ⇒ Object
– A Name is a collection of Labels.
-
.decode(wire) ⇒ Object
:nodoc: all.
-
.encode(presentation) ⇒ Object
wire,leftover=presentation2wire(leftover) Will parse the input presentation format and return everything before the first non-escaped “.” in the first element of the return array and all that has not been parsed yet in the 2nd argument.
-
.encodedlabels2name(labels) ⇒ Object
:nodoc: all.
-
.name2encodedlabels(dName) ⇒ Object
Utility function.
-
.split_escaped(arg) ⇒ Object
:nodoc: all.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
:nodoc:.
-
#[](i) ⇒ Object
:nodoc: all.
-
#absolute=(on) ⇒ Object
:nodoc:.
-
#absolute? ⇒ Boolean
Returns true if this Name is absolute.
- #canonically_before(n) ⇒ Object
- #downcase ⇒ Object
-
#hash ⇒ Object
:nodoc:.
-
#initialize(labels, absolute = true) ⇒ Name
constructor
This method should only be called internally.
-
#inspect ⇒ Object
:nodoc:.
-
#length ⇒ Object
:nodoc: all.
-
#strip_label ⇒ Object
:nodoc:.
-
#subdomain_of?(other) ⇒ Boolean
Tests subdomain-of relation : returns true if this name is a subdomain of
other. -
#to_a ⇒ Object
:nodoc: all.
-
#to_s ⇒ Object
returns the domain name as a string.
-
#wild? ⇒ Boolean
Is this name a wildcard?.
Constructor Details
#initialize(labels, absolute = true) ⇒ Name
This method should only be called internally. Use Name::create to create a new Name
72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/Dnsruby/name.rb', line 72 def initialize(labels, absolute=true) #:nodoc: all total_length=labels.length-1 labels.each do |l| if (!l.kind_of?Label) raise ArgumentError.new("Name::new called with non-labels. Use Name::create instead?") end total_length+=l.length end if (total_length > MaxNameLength) raise ResolvError.new("Name length is #{total_length}, greater than max of #{MaxNameLength} octets!") end @labels = labels @absolute = absolute end |
Instance Attribute Details
#labels ⇒ Object (readonly)
Returns the value of attribute labels.
68 69 70 |
# File 'lib/Dnsruby/name.rb', line 68 def labels @labels end |
Class Method Details
.create(arg) ⇒ Object
– A Name is a collection of Labels. Each label is presentation-formatted When a Name is wire-encoded, the label array is walked, and each label is wire-encoded. When a Name is unencoded, each label is unencoded, and added to the Name collection of labels. When a Name is made from a string, the Name is split into Labels. ++ Creates a new Dnsruby::Name from arg. arg can be :
- Name
-
returns
arg
- String
-
returns a new Name
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/Dnsruby/name.rb', line 42 def self.create(arg) case arg when Name return Name.new(arg.labels, arg.absolute?) when String # arg.gsub!(/\.$/o, "") if (arg==".") return Name.new([],true) end if (arg=="") return Name.new([],false) end return Name.new(split_escaped(arg), /\.\z/ =~ arg ? true : false) # return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false) when Array return Name.new(arg, /\.\z/ =~ ((arg.last.kind_of?String)?arg.last : arg.last.string) ? true : false) else raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}") end end |
.decode(wire) ⇒ Object
:nodoc: all
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/Dnsruby/name.rb', line 229 def self.decode(wire) #:nodoc: all presentation="" length=wire.length # There must be a nice regexp to do this.. but since I failed to # find one I scan the name string until I find a '\', at that time # I start looking forward and do the magic. i=0; while (i < length ) c=wire.unpack("x#{i}C1") [0] if ( c < 33 || c > 126 ) presentation=presentation + sprintf("\\%03u" ,c) elsif ( c.chr == "\"" ) presentation=presentation + "\\\"" elsif ( c.chr == "\$") presentation=presentation + "\\\$" elsif ( c.chr == "(" ) presentation=presentation + "\\(" elsif ( c.chr == ")" ) presentation=presentation + "\\)" elsif ( c.chr == ";" ) presentation=presentation + "\\;" elsif ( c.chr == "@" ) presentation=presentation + "\\@" elsif ( c.chr == "\\" ) presentation=presentation + "\\\\" elsif ( c.chr == ".") presentation=presentation + "\\." else presentation=presentation + c.chr() end i=i+1 end return Label.new(presentation) end |
.encode(presentation) ⇒ Object
wire,leftover=presentation2wire(leftover)
Will parse the input presentation format and return everything before the first non-escaped “.” in the first element of the return array and all that has not been parsed yet in the 2nd argument.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/Dnsruby/name.rb', line 273 def self.encode(presentation) #:nodoc: all presentation=presentation.to_s wire=""; length=presentation.length; i=0; while (i < length ) c=presentation.unpack("x#{i}C1") [0] if (c == 46) # ord('.') endstring = presentation[i+1, presentation.length-(i+1)] return Label.new(wire),endstring end if (c == 92) # ord'\\' #backslash found pos = i+1 # pos sets where next pattern matching should start if (presentation.index(/\G(\d\d\d)/o, pos)) wire=wire+[$1.to_i].pack("C") i=i+3 elsif(presentation.index(/\Gx([0..9a..fA..F][0..9a..fA..F])/o, pos)) wire=wire+[$1].pack("H*") i=i+3 elsif(presentation.index(/\G\./o, pos)) wire=wire+"\." i=i+1 elsif(presentation.index(/\G@/o,pos)) wire=wire+"@" i=i+1 elsif(presentation.index(/\G\(/o, pos)) wire=wire+"(" i=i+1 elsif(presentation.index(/\G\)/o, pos)) wire=wire+")" i=i+1 elsif(presentation.index(/\G\\/o, pos)) wire=wire+"\\" i+=1 end else wire = wire + [c].pack("C") end i=i+1 end return Label.new(wire) end |
.encodedlabels2name(labels) ⇒ Object
:nodoc: all
221 222 223 224 225 226 227 |
# File 'lib/Dnsruby/name.rb', line 221 def self.encodedlabels2name(labels) #:nodoc: all ls = [] labels.each do |l| ls.push(Name.decode(l.string)) end return Name.new(ls) end |
.name2encodedlabels(dName) ⇒ Object
Utility function
name2labels to translate names from presentation format into an array of “wire-format” labels.
in: dName a string with a domain name in presentation format (1035 sect 5.1) out: an array of labels in wire format.
210 211 212 213 214 215 216 217 218 219 |
# File 'lib/Dnsruby/name.rb', line 210 def self.name2encodedlabels (dName) #:nodoc: all names=[] j=0; while (dName && dName.length > 0) names[j],dName = encode(dName) j+=1 end return names end |
.split_escaped(arg) ⇒ Object
:nodoc: all
63 64 65 66 |
# File 'lib/Dnsruby/name.rb', line 63 def self.split_escaped(arg) #:nodoc: all encodedlabels = name2encodedlabels(arg) return encodedlabels2name(encodedlabels).labels end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
:nodoc:
149 150 151 152 |
# File 'lib/Dnsruby/name.rb', line 149 def ==(other) # :nodoc: return false unless Name === other return @labels == other.labels && @absolute == other.absolute? end |
#[](i) ⇒ Object
:nodoc: all
185 186 187 |
# File 'lib/Dnsruby/name.rb', line 185 def [](i) #:nodoc: all return @labels[i] end |
#absolute=(on) ⇒ Object
:nodoc:
102 103 104 |
# File 'lib/Dnsruby/name.rb', line 102 def absolute=(on) # :nodoc: @absolute = on end |
#absolute? ⇒ Boolean
Returns true if this Name is absolute
98 99 100 |
# File 'lib/Dnsruby/name.rb', line 98 def absolute? return @absolute end |
#canonically_before(n) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/Dnsruby/name.rb', line 119 def canonically_before(n) if (!(Name === n)) n = Name.create(n) end # @TODO@ Work out whether this name is canonically before the passed Name # RFC 4034 section 6.1 # For the purposes of DNS security, owner names are ordered by treating #individual labels as unsigned left-justified octet strings. The #absence of a octet sorts before a zero value octet, and uppercase #US-ASCII letters are treated as if they were lowercase US-ASCII #letters. #To compute the canonical ordering of a set of DNS names, start by #sorting the names according to their most significant (rightmost) #labels. For names in which the most significant label is identical, #continue sorting according to their next most significant label, and #so forth. # Get the list of labels for both names, and then swap them my_labels = @labels.reverse other_labels = n.labels.reverse my_labels.each_index {|i| if (!other_labels[i]) return false end next if (other_labels[i].downcase == my_labels[i].downcase) return (my_labels[i].downcase < other_labels[i].downcase) } return true end |
#downcase ⇒ Object
87 88 89 90 91 |
# File 'lib/Dnsruby/name.rb', line 87 def downcase labels = [] @labels.each do |label| labels << Label.new(label.downcase) end return Name.create(labels) end |
#hash ⇒ Object
:nodoc:
173 174 175 |
# File 'lib/Dnsruby/name.rb', line 173 def hash # :nodoc: return @labels.hash ^ @absolute.hash end |
#inspect ⇒ Object
:nodoc:
93 94 95 |
# File 'lib/Dnsruby/name.rb', line 93 def inspect # :nodoc: "#<#{self.class}: #{self.to_s}#{@absolute ? '.' : ''}>" end |
#length ⇒ Object
:nodoc: all
181 182 183 |
# File 'lib/Dnsruby/name.rb', line 181 def length #:nodoc: all return @labels.length end |
#strip_label ⇒ Object
:nodoc:
106 107 108 109 |
# File 'lib/Dnsruby/name.rb', line 106 def strip_label # :nodoc: n = Name.new(self.labels()[1, self.labels.length-1], self.absolute?) return n end |
#subdomain_of?(other) ⇒ Boolean
Tests subdomain-of relation : returns true if this name is a subdomain of other.
domain = Resolv::Name.create("y.z")
p Resolv::Name.create("w.x.y.z").subdomain_of?(domain) #=> true
p Resolv::Name.create("x.y.z").subdomain_of?(domain) #=> true
p Resolv::Name.create("y.z").subdomain_of?(domain) #=> false
p Resolv::Name.create("z").subdomain_of?(domain) #=> false
p Resolv::Name.create("x.y.z.").subdomain_of?(domain) #=> false
p Resolv::Name.create("w.z").subdomain_of?(domain) #=> false
165 166 167 168 169 170 171 |
# File 'lib/Dnsruby/name.rb', line 165 def subdomain_of?(other) raise ArgumentError, "not a domain name: #{other.inspect}" unless Name === other return false if @absolute != other.absolute? other_len = other.length return false if @labels.length <= other_len return @labels[-other_len, other_len] == other.to_a end |
#to_a ⇒ Object
:nodoc: all
177 178 179 |
# File 'lib/Dnsruby/name.rb', line 177 def to_a #:nodoc: all return @labels end |
#to_s ⇒ Object
199 200 201 |
# File 'lib/Dnsruby/name.rb', line 199 def to_s return @labels.collect{|l| (l.kind_of?String) ? l : l.string}.join('.') end |
#wild? ⇒ Boolean
Is this name a wildcard?
112 113 114 115 116 117 |
# File 'lib/Dnsruby/name.rb', line 112 def wild? if (labels.length == 0) return false end return (labels[0].string == '*') end |