1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 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 266 267 268 269 270 271 272 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
|
require 'active_support/concern'
require 'active_record'
require 'active_model'
module PAK
module ValidatesHostname
autoload :VERSION, 'validates_hostname/version'
# List from IANA: http://www.iana.org/domains/root/db/
# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
ALLOWED_TLDS = %w(
. aaa aarp abarth abb abbott abbvie abc able abogado abudhabi ac academy
accenture accountant accountants aco actor ad adac ads adult ae aeg aero
aetna af afamilycompany afl africa ag agakhan agency ai aig aigo airbus
airforce airtel akdn al alfaromeo alibaba alipay allfinanz allstate ally
alsace alstom am americanexpress americanfamily amex amfam amica amsterdam
analytics android anquan anz ao aol apartments app apple aq aquarelle ar
arab aramco archi army arpa art arte as asda asia associates at athleta
attorney au auction audi audible audio auspost author auto autos avianca aw
aws ax axa az azure ba baby baidu banamex bananarepublic band bank bar
barcelona barclaycard barclays barefoot bargains baseball basketball bauhaus
bayern bb bbc bbt bbva bcg bcn bd be beats beauty beer bentley berlin best
bestbuy bet bf bg bh bharti bi bible bid bike bing bingo bio biz bj black
blackfriday blockbuster blog bloomberg blue bm bms bmw bn bnpparibas bo
boats boehringer bofa bom bond boo book booking bosch bostik boston bot
boutique box br bradesco bridgestone broadway broker brother brussels bs bt
budapest bugatti build builders business buy buzz bv bw by bz bzh ca cab
cafe cal call calvinklein cam camera camp cancerresearch canon capetown
capital capitalone car caravan cards care career careers cars casa case
caseih cash casino cat catering catholic cba cbn cbre cbs cc cd ceb center
ceo cern cf cfa cfd cg ch chanel channel charity chase chat cheap chintai
christmas chrome church ci cipriani circle cisco citadel citi citic city
cityeats ck cl claims cleaning click clinic clinique clothing cloud club
clubmed cm cn co coach codes coffee college cologne com comcast commbank
community company compare computer comsec condos construction consulting
contact contractors cooking cookingchannel cool coop corsica country coupon
coupons courses cpa cr credit creditcard creditunion cricket crown crs
cruise cruises csc cu cuisinella cv cw cx cy cymru cyou cz dabur dad dance
data date dating datsun day dclk dds de deal dealer deals degree delivery
dell deloitte delta democrat dental dentist desi design dev dhl diamonds
diet digital direct directory discount discover dish diy dj dk dm dnp do
docs doctor dog domains dot download drive dtv dubai duck dunlop dupont
durban dvag dvr dz earth eat ec eco edeka edu education ee eg email emerck
energy engineer engineering enterprises epson equipment er ericsson erni
es esq estate esurance et etisalat eu eurovision eus events exchange
expert exposed express extraspace fage fail fairwinds faith family fan
fans farm farmers fashion fast fedex feedback ferrari ferrero fi fiat
fidelity fido film final finance financial fire firestone firmdale fish
fishing fit fitness fj fk flickr flights flir florist flowers fly fm fo
foo food foodnetwork football ford forex forsale forum foundation fox fr
free fresenius frl frogans frontdoor frontier ftr fujitsu fujixerox fun
fund furniture futbol fyi ga gal gallery gallo gallup game games gap
garden gay gb gbiz gd gdn ge gea gent genting george gf gg ggee gh gi gift
gifts gives giving gl glade glass gle global globo gm gmail gmbh gmo gmx
gn godaddy gold goldpoint golf goo goodyear goog google gop got gov gp gq
gr grainger graphics gratis green gripe grocery group gs gt gu guardian
gucci guge guide guitars guru gw gy hair hamburg hangout haus hbo hdfc
hdfcbank health healthcare help helsinki here hermes hgtv hiphop hisamitsu
hitachi hiv hk hkt hm hn hockey holdings holiday homedepot homegoods homes
homesense honda horse hospital host hosting hot hoteles hotels hotmail
house how hr hsbc ht hu hughes hyatt hyundai ibm icbc ice icu id ie ieee
ifm ikano il im imamat imdb immo immobilien in inc industries infiniti
info ing ink institute insurance insure int intel international intuit
investments io ipiranga iq ir irish is ismaili ist istanbul it itau itv
iveco jaguar java jcb jcp je jeep jetzt jewelry jio jll jm jmp jnj jo jobs
joburg jot joy jp jpmorgan jprs juegos juniper kaufen kddi ke kerryhotels
kerrylogistics kerryproperties kfh kg kh ki kia kim kinder kindle kitchen
kiwi km kn koeln komatsu kosher kp kpmg kpn kr krd kred kuokgroup kw ky
kyoto kz la lacaixa lamborghini lamer lancaster lancia land landrover
lanxess lasalle lat latino latrobe law lawyer lb lc lds lease leclerc
lefrak legal lego lexus lgbt li lidl life lifeinsurance lifestyle lighting
like lilly limited limo lincoln linde link lipsy live living lixil lk llc
llp loan loans locker locus loft lol london lotte lotto love lpl
lplfinancial lr ls lt ltd ltda lu lundbeck lupin luxe luxury lv ly ma
macys madrid maif maison makeup man management mango map market marketing
markets marriott marshalls maserati mattel mba mc mckinsey md me med media
meet melbourne meme memorial men menu merckmsd metlife mg mh miami
microsoft mil mini mint mit mitsubishi mk ml mlb mls mm mma mn mo mobi
mobile moda moe moi mom monash money monster mormon mortgage moscow moto
motorcycles mov movie mp mq mr ms msd mt mtn mtr mu museum mutual mv mw mx
my mz na nab nadex nagoya name nationwide natura navy nba nc ne nec net
netbank netflix network neustar new newholland news next nextdirect nexus
nf nfl ng ngo nhk ni nico nike nikon ninja nissan nissay nl no nokia
northwesternmutual norton now nowruz nowtv np nr nra nrw ntt nu nyc nz obi
observer off office okinawa olayan olayangroup oldnavy ollo om omega one
ong onl online onyourside ooo open oracle orange org organic origins osaka
otsuka ott ovh pa page panasonic paris pars partners parts party passagens
pay pccw pe pet pf pfizer pg ph pharmacy phd philips phone photo
photography photos physio pics pictet pictures pid pin ping pink pioneer
pizza pk pl place play playstation plumbing plus pm pn pnc pohl poker
politie porn post pr pramerica praxi press prime pro prod productions prof
progressive promo properties property protection pru prudential ps pt pub
pw pwc py qa qpon quebec quest qvc racing radio raid re read realestate
realtor realty recipes red redstone redumbrella rehab reise reisen reit
reliance ren rent rentals repair report republican rest restaurant review
reviews rexroth rich richardli ricoh rightathome ril rio rip rmit ro
rocher rocks rodeo rogers room rs rsvp ru rugby ruhr run rw rwe ryukyu sa
saarland safe safety sakura sale salon samsclub samsung sandvik
sandvikcoromant sanofi sap sarl sas save saxo sb sbi sbs sc sca scb
schaeffler schmidt scholarships school schule schwarz science scjohnson
scor scot sd se search seat secure security seek select sener services ses
seven sew sex sexy sfr sg sh shangrila sharp shaw shell shia shiksha shoes
shop shopping shouji show showtime shriram si silk sina singles site sj sk
ski skin sky skype sl sling sm smart smile sn sncf so soccer social
softbank software sohu solar solutions song sony soy space sport spot
spreadbetting sr srl ss st stada staples star statebank statefarm stc
stcgroup stockholm storage store stream studio study style su sucks
supplies supply support surf surgery suzuki sv swatch swiftcover swiss sx
sy sydney symantec systems sz tab taipei talk taobao target tatamotors
tatar tattoo tax taxi tc tci td tdk team tech technology tel temasek
tennis teva tf tg th thd theater theatre tiaa tickets tienda tiffany tips
tires tirol tj tjmaxx tjx tk tkmaxx tl tm tmall tn to today tokyo tools
top toray toshiba total tours town toyota toys tr trade trading training
travel travelchannel travelers travelersinsurance trust trv tt tube tui
tunes tushu tv tvs tw tz ua ubank ubs ug uk unicom university uno uol ups
us uy uz va vacations vana vanguard vc ve vegas ventures verisign
versicherung vet vg vi viajes video vig viking villas vin vip virgin visa
vision vistaprint viva vivo vlaanderen vn vodka volkswagen volvo vote
voting voto voyage vu vuelos wales walmart walter wang wanggou watch
watches weather weatherchannel webcam weber website wed wedding weibo weir
wf whoswho wien wiki williamhill win windows wine winners wme
wolterskluwer woodside work works world wow ws wtc wtf xbox xerox xfinity
xihuan xin xn--11b4c3d xn--1ck2e1b xn--1qqw23a xn--2scrj9c xn--30rr7y
xn--3bst00m xn--3ds443g xn--3e0b707e xn--3hcrj9c xn--3oq18vl8pn36a
xn--3pxu8k xn--42c2d9a xn--45br5cyl xn--45brj9c xn--45q11c xn--4gbrim
xn--54b7fta0cc xn--55qw42g xn--55qx5d xn--5su34j936bgsg xn--5tzm5g
xn--6frz82g xn--6qq986b3xl xn--80adxhks xn--80ao21a xn--80aqecdr1a
xn--80asehdb xn--80aswg xn--8y0a063a xn--90a3ac xn--90ae xn--90ais
xn--9dbq2a xn--9et52u xn--9krt00a xn--b4w605ferd xn--bck1b9a5dre4c
xn--c1avg xn--c2br7g xn--cck2b3b xn--cg4bki xn--clchc0ea0b2g2a9gcd
xn--czr694b xn--czrs0t xn--czru2d xn--d1acj3b xn--d1alf xn--e1a4c
xn--eckvdtc9d xn--efvy88h xn--estv75g xn--fct429k xn--fhbei xn--fiq228c5hs
xn--fiq64b xn--fiqs8s xn--fiqz9s xn--fjq720a xn--flw351e xn--fpcrj9c3d
xn--fzc2c9e2c xn--fzys8d69uvgm xn--g2xx48c xn--gckr3f0f xn--gecrj9c
xn--gk3at1e xn--h2breg3eve xn--h2brj9c xn--h2brj9c8c xn--hxt814e
xn--i1b6b1a6a2e xn--imr513n xn--io0a7i xn--j1aef xn--j1amh xn--j6w193g
xn--jlq61u9w7b xn--jvr189m xn--kcrx77d1x4a xn--kprw13d xn--kpry57d
xn--kpu716f xn--kput3i xn--l1acc xn--lgbbat1ad8j xn--mgb9awbf
xn--mgba3a3ejt xn--mgba3a4f16a xn--mgba7c0bbn0a xn--mgbaakc7dvf
xn--mgbaam7a8h xn--mgbab2bd xn--mgbah1a3hjkrd xn--mgbai9azgqp6j
xn--mgbayh7gpa xn--mgbbh1a xn--mgbbh1a71e xn--mgbc0a9azcg xn--mgbca7dzdo
xn--mgbcpq6gpa1a xn--mgberp4a5d4ar xn--mgbgu82a xn--mgbi4ecexp
xn--mgbpl2fh xn--mgbt3dhd xn--mgbtx2b xn--mgbx4cd0ab xn--mix891f
xn--mk1bu44c xn--mxtq1m xn--ngbc5azd xn--ngbe9e0a xn--ngbrx xn--node
xn--nqv7f xn--nqv7fs00ema xn--nyqy26a xn--o3cw4h xn--ogbpf8fl xn--otu796d
xn--p1acf xn--p1ai xn--pbt977c xn--pgbs0dh xn--pssy2u xn--q7ce6a
xn--q9jyb4c xn--qcka1pmc xn--qxa6a xn--qxam xn--rhqv96g xn--rovu88b
xn--rvc1e0am3e xn--s9brj9c xn--ses554g xn--t60b56a xn--tckwe xn--tiq49xqyj
xn--unup4y xn--vermgensberater-ctb xn--vermgensberatung-pwb xn--vhquv
xn--vuq861b xn--w4r85el8fhu5dnra xn--w4rs40l xn--wgbh1c xn--wgbl6a
xn--xhq521b xn--xkc2al3hye2a xn--xkc2dl3a5ee0h xn--y9a3aq xn--yfro4i67o
xn--ygbi2ammx xn--zfr164b xxx xyz yachts yahoo yamaxun yandex ye yodobashi
yoga yokohama you youtube yt yun za zappos zara zero zip zm zone zuerich
zw
)
DEFAULT_ERROR_MSG = {
:invalid_hostname_length => 'must be between 1 and 255 characters long',
:invalid_label_length => 'must be between 1 and 63 characters long',
:label_begins_or_ends_with_hyphen => 'begins or ends with hyphen',
:label_contains_invalid_characters => "contains invalid characters (valid characters: [%{valid_chars}])",
:hostname_label_is_numeric => 'unqualified hostname part cannot consist of numeric values only',
:hostname_is_not_fqdn => 'is not a fully qualified domain name',
:single_numeric_hostname_label => 'cannot consist of a single numeric label',
:hostname_contains_consecutive_dots => 'must not contain consecutive dots',
:hostname_ends_with_dot => 'must not end with a dot'
}.freeze
class HostnameValidator < ActiveModel::EachValidator
def initialize(options)
opts = {
:allow_underscore => false,
:require_valid_tld => false,
:valid_tlds => ALLOWED_TLDS,
:allow_numeric_hostname => false,
:allow_wildcard_hostname => false,
:allow_root_label => false
}.merge(options)
super(opts)
end
def validate_each(record, attribute, value)
value ||= ''
# maximum hostname length: 255 characters
add_error(record, attribute, :invalid_hostname_length) unless value.length.between?(1, 255)
# split each hostname into labels and do various checks
if value.is_a?(String)
labels = value.split '.'
labels.each_with_index do |label, index|
# CHECK 1: hostname label cannot be longer than 63 characters
add_error(record, attribute, :invalid_label_length) unless label.length.between?(1, 63)
# CHECK 2: hostname label cannot begin or end with hyphen
add_error(record, attribute, :label_begins_or_ends_with_hyphen) if label =~ /^[-]/i or label =~ /[-]$/
# Take care of wildcard first label
next if options[:allow_wildcard_hostname] and label == '*' and index == 0
# CHECK 3: hostname can only contain characters:
# a-z, 0-9, hyphen, optional underscore, optional asterisk
valid_chars = 'a-z0-9\-'
valid_chars << '_' if options[:allow_underscore] == true
add_error(record, attribute, :label_contains_invalid_characters, :valid_chars => valid_chars) unless label =~ /^[#{valid_chars}]+$/i
end
# CHECK 4: the unqualified hostname portion cannot consist of
# numeric values only
if options[:allow_numeric_hostname] == false and labels.length > 0
is_numeric_only = labels[0] =~ /\A\d+\z/
add_error(record, attribute, :hostname_label_is_numeric) if is_numeric_only
end
# CHECK 5: in order to be fully qualified, the full hostname's
# TLD must be valid
require_valid_tld = options[:require_valid_tld]
require_valid_tld = record.send(require_valid_tld) if require_valid_tld.is_a?(Symbol)
if require_valid_tld
my_tld = value == '.' ? value : labels.last
my_tld ||= ''
has_tld = options[:valid_tlds].select {
|tld| tld =~ /^#{Regexp.escape(my_tld)}$/i
}.empty? ? false : true
add_error(record, attribute, :hostname_is_not_fqdn) unless has_tld
end
# CHECK 6: hostname may not contain consecutive dots
if value =~ /\.\./
add_error(record, attribute, :hostname_contains_consecutive_dots)
end
# CHECK 7: do not allow trailing dot unless option is set
if options[:allow_root_label] == false
if value =~ /\.$/
add_error(record, attribute, :hostname_ends_with_dot)
end
end
end
end
def add_error(record, attr_name, message, *interpolators)
args = {
:default => [DEFAULT_ERROR_MSG[message], options[:message]],
:scope => [:errors, :messages]
}.merge(interpolators.last.is_a?(Hash) ? interpolators.pop : {})
record.errors.add(attr_name, I18n.t( message, **args ))
end
end
class DomainnameValidator < HostnameValidator
def initialize(options)
opts = {
:require_valid_tld => true,
:allow_numeric_hostname => true
}.merge(options)
super(opts)
end
def validate_each(record, attribute, value)
super
if value.is_a?(String)
labels = value.split '.'
# CHECK 1: if there is only one label it cannot be numeric even
# though numeric hostnames are allowed
if options[:allow_numeric_hostname] == true
is_numeric_only = labels[0] =~ /\A\d+\z/
if is_numeric_only and labels.size == 1
add_error(record, attribute, :single_numeric_hostname_label)
end
end
end
end
def add_error(record, attr_name, message, *interpolators)
args = {
:default => [DEFAULT_ERROR_MSG[message], options[:message]],
:scope => [:errors, :messages]
}.merge(interpolators.last.is_a?(Hash) ? interpolators.pop : {})
record.errors.add(attr_name, I18n.t( message, **args ))
end
end
class FqdnValidator < HostnameValidator
def initialize(options)
opts = {
:require_valid_tld => true,
}.merge(options)
super(opts)
end
end
class WildcardValidator < HostnameValidator
def initialize(options)
opts = {
:allow_wildcard_hostname => true,
}.merge(options)
super(opts)
end
end
end
end
ActiveRecord::Base.send(:include, PAK::ValidatesHostname)
|