pax_global_header00006660000000000000000000000064152134131660014514gustar00rootroot0000000000000052 comment=67614479d29a1ae1649280a24f9d571f1d0123d0 KimNorgaard-validates_hostname-6761447/000077500000000000000000000000001521341316600177665ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/.github/000077500000000000000000000000001521341316600213265ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/.github/workflows/000077500000000000000000000000001521341316600233635ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/.github/workflows/ci.yml000066400000000000000000000007101521341316600244770ustar00rootroot00000000000000name: CI on: push: tags: [v*] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest strategy: matrix: ruby-version: ["3.0", "3.1", "3.2", "3.3", "3.4"] steps: - uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true - name: Run tests run: bundle exec rspec KimNorgaard-validates_hostname-6761447/.github/workflows/release.yml000066400000000000000000000015111521341316600255240ustar00rootroot00000000000000name: Release on: push: tags: - "v[0-9]+.[0-9]+.[0-9]+*" jobs: release: name: Release to RubyGems.org runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout code uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ".ruby-version" - name: Configure RubyGems Credentials run: | mkdir -p $HOME/.gem touch $HOME/.gem/credentials chmod 0600 $HOME/.gem/credentials printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials env: GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }} - name: Build gem run: gem build *.gemspec - name: Push gem to RubyGems.org run: gem push *.gem KimNorgaard-validates_hostname-6761447/.github/workflows/tld-update.yml000066400000000000000000000036541521341316600261610ustar00rootroot00000000000000name: Automated TLD Update and Release on: schedule: - cron: "0 0 * * 0" workflow_dispatch: jobs: update_and_release: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v5 with: token: ${{ secrets.GH_PAT }} - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ".ruby-version" bundler-cache: true - name: Update TLD list from IANA run: bundle exec rake tlds:update - name: Check for changes id: git_diff run: | git diff --quiet data/tlds.txt || echo "changed=true" >> $GITHUB_OUTPUT - name: Configure Git if: steps.git_diff.outputs.changed == 'true' run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Bump version and push changes if: steps.git_diff.outputs.changed == 'true' run: | # Extract the current version string, e.g., '2.0.0' current_version=$(grep -oP "VERSION = '\K[^']+" lib/validates_hostname/version.rb) echo "Current version: $current_version" # Bump the patch version using Ruby new_version=$(ruby -e "v = '$current_version'.split('.'); v[-1] = v[-1].to_i + 1; puts v.join('.')") echo "New version: $new_version" # Update the version file sed -i "s/VERSION = '$current_version'/VERSION = '$new_version'/" lib/validates_hostname/version.rb # Commit the changes git add data/tlds.txt lib/validates_hostname/version.rb git commit -m "chore: Update TLD list and bump version to v${new_version}" -m "This is an automated commit." # Tag the new version git tag "v${new_version}" # Push the commit and the tag, triggering the release workflow git push origin main --tags KimNorgaard-validates_hostname-6761447/.gitignore000066400000000000000000000001631521341316600217560ustar00rootroot00000000000000/pkg/ /tmp/ *.gem .DS_Store .vscode/ .idea/ .env Gemfile.lock /.yardoc/ /doc/ /rdoc/ /.rspec_status coverage / KimNorgaard-validates_hostname-6761447/.rspec000066400000000000000000000000371521341316600211030ustar00rootroot00000000000000--format documentation --color KimNorgaard-validates_hostname-6761447/.rubocop.yml000066400000000000000000000011361521341316600222410ustar00rootroot00000000000000plugins: - rubocop-rake - rubocop-rspec AllCops: NewCops: enable Exclude: - "bin/*" - "db/**/*" - "config/**/*" - "script/**/*" - "vendor/**/*" - "tmp/**/*" - "node_modules/**/*" Metrics/MethodLength: Exclude: - "lib/validates_hostname.rb" Metrics/AbcSize: Exclude: - "lib/validates_hostname.rb" Metrics/CyclomaticComplexity: Exclude: - "lib/validates_hostname.rb" Metrics/PerceivedComplexity: Exclude: - "lib/validates_hostname.rb" Metrics/BlockLength: Exclude: - "spec/hostname_validator_spec.rb" - "validates_hostname.gemspec" KimNorgaard-validates_hostname-6761447/.ruby-version000066400000000000000000000000061521341316600224270ustar00rootroot000000000000003.4.6 KimNorgaard-validates_hostname-6761447/CHANGELOG.md000066400000000000000000000005711521341316600216020ustar00rootroot00000000000000# Changelog - 2.0.30 [2026-04-17] - fix i18n loading - 2.0.3 [2025-10-16] - allow to run with activemodel 8 - 2.0.0 [2025-09-22] - new major release - decouple from ActiveRecord and modernize for ActiveModel - 1.0.13 [2022-10-14] - allow for conditional validation, controlled with model method - 1.0.11 [2020-08-18] - fixes for ruby 2.7 - 1.0.0 [2011-01-12] - Initial commit KimNorgaard-validates_hostname-6761447/Gemfile000066400000000000000000000005631521341316600212650ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec group :development, :test do gem 'guard', '~> 2.19' gem 'guard-rspec', '~> 4.7' gem 'rake', '~> 13.0' gem 'rspec', '~> 3.13' gem 'rspec-collection_matchers', '~> 1.2' gem 'rubocop', '~> 1.80' gem 'rubocop-rake', '~> 0.7' gem 'rubocop-rspec', '~> 3.7' gem 'simplecov', '~> 0.21' end KimNorgaard-validates_hostname-6761447/Guardfile000066400000000000000000000005231521341316600216130ustar00rootroot00000000000000# frozen_string_literal: true guard :rspec, cmd: 'rbenv exec bundle exec rspec' do # Watch spec files watch(%r{^spec/.+_spec\.rb$}) # Watch lib files and run the corresponding spec watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } # Watch the spec_helper and run all specs watch('spec/spec_helper.rb') { 'spec' } end KimNorgaard-validates_hostname-6761447/LICENSE000066400000000000000000000020631521341316600207740ustar00rootroot00000000000000MIT License Copyright (c) 2009-2025 Kim Nørgaard Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. KimNorgaard-validates_hostname-6761447/README.md000066400000000000000000000164371521341316600212600ustar00rootroot00000000000000# ValidatesHostname [![Gem Version](https://badge.fury.io/rb/validates_hostname.svg)](https://badge.fury.io/rb/validates_hostname) [![CI](https://github.com/KimNorgaard/validates_hostname/actions/workflows/ci.yml/badge.svg)](https://github.com/KimNorgaard/validates_hostname/actions/workflows/ci.yml) ## Description Extension to ActiveModel for validating hostnames and domain names. ## Requirements - Ruby >= 3.0.0 - Active Model >= 6.0 ## Features - Adds validation for hostnames to ActiveModel - Supports I18n for the error messages ## Installation As a gem: ```bash # in Gemfile gem 'validates_hostname', '~> 2.0' # Run bundler bundle install ``` ## Validations Performed The following validations are performed on the hostname: - The maximum length of the hostname is 255 characters. - The maximum length of each hostname label is 63 characters. - The allowed characters in hostname labels are `a-z`, `A-Z`, `0-9` and hyphen (`-`). - Labels do not begin or end with a hyphen. - Labels do not consist of numeric values only. ## Options The validator can be configured with the following options: - `allow_underscore`: Allows for underscores in hostname labels. - `require_valid_tld`: Requires that the last label is a valid TLD. - `valid_tlds`: A list of valid TLDs. This option requires `require_valid_tld` to be `true`. - `allow_numeric_hostname`: Allows numeric values in the first label of the hostname. - `allow_wildcard_hostname`: Allows for a wildcard hostname in the first label. - `allow_root_label`: Allows for a trailing dot (root label) in the hostname. See also http://www.zytrax.com/books/dns/apa/names.html ## How to Use Simple usage: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: true end ``` With options: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { allow_underscore: true } end ``` ## Options and Their Defaults - `allow_underscore`: Permits underscore characters (`_`) in hostname labels. (default: `false`) - `require_valid_tld`: Ensures that the hostname's last label is a recognized Top-Level Domain (TLD). (default: `false`) - `valid_tlds`: An array of specific Top-Level Domains (TLDs) that are considered valid. This option requires `require_valid_tld` to be `true` to take effect. (default: List from `data/tlds.txt`) - `allow_numeric_hostname`: Allows hostname labels to consist solely of numeric digits (e.g., `123.example.com`). Note: A hostname cannot consist of a single numeric label (e.g., `123` is always invalid). (default: `false`) - `allow_wildcard_hostname`: Permits a wildcard character (`*`) as the first label of the hostname (e.g., `*.example.com`). (default: `false`) - `allow_root_label`: Permits a trailing dot (root label) in the hostname (e.g., `example.com.`). (default: `false`) ## Examples Without options: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: true end >> @record = Record.new(name: "horse") >> @record.save => true >> @record2 = Record.new(name: "_horse") >> @record2.save => false ``` With `:allow_underscore`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { allow_underscore: true } end >> @record3 = Record.new(name: "_horse") >> @record3.save => true ``` With `:require_valid_tld`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { require_valid_tld: true } end >> @record4 = Record.new(name: "horse") >> @record4.save => false >> @record5 = Record.new(name: "horse.com") >> @record5.save => true ``` With `:valid_tlds`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { require_valid_tld: true, valid_tlds: %w(com org net) } end >> @record6 = Record.new(name: "horse.info") >> @record6.save => false ``` With `:allow_numeric_hostname`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { allow_numeric_hostname: false } end >> @record7 = Record.new(name: "123.info") >> @record7.save => false ``` With `:allow_wildcard_hostname`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { allow_wildcard_hostname: true } end >> @record8 = Record.new(name: "*.123.info") >> @record8.save => true ``` With `:allow_root_label`: ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, hostname: { allow_root_label: true } end >> @record9 = Record.new(name: "example.com.") >> @record9.save => true ``` ## Extra Validators A few extra validators are included. ### domainname Sets `require_valid_tld` to `true`. Sets `allow_numeric_hostname` to `true`. This option cannot be changed by the user. Returns error if there is only one label and this label is numeric. ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, domainname: true end >> @record = Record.new(name: "123.com") >> @record.save => true >> @record2 = Record.new(name: "123") >> @record2.save => false ``` ### fqdn Sets `require_valid_tld` to `true`. ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, fqdn: true end >> @record = Record.new(name: "example.com") >> @record.save => true >> @record2 = Record.new(name: "example") >> @record2.save => false ``` ### wildcard Sets `allow_wildcard_hostname` to `true`. ```ruby class Record include ActiveModel::Validations attr_accessor :name def self.model_name ActiveModel::Name.new(self, nil, "Record") end validates :name, wildcard: true end >> @record = Record.new(name: "*.example.com") >> @record.save => true ``` ## Error Messages The gem uses the I18n system for error messages. You can provide your own translations in your application's locale files (e.g., `config/locales/en.yml`). Example of a custom error message in `config/locales/en.yml`: ```yaml en: errors: messages: invalid_hostname_length: "is not a valid hostname length" ``` The gem comes with the following built-in translations: - English (en) - Spanish (es) - German (de) - French (fr) - Simplified Chinese (zh) The `%{valid_chars}` interpolator is available for the `label_contains_invalid_characters` message. ## Maintainers - [Kim Nørgaard](mailto:jasen@jasen.dk) ## License Copyright (c) 2009-2025 Kim Nørgaard, released under the MIT license. KimNorgaard-validates_hostname-6761447/Rakefile000066400000000000000000000021171521341316600214340ustar00rootroot00000000000000# frozen_string_literal: true require 'bundler/gem_tasks' require 'net/http' require 'rspec/core/rake_task' require 'rubocop/rake_task' # Set the default task to run both specs and linting. task default: :ci # --- Testing Tasks --- desc 'Run RSpec tests' RSpec::Core::RakeTask.new(:spec) # --- Linting Tasks --- desc 'Run RuboCop for static analysis' RuboCop::RakeTask.new(:rubocop) # --- Continuous Integration Task --- desc 'Run all tests and linters' task ci: %i[spec rubocop] # --- Development Tasks --- desc 'Open an IRB console with the gem loaded' task :console do sh 'irb -Ilib -rvalidates_hostname' end # --- TLD Update Task --- namespace :tlds do desc 'Update the TLD list from IANA' task :update do uri = URI('http://data.iana.org/TLD/tlds-alpha-by-domain.txt') puts "Fetching latest TLDs from #{uri}..." begin response = Net::HTTP.get(uri) File.write('data/tlds.txt', response) puts 'Successfully updated data/tlds.txt.' rescue StandardError => e warn "An error occurred during TLD update: #{e.message}" exit 1 end end end KimNorgaard-validates_hostname-6761447/config/000077500000000000000000000000001521341316600212335ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/config/locales/000077500000000000000000000000001521341316600226555ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/config/locales/de.yml000066400000000000000000000014501521341316600237700ustar00rootroot00000000000000de: errors: messages: invalid_hostname_length: "muss zwischen 1 und 255 Zeichen lang sein" invalid_label_length: "muss zwischen 1 und 63 Zeichen lang sein" label_begins_or_ends_with_hyphen: "beginnt oder endet mit einem Bindestrich" label_contains_invalid_characters: "enthält ungültige Zeichen (gültige Zeichen: [%{valid_chars}])" hostname_label_is_numeric: "der nicht qualifizierte Hostname-Teil darf nicht nur aus numerischen Werten bestehen" hostname_is_not_fqdn: "ist kein vollqualifizierter Domainname" single_numeric_hostname_label: "darf nicht aus einem einzigen numerischen Label bestehen" hostname_contains_consecutive_dots: "darf keine aufeinanderfolgenden Punkte enthalten" hostname_ends_with_dot: "darf nicht mit einem Punkt enden" KimNorgaard-validates_hostname-6761447/config/locales/en.yml000066400000000000000000000013351521341316600240040ustar00rootroot00000000000000en: errors: messages: 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 a 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" KimNorgaard-validates_hostname-6761447/config/locales/es.yml000066400000000000000000000014041521341316600240060ustar00rootroot00000000000000es: errors: messages: invalid_hostname_length: "debe tener entre 1 y 255 caracteres" invalid_label_length: "debe tener entre 1 y 63 caracteres" label_begins_or_ends_with_hyphen: "comienza o termina con un guión" label_contains_invalid_characters: "contiene caracteres inválidos (caracteres válidos: [%{valid_chars}])" hostname_label_is_numeric: "la parte del nombre de host no calificada no puede consistir solo en valores numéricos" hostname_is_not_fqdn: "no es un nombre de dominio completo" single_numeric_hostname_label: "no puede consistir en una sola etiqueta numérica" hostname_contains_consecutive_dots: "no debe contener puntos consecutivos" hostname_ends_with_dot: "no debe terminar con un punto" KimNorgaard-validates_hostname-6761447/config/locales/fr.yml000066400000000000000000000014761521341316600240170ustar00rootroot00000000000000fr: errors: messages: invalid_hostname_length: "doit avoir entre 1 et 255 caractères" invalid_label_length: "doit avoir entre 1 et 63 caractères" label_begins_or_ends_with_hyphen: "commence ou se termine par un trait d'union" label_contains_invalid_characters: "contient des caractères non valides (caractères valides: [%{valid_chars}])" hostname_label_is_numeric: "la partie non qualifiée du nom d'hôte ne peut pas être constituée uniquement de valeurs numériques" hostname_is_not_fqdn: "n'est pas un nom de domaine complet" single_numeric_hostname_label: "ne peut pas consister en une seule étiquette numérique" hostname_contains_consecutive_dots: "ne doit pas contenir de points consécutifs" hostname_ends_with_dot: "ne doit pas se terminer par un point" KimNorgaard-validates_hostname-6761447/config/locales/zh.yml000066400000000000000000000012421521341316600240200ustar00rootroot00000000000000zh: errors: messages: invalid_hostname_length: "长度必须在 1 到 255 个字符之间" invalid_label_length: "长度必须在 1 到 63 个字符之间" label_begins_or_ends_with_hyphen: "以连字符开头或结尾" label_contains_invalid_characters: "包含无效字符 (有效字符: [%{valid_chars}])" hostname_label_is_numeric: "非限定主机名部分不能仅由数值组成" hostname_is_not_fqdn: "不是完全限定的域名" single_numeric_hostname_label: "不能由单个数字标签组成" hostname_contains_consecutive_dots: "不得包含连续的点" hostname_ends_with_dot: "不得以点结尾" KimNorgaard-validates_hostname-6761447/data/000077500000000000000000000000001521341316600206775ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/data/tlds.txt000066400000000000000000000224741521341316600224170ustar00rootroot00000000000000# Version 2026061300, Last Updated Sat Jun 13 07:07:02 2026 UTC AAA AARP ABB ABBOTT ABBVIE ABC ABLE ABOGADO ABUDHABI AC ACADEMY ACCENTURE ACCOUNTANT ACCOUNTANTS ACO ACTOR AD ADS ADULT AE AEG AERO AETNA AF AFL AFRICA AG AGAKHAN AGENCY AI AIG AIRBUS AIRFORCE AIRTEL AKDN AL ALIBABA ALIPAY ALLFINANZ ALLSTATE ALLY ALSACE ALSTOM AM AMAZON 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 AW AWS AX AXA AZ AZURE BA BABY BAIDU BANAMEX BAND BANK BAR BARCELONA BARCLAYCARD BARCLAYS BAREFOOT BARGAINS BASEBALL BASKETBALL BAUHAUS BAYERN BB BBC BBT BBVA BCG BCN BD BE BEATS BEAUTY BEER 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 BUILD BUILDERS BUSINESS BUY BUZZ BV BW BY BZ BZH CA CAB CAFE CAL CALL CALVINKLEIN CAM CAMERA CAMP CANON CAPETOWN CAPITAL CAPITALONE CAR CARAVAN CARDS CARE CAREER CAREERS CARS CASA CASE CASH CASINO CAT CATERING CATHOLIC CBA CBN CBRE CC CD 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 CK CL CLAIMS CLEANING CLICK CLINIC CLINIQUE CLOTHING CLOUD CLUB CLUBMED CM CN CO COACH CODES COFFEE COLLEGE COLOGNE COM COMMBANK COMMUNITY COMPANY COMPARE COMPUTER COMSEC CONDOS CONSTRUCTION CONSULTING CONTACT CONTRACTORS COOKING COOL COOP CORSICA COUNTRY COUPON COUPONS COURSES CPA CR CREDIT CREDITCARD CREDITUNION CRICKET CROWN CRS CRUISE CRUISES CU CUISINELLA CV CW CX CY CYMRU CYOU CZ 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 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 ET 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 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 FOOTBALL FORD FOREX FORSALE FORUM FOUNDATION FOX FR FREE FRESENIUS FRL FROGANS FRONTIER FTR FUJITSU 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 GLASS GLE GLOBAL GLOBO GM GMAIL GMBH GMO GMX GN GODADDY GOLD GOLDPOINT GOLF GOODYEAR GOOG GOOGLE GOP GOT GOV GP GQ GR GRAINGER GRAPHICS GRATIS GREEN GRIPE GROCERY GROUP GS GT GU GUCCI GUGE GUIDE GUITARS GURU GW GY HAIR HAMBURG HANGOUT HAUS HBO HDFC HDFCBANK HEALTH HEALTHCARE HELP HELSINKI HERE HERMES HIPHOP HISAMITSU HITACHI HIV HK HKT HM HN HOCKEY HOLDINGS HOLIDAY HOMEDEPOT HOMEGOODS HOMES HOMESENSE HONDA HORSE HOSPITAL HOST HOSTING HOT 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 INTERNATIONAL INTUIT INVESTMENTS IO IPIRANGA IQ IR IRISH IS ISMAILI IST ISTANBUL IT ITAU ITV JAGUAR JAVA JCB JE JEEP JETZT JEWELRY JIO JLL JM JMP JNJ JO JOBS JOBURG JOT JOY JP JPMORGAN JPRS JUEGOS JUNIPER KAUFEN KDDI KE KERRYHOTELS KERRYPROPERTIES KFH KG KH KI KIA KIDS KIM KINDLE KITCHEN KIWI KM KN KOELN KOMATSU KOSHER KP KPMG KPN KR KRD KRED KUOKGROUP KW KY KYOTO KZ LA LACAIXA LAMBORGHINI LAMER 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 LINK LIVE LIVING LK LLC LLP LOAN LOANS LOCKER LOCUS LOL LONDON LOTTE LOTTO LOVE LPL LPLFINANCIAL LR LS LT LTD LTDA LU LUNDBECK LUXE LUXURY LV LY MA MADRID MAIF MAISON MAKEUP MAN MANAGEMENT MANGO MAP MARKET MARKETING MARKETS MARRIOTT MARSHALLS MATTEL MBA MC MCKINSEY MD ME MED MEDIA MEET MELBOURNE MEME MEMORIAL MEN MENU MERCK MERCKMSD 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 MUSIC MV MW MX MY MZ NA NAB NAGOYA NAME NAVY NBA NC NE NEC NET NETBANK NETFLIX NETWORK NEUSTAR NEW NEWS NEXT NEXTDIRECT NEXUS NF NFL NG NGO NHK NI NICO NIKE NIKON NINJA NISSAN NISSAY NL NO NOKIA NORTON NOW NOWRUZ NOWTV NP NR NRA NRW NTT NU NYC NZ OBI OBSERVER OFFICE OKINAWA OLAYAN OLAYANGROUP OLLO OM OMEGA ONE ONG ONL ONLINE OOO OPEN ORACLE ORANGE ORG ORGANIC ORIGINS OSAKA OTSUKA OTT OVH PA PAGE PANASONIC PARIS PARS PARTNERS PARTS PARTY 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 PRAXI PRESS PRIME PRO PROD PRODUCTIONS PROF PROGRESSIVE PROMO PROPERTIES PROPERTY PROTECTION PRU PRUDENTIAL PS PT PUB PW PWC PY QA QPON QUEBEC QUEST RACING RADIO RE READ REALESTATE REALTOR REALTY RECIPES RED REDUMBRELLA REHAB REISE REISEN REIT RELIANCE REN RENT RENTALS REPAIR REPORT REPUBLICAN REST RESTAURANT REVIEW REVIEWS REXROTH RICH RICHARDLI RICOH RIL RIO RIP RO 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 SCB SCHAEFFLER SCHMIDT SCHOLARSHIPS SCHOOL SCHULE SCHWARZ SCIENCE SCOT SD SE SEARCH SEAT SECURE SECURITY SEEK SELECT SENER SERVICES SEVEN SEW SEX SEXY SFR SG SH SHANGRILA SHARP SHELL SHIA SHIKSHA SHOES SHOP SHOPPING SHOUJI SHOW 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 SPA SPACE SPORT SPOT 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 SWISS SX SY SYDNEY 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 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 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 VIVA VIVO VLAANDEREN VN VODKA VOLVO VOTE VOTING VOTO VOYAGE VU 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 WOODSIDE WORK WORKS WORLD WOW WS WTC WTF XBOX XEROX XIHUAN XIN XN--11B4C3D XN--1CK2E1B XN--1QQW23A XN--2SCRJ9C XN--30RR7Y XN--3BST00M XN--3DS443G XN--3E0B707E XN--3HCRJ9C XN--3PXU8K XN--42C2D9A XN--45BR5CYL XN--45BRJ9C XN--45Q11C XN--4DBRK0CE 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--CCKWCXETD XN--CG4BKI XN--CLCHC0EA0B2G2A9GCD XN--CZR694B XN--CZRS0T XN--CZRU2D XN--D1ACJ3B XN--D1ALF XN--E1A4C XN--ECKVDTC9D XN--EFVY88H 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--JLQ480N2RG XN--JVR189M XN--KCRX77D1X4A XN--KPRW13D XN--KPRY57D XN--KPUT3I XN--L1ACC XN--LGBBAT1AD8J XN--MGB9AWBF XN--MGBA3A3EJT XN--MGBA3A4F16A XN--MGBA7C0BBN0A 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--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 KimNorgaard-validates_hostname-6761447/lib/000077500000000000000000000000001521341316600205345ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/lib/validates_hostname.rb000066400000000000000000000210471521341316600247370ustar00rootroot00000000000000# frozen_string_literal: true require 'active_model' require 'set' require_relative 'validates_hostname/version' module ValidatesHostname # Handles TLD list loading and management. module Tld # List from IANA: http://www.iana.org/domains/root/db/ # http://data.iana.org/TLD/tlds-alpha-by-domain.txt def self.load_tlds tlds_file_path = File.expand_path('../data/tlds.txt', __dir__) Set.new(File.readlines(tlds_file_path) .map(&:strip) .map(&:downcase) .reject { |line| line.start_with?('#') || line.empty? }) .add('.') .freeze end ALLOWED_TLDS = load_tlds end end ALLOWED_TLDS = ValidatesHostname::Tld::ALLOWED_TLDS # Validates hostnames. class HostnameValidator < ActiveModel::EachValidator # @param [Hash] options # @option options [Boolean] :allow_underscore (false) Allows underscores in hostname labels. # @option options [Boolean] :require_valid_tld (false) Requires the hostname to have a valid TLD. # @option options [Array] :valid_tlds (ALLOWED_TLDS) A list of valid TLDs. # @option options [Boolean] :allow_numeric_hostname (false) Allows numeric-only hostname labels. # @option options [Boolean] :allow_wildcard_hostname (false) Allows wildcard hostnames. # @option options [Boolean] :allow_root_label (false) Allows a trailing dot. def initialize(options) super({ 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)) end # Validates the hostname. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [String] value The value to validate. def validate_each(record, attribute, value) value = value.to_s labels = value.split('.') validate_hostname_length(record, attribute, value) # CHECK 1: hostname label cannot be longer than 63 characters validate_label_length(record, attribute, labels) # CHECK 2: hostname label cannot begin or end with hyphen validate_label_hyphens(record, attribute, labels) # CHECK 3: hostname can only contain valid characters validate_label_characters(record, attribute, labels) # CHECK 4: the unqualified hostname portion cannot consist of numeric values only validate_numeric_hostname(record, attribute, labels) # CHECK 5: TLD must be valid if required handle_tld_validation(record, attribute, value, labels) # CHECK 6: hostname may not contain consecutive dots validate_consecutive_dots(record, attribute, value) # CHECK 7: do not allow trailing dot unless option is set validate_trailing_dot(record, attribute, value) end private # Validates the length of the hostname. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [String] value The value to validate. def validate_hostname_length(record, attribute, value) # maximum hostname length: 255 characters return if value.length.between?(1, 255) add_error(record, attribute, :invalid_hostname_length) end # Validates the length of each label in the hostname. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [Array] labels The labels to validate. def validate_label_length(record, attribute, labels) labels.each do |label| add_error(record, attribute, :invalid_label_length) unless label.length.between?(1, 63) end end # Validates that no label begins or ends with a hyphen. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [Array] labels The labels to validate. def validate_label_hyphens(record, attribute, labels) labels.each do |label| add_error(record, attribute, :label_begins_or_ends_with_hyphen) if label.start_with?('-') || label.end_with?('-') end end # Validates the characters in each label of the hostname. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [Array] labels The labels to validate. def validate_label_characters(record, attribute, labels) labels.each_with_index do |label, index| next if options[:allow_wildcard_hostname] && label == '*' && index.zero? valid_chars = 'a-z0-9\-' valid_chars += '_' if options[:allow_underscore] unless label.match?(/^[#{valid_chars}]+$/i) add_error(record, attribute, :label_contains_invalid_characters, valid_chars: valid_chars.delete('\\')) end end end # Validates that the hostname is not numeric. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [Array] labels The labels to validate. def validate_numeric_hostname(record, attribute, labels) return unless !options[:allow_numeric_hostname] && !labels.empty? && labels.first.match?(/\A\d+\z/) add_error(record, attribute, :hostname_label_is_numeric) end # Validates that the hostname does not contain consecutive dots. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [String] value The value to validate. def validate_consecutive_dots(record, attribute, value) return unless value.include?('..') add_error(record, attribute, :hostname_contains_consecutive_dots) end # Validates that the hostname does not end with a dot. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [String] value The value to validate. def validate_trailing_dot(record, attribute, value) return unless !options[:allow_root_label] && value.end_with?('.') add_error(record, attribute, :hostname_ends_with_dot) end # Handles the TLD validation. # # @param [ActiveModel::Base] record The record to validate. # @param [Symbol] attribute The attribute to validate. # @param [String] value The value to validate. # @param [Array] labels The labels to validate. def handle_tld_validation(record, attribute, value, labels) require_valid_tld = options[:require_valid_tld] require_valid_tld = record.send(require_valid_tld) if require_valid_tld.is_a?(Symbol) return unless require_valid_tld tld = (value == '.' ? value : labels.last) || '' return if options[:valid_tlds].any? { |v| v.casecmp?(tld) } add_error(record, attribute, :hostname_is_not_fqdn) end # Adds an error to the record. # # @param [ActiveModel::Base] record The record to add the error to. # @param [Symbol] attr_name The attribute to add the error to. # @param [Symbol] message The error message. # @param [Hash] interpolators The interpolators for the error message. def add_error(record, attr_name, message, interpolators = {}) # Use the custom message if provided in the options, otherwise use the # symbolic message key for I18n lookup. custom_message = options[:message] record.errors.add(attr_name, custom_message || message, **interpolators) end end # Validates domain names. class DomainnameValidator < HostnameValidator def initialize(options) # The :domainname validator intentionally sets allow_numeric_hostname to true. # This behavior cannot be overridden by the user. super({ require_valid_tld: true, allow_numeric_hostname: true }.merge(options)) end def validate_each(record, attribute, value) super return unless value.is_a?(String) labels = value.split('.') # CHECK 1: if there is only one label it cannot be numeric return unless labels.first.match?(/\A\d+\z/) && labels.size == 1 add_error(record, attribute, :single_numeric_hostname_label) end end # Validates fully qualified domain names. class FqdnValidator < HostnameValidator def initialize(options) super({ require_valid_tld: true }.merge(options)) end end # Validates wildcard hostnames. class WildcardValidator < HostnameValidator def initialize(options) super({ allow_wildcard_hostname: true }.merge(options)) end end if defined?(Rails) module ValidatesHostname # Railtie to automatically load I18n translations. class Railtie < Rails::Railtie initializer 'validates_hostname.i18n' do I18n.load_path += Dir[File.expand_path('../config/locales/*.yml', __dir__)] end end end end KimNorgaard-validates_hostname-6761447/lib/validates_hostname/000077500000000000000000000000001521341316600244065ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/lib/validates_hostname/version.rb000066400000000000000000000001211521341316600264120ustar00rootroot00000000000000# frozen_string_literal: true module ValidatesHostname VERSION = '2.0.39' end KimNorgaard-validates_hostname-6761447/spec/000077500000000000000000000000001521341316600207205ustar00rootroot00000000000000KimNorgaard-validates_hostname-6761447/spec/hostname_validator_spec.rb000066400000000000000000000136161521341316600261510ustar00rootroot00000000000000# frozen_string_literal: true require 'spec_helper' RSpec.describe HostnameValidator do let(:test_class) do Class.new do include ActiveModel::Validations attr_accessor :hostname # This is necessary for ActiveModel to work with an anonymous class def self.model_name ActiveModel::Name.new(self, nil, 'TestModel') end end end let(:record) { test_class.new } RSpec.shared_examples 'a valid hostname' do |hostname| it "is valid with #{hostname}" do record.hostname = hostname expect(record).to be_valid end end RSpec.shared_examples 'an invalid hostname' do |hostname| it "is invalid with #{hostname}" do record.hostname = hostname expect(record).to be_invalid end end describe 'with default options' do before { test_class.validates :hostname, hostname: true } it_behaves_like 'a valid hostname', 'example.com' it_behaves_like 'a valid hostname', 'example-hyphen.com' it_behaves_like 'a valid hostname', 'a' it_behaves_like 'a valid hostname', "#{'a' * 63}.com" it_behaves_like 'a valid hostname', "#{'a' * 60}.#{'b' * 60}.#{'c' * 60}.#{'d' * 59}.com" # 245 chars total it 'is invalid with underscores' do record.hostname = '_example.com' expect(record).to be_invalid end it 'is invalid if a label ends with a hyphen' do record.hostname = 'example-.com' expect(record).to be_invalid end it 'is invalid if a label begins with a hyphen' do record.hostname = '-example.com' expect(record).to be_invalid end it 'is invalid with consecutive dots' do record.hostname = 'example..com' expect(record).to be_invalid end it 'is invalid with a trailing dot' do record.hostname = 'example.com.' expect(record).to be_invalid end it 'is invalid with a numeric-only label' do record.hostname = '12345.com' expect(record).to be_invalid end it 'is invalid with a wildcard' do record.hostname = '*.example.com' expect(record).to be_invalid end it 'is invalid if it is too long (256 chars)' do record.hostname = 'a' * 256 expect(record).to be_invalid end it 'is invalid if a label is too long (64 chars)' do record.hostname = "#{'a' * 64}.com" expect(record).to be_invalid end it 'is invalid with leading/trailing whitespace' do record.hostname = ' example.com ' expect(record).to be_invalid end it 'is invalid if blank' do record.hostname = '' expect(record).to be_invalid end it 'is invalid if nil' do record.hostname = nil expect(record).to be_invalid end it 'is invalid if a single dot' do record.hostname = '.' expect(record).to be_invalid end it 'is invalid with special characters' do %w[; : * ^ ~ + ' ! # " % & / ( ) = ? $ \\].each do |char| record.hostname = "#{char}example.com" expect(record).to be_invalid end end end describe 'with fqdn: true' do before { test_class.validates :hostname, fqdn: true } it_behaves_like 'a valid hostname', 'example.com' it_behaves_like 'an invalid hostname', 'example' end describe 'with wildcard: true' do before { test_class.validates :hostname, wildcard: true } it_behaves_like 'a valid hostname', '*.example.com' end describe 'with allow_underscore: true' do before { test_class.validates :hostname, hostname: { allow_underscore: true } } it_behaves_like 'a valid hostname', '_example.com' end describe 'with require_valid_tld: true' do before { test_class.validates :hostname, hostname: { require_valid_tld: true } } it_behaves_like 'a valid hostname', 'example.com' it_behaves_like 'an invalid hostname', 'example.invalidtld' end describe 'with valid_tlds: %w[test]' do before { test_class.validates :hostname, hostname: { require_valid_tld: true, valid_tlds: %w[test] } } it_behaves_like 'a valid hostname', 'example.test' it_behaves_like 'an invalid hostname', 'example.com' end describe 'with allow_numeric_hostname: true' do before { test_class.validates :hostname, hostname: { allow_numeric_hostname: true } } it_behaves_like 'a valid hostname', '12345.com' end describe 'with allow_wildcard_hostname: true' do before { test_class.validates :hostname, hostname: { allow_wildcard_hostname: true } } it_behaves_like 'a valid hostname', '*.example.com' end describe 'with allow_root_label: true' do before { test_class.validates :hostname, hostname: { allow_root_label: true } } it_behaves_like 'a valid hostname', 'example.com.' it_behaves_like 'a valid hostname', '.' end describe 'domainname validation' do before { test_class.validates :hostname, domainname: true } it_behaves_like 'a valid hostname', '12345.com' it_behaves_like 'an invalid hostname', '12345' end describe 'with allow_blank: true' do before { test_class.validates :hostname, hostname: { allow_blank: true } } it_behaves_like 'a valid hostname', '' end describe 'with allow_nil: true' do before { test_class.validates :hostname, hostname: { allow_nil: true } } it_behaves_like 'a valid hostname', nil end describe 'with a custom message' do before { test_class.validates :hostname, hostname: { message: 'is a custom message' } } it 'returns the custom error message' do record.hostname = '-example.com' record.valid? expect(record.errors[:hostname]).to include('is a custom message') end end describe 'I18n' do before do test_class.validates :hostname, hostname: true I18n.locale = :es end after do I18n.locale = :en end it 'returns the translated error message' do record.hostname = '-example.com' record.valid? expect(record.errors[:hostname]).to include('comienza o termina con un guión') end end end KimNorgaard-validates_hostname-6761447/spec/spec_helper.rb000066400000000000000000000014261521341316600235410ustar00rootroot00000000000000# frozen_string_literal: true require 'simplecov' SimpleCov.start require 'rspec/core' require 'bundler/setup' require 'active_model' require 'rspec/collection_matchers' require 'validates_hostname' I18n.load_path += Dir[File.expand_path('../config/locales/*.yml', __dir__)] RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = '.rspec_status' # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! config.expect_with :rspec do |c| c.syntax = :expect end # Run specs in random order to surface order dependencies. config.order = :random # Allows you to focus on a single test by adding `, :focus` config.filter_run_when_matching :focus end KimNorgaard-validates_hostname-6761447/validates_hostname.gemspec000066400000000000000000000015331521341316600252070ustar00rootroot00000000000000# frozen_string_literal: true # stub: validates_hostname 2.0.0 ruby lib Gem::Specification.new do |s| s.name = 'validates_hostname' s.version = '2.0.30' s.required_ruby_version = '>= 3.0.0' s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version= s.require_paths = ['lib'] s.authors = ['Kim Nøgaard'] s.description = 'Extension to ActiveModel for validating hostnames' s.email = 'jasen@jasen.dk' s.extra_rdoc_files = ['README.md', 'CHANGELOG.md', 'LICENSE'] s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } s.homepage = 'https://github.com/KimNorgaard/validates_hostname' s.licenses = ['MIT'] s.summary = 'Checks for valid hostnames' s.add_dependency('activemodel', ['>= 6.0', '< 9']) s.metadata['rubygems_mfa_required'] = 'true' end