diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..c656199e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.neon] +indent_size = 2 + +[*.xml.dist] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dc59f075 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +* text=auto + +/.editorconfig export-ignore +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/.php-cs-fixer.php export-ignore +/phpstan.neon export-ignore +/phpunit.xml.dist export-ignore +/psalm.xml export-ignore +/test_data/ export-ignore +/CHANGELOG.md export-ignore +/UPGRADING.md export-ignore +/README.md export-ignore +/**/*Test.php export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..ec9a71c7 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +## Bug Report + +We accept bug reports via issues created on [Github](https://github.com/jeremykendall/php-domain-parser/issues). + +### Prior to submitting your report + +- **Always search the issue or pull request list first** - The odds are good that if you've found a problem, someone else has found it, too. + +- **Always try the [master branch](https://github.com/jeremykendall/php-domain-parser/tree/master)** - to see if the reported bug has not already been fixed. + +### When submitting your report + +- **Open a new bug report for each issue.** + +- **Write a clear summary in english** - A good summary should quickly and uniquely identify a bug report. It should explain the problem, not your suggested solution. + +- **Be brief, but don't leave any important details out** - Tell us what you did, what you expected to happen, and what happened. Do not forget to mention your PHP version, the OS Platform and the package version you were using. + +## Pull Request + +We accept contributions via Pull Requests on [Github](https://github.com/jeremykendall/php-domain-parser/pull). + +- **Always make your Pull Request against the [master branch](https://github.com/jeremykendall/php-domain-parser/tree/master)** + +- **[PSR-2 Coding Standard](http://www.php-fig.org/psr/psr-2/)** - Your patch won't be accepted if it doesn't pass the package coding style test suite. + +You can resolve most of the styling code issues using the following command line: + +```bash +$ ./vendor/bin/php-cs-fixer fix -vvv --allow-risky=yes +``` + +You should run this command **prior** to committing your code. + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option. + +- **Create topic branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..70fdf4b1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [nyamsprod] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..b52aa102 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,22 @@ +## Issue summary + +_(Please explain in plain english your issue)_ + +### System informations + +_(In case of a bug report Please complete the table below)_ + +| Information | Description | +|--------------|---------| +| Pdp version | | +| PHP version | | +| OS Platform | | + + +## Standalone code, or other way to reproduce the problem + +_(Please complete the text below to help us fix the issue)_ + +### Expected result + +### Actual result diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..06752e87 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,25 @@ +## Introduction + +_(Please explain the library current status regarding your PR.)_ + +## Proposal + +### Describe the new/upated/fixed feature + +_(Please explain your proposal. If this is a issue fix, please provide the issue number. If you have not yet created an issue, please do so now)_ + +### Backward Incompatible Changes + +_(Describe if they exists BC break)_ + +### Targeted release version + +_(Indicate the release version targeted for your PR)_ + +### PR Impact + +_(Describe the PR impact on the current public API)_ + +## Open issues + +_(Describe possible open issues and/or future scope if any depending on this RFC acceptance)_ diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..c4ede256 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,65 @@ +--- +name: build +on: + push: ~ + pull_request: ~ + +jobs: + linux_tests: + name: PHP on ${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.composer-flags }} + runs-on: ubuntu-22.04 + strategy: + matrix: + php: ['8.1', '8.2', '8.3', '8.4'] + stability: [prefer-lowest, prefer-stable] + include: + - php: '8.4' + flags: "--ignore-platform-req=php" + phpunit-flags: '--no-coverage' + stability: prefer-stable + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: xdebug + tools: composer:v2 + - name: Check PHP Version + run: php -v + + - name: Validate composer files + run: composer validate --strict + + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.stability }}-${{ matrix.flags }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer-${{ matrix.stability }}-${{ matrix.flags }}- + ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress ${{ matrix.flags }} + + - name: Run Unit tests with coverage + run: composer phpunit -- ${{ matrix.phpunit-flags }} + if: ${{ matrix.php == '8.3' || matrix.php == '8.2' || matrix.php == '8.1'}} + + - name: Run Unit tests without coverage + run: composer phpunit:min + if: ${{ matrix.php == '8.4'}} + + - name: Run static analysis + run: composer phpstan + if: ${{ matrix.php == '8.3' && matrix.stability == 'prefer-stable'}} + + - name: Run Coding style rules + run: composer phpcs:fix + if: ${{ matrix.php == '8.3' && matrix.stability == 'prefer-stable'}} diff --git a/.gitignore b/.gitignore index 1ab82556..61906c3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ -tags -composer.lock +data vendor -*.swp docs -*~ build +pdp .idea +.phpunit.cache +.php_cs.cache +.php-cs-fixer.cache +composer.lock diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 00000000..c17d0c98 --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,50 @@ +in(__DIR__.'/src') +; + +$config = new PhpCsFixer\Config(); + +return $config + ->setParallelConfig(ParallelConfigFactory::detect()) + ->setRules([ + '@PSR12' => true, + 'array_syntax' => ['syntax' => 'short'], + 'concat_space' => ['spacing' => 'none'], + 'global_namespace_import' => [ + 'import_classes' => true, + 'import_constants' => true, + 'import_functions' => true, + ], + 'new_with_parentheses' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_phpdoc' => true, + 'no_empty_comment' => true, + 'no_leading_import_slash' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_singleline' => true, + 'no_unused_imports' => true, + 'nullable_type_declaration_for_default_null_value' => true, + 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], + 'phpdoc_add_missing_param_annotation' => ['only_untyped' => true], + 'phpdoc_align' => ['align' => 'left'], + 'phpdoc_no_empty_return' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_summary' => true, + 'psr_autoloading' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'blank_lines_before_namespace' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'ternary_operator_spaces' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => true, + ]) + ->setFinder($finder); diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 033074dd..00000000 --- a/.php_cs +++ /dev/null @@ -1,18 +0,0 @@ -in('src/') - ->in('tests/'); - -return \Symfony\CS\Config\Config::create() - ->setUsingCache(true) - ->fixers([ - '-pre_increment', - '-concat_without_spaces', - 'concat_with_spaces', - 'ordered_use', - 'long_array_syntax', - ]) - ->finder($finder); diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0e690e7b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: php - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm - -script: phpunit - -before_script: - - composer install - - ./bin/update-psl diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..50dc06fd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,432 @@ +# Changelog + +All Notable changes to `PHP Domain Parser` starting from the **5.x** series will be documented in this file + +## [6.4.0] - 2025-04-26 + +### Added + +- `DomainName::withRootLabel`, `DomainName::withoutRootLabel`, `DomainName::isAbsolute` methods to handle absolute domain names. +- `DomainName::when` to allow conditionable when building the domain. + +### Fixed + +- Absolute domain name can now also be resolved by the package see issue [#361](https://github.com/jeremykendall/php-domain-parser/issues/361) prior to this release an exception was thrown. +- Since we no longer support PHP7 type hint and return type are improved. +- Resolving private suffixes that have a wildcarded subdomain suffix [#363](https://github.com/jeremykendall/php-domain-parser/issues/363) by [@wikando-ck](https://github.com/wikando-ck) + (Once downloaded and installed you MUST refresh your cache to enable the fix to work.) + +### Deprecated + +- None + +### Removed + +- None + +## [6.3.0] - 2023-02-25 + +### Added + +- `RegisteredName` class to allow domain with IP4-like labels + +### Fixed + +- Using PHPUnit 10 +- `Domain` decorates the new `RegisteredName` class [#347](https://github.com/jeremykendall/php-domain-parser/issues/347) +- `Host::withoutLabel` works without arguments. + +### Deprecated + +- None + +### Removed + +- None + +## [6.2.0] - 2022-10-30 + +### Added + +- None + +### Fixed + +- None + +### Deprecated + +- None + +### Removed + +- PHP7 and PHP8.0 support + +## [6.1.2] - 2022-09-29 + +### Added + +- None + +### Fixed + +- [#321](https://github.com/jeremykendall/php-domain-parser/issues/334) remove regression to resolving private domain suffix. + +### Deprecated + +- None + +### Removed + +- None + +## [6.1.1] - 2022-02-18 + +### Added + +- None + +### Fixed + +- [#321](https://github.com/jeremykendall/php-domain-parser/issues/321) improve resolving private domain suffix. `Rules::getPrivateDomain` will now throw if the domain name does not contain a "private" TLD. + +### Deprecated + +- None + +### Removed + +- None + +## [6.1.0] - 2021-06-19 + +### Added + +- `TimeToLive::until` +- `TimeToLive::fromDurationString` + +### Fixed + +- `.gitattributes` files to be filter out. +- `TimeToLive` marked as internal +- `Host::toUnicode` method MUST never throw exceptions on conversion according to RFC3490. +- `UnableToResolveDomain` typo in the exception message + +### Deprecated + +- `TimeToLive::fromDateTimeInterface` use `TimeToLive::fromNow` +- `TimeToLive::fromScalar` use `TimeToLive::convert` + +### Removed + +- None + +## [6.0.0] - 2020-12-13 + +### Added + +- Adding proper Interfaces +- Added `Domain::clear` to easily initialize an empty domain object +- Added `Domain::slice` to easily slice a domain object +- Added `ResolvedDomain` object to normalize Resolver results. +- Added `Suffix` object to replace the `PublicSuffix` object from v5. +- Public Suffix List and IANA Top Level Domain List are fully decoupled +- Added `Idna`, IDN support has been completely revamped +- Added internal `Stream` class, to improve path/stream resolution +- Resolver uses by default UTS#46 IDNA2008 algorithm to convert domain names +- Storage capability is now optional and can be based on PHP-FIG related interfaces to improve interoperability +- `Pdp\TopLevelDomains::getIANADomain` which throws on syntax error and if no effective TLD is found (behave like `Pdp\TopLevelDomains::resolve` in v5). + +### Fixed + +- The `Pdp\Domain` class not longer directly exposes Effective TLD status. +- Effective TLD resolver (`Pdp\Rules::resolve` and `Pdp\TopLevelDomains::resolve`) no longer accept IDNA options. +- `Rules::getICANNDomain`, `Rules::getPrivateDomain` will throw even if a `PublicSuffix` is found but does not belong to the correct PSL section. +- `Pdp\TopLevelDomains::resolve` acts like `Pdp\Rules::resolve` and only throw on `TypeError` + +### Deprecated + +- None + +### Removed + +- `__toString` and `__debugInfo` usage +- Support for PHP7.4- +- Composer script for automatic updates of the remote databases +- CLI command `bin/update-psl` +- `Pdp\Cache`, `Pdp\CacheException`: The package PSR-16 Cache implementation using the underlying filesystem. +- `Pdp\HttpClient`, `Pdp\CurlHttpClient` and `Pdp\HttpClientException`: The package Http Client. +- `Pdp\Installer`, `Pdp\Manager`: The package source manager and installer +- `Pdp\Logger`, The package logger implementation +- `Pdp\Rules::ALL_DOMAINS` constant deprecated in version 5.3 +- `Pdp\Domain::getDomain` deprecated in version 5.3 +- `Pdp\Domain::resolve` +- `Pdp\Domain::getPublicSuffix` replaced by `Pdp\ResolvedDomain::suffix` +- `Pdp\Domain::getRegistrableDomain` replaced by `Pdp\ResolvedDomain::registrableDomain` +- `Pdp\Domain::getSubDomain` replaced by `Pdp\ResolvedDomain::subDomain` +- `Pdp\Domain::withPublicSuffix` replaced by `Pdp\ResolvedDomain::withSuffix` +- `Pdp\Domain::getLabel` replaced by `Pdp\Domain::label` +- `Pdp\Domain::isTransitionalDifferent` replaced by `Pdp\IdnaInfo::isTransitionalDifferent` +- `Pdp\PublicSuffix` replaced by `Pdp\Suffix` +- Accessing suffix information from the `Pdp\Domain` object is no longer possible you need to do it from `Pdp\Suffix` +- `Pdp\TopLevelDomains::contains` without replacement +- Internal Converter classes (implementation details are no longer exposed). + +## [5.7.2] - 2020-10-25 + +### Added + +- None + +### Fixed + +- Added support for PHP8 see [#289](https://github.com/jeremykendall/php-domain-parser/pull/289) based on works by [@szepeviktor](https://github.com/szepeviktor) + +### Deprecated + +- None + +### Remove + +- None + +## [5.7.1] - 2020-08-24 + +### Added + +- None + +### Fixed + +- Cache throws when cache directory doesn't exist [#280](https://github.com/jeremykendall/php-domain-parser/issues/280) + +### Deprecated + +- None + +### Removed + +- None + +## [5.7.0] - 2020-08-02 + +### Added + +- `Rules::getCookieDomain` +- `Rules::getICANNDomain` +- `Rules::getPrivateDomain` +- `CouldNotResolvePublicSuffix::dueToUnresolvableDomain` + +### Fixed + +- Improve type hinting and return type by dropping EOL PHP versions support. +- Improve development environment by dropping EOL PHP versions support. +- Composer script + +### Deprecated + +- None + +### Removed + +- Support for PHP7.0 and PHP7.1 +- The external data from IANA and mozilla is no longer part of the package and will be downloaded only on demand on composer update/install. + +## [5.6.0] - 2019-12-29 + +### Added + +- A simple `Psr3` compatible logger class which output the logs to you cli console. + +### Fixed + +- `composer.json` updated to be composer 2.0 ready +- package bundle installer is rewritten to improve its usage see [#249](https://github.com/jeremykendall/php-domain-parser/issues/249) and [#250](https://github.com/jeremykendall/php-domain-parser/issues/250) + +### Deprecated + +- None + +### Removed + +- None + +## [5.5.0] - 2019-04-14 + +### Added + +- Support for IDNA options see [#236](https://github.com/jeremykendall/php-domain-parser/pull/236) thanks to [Insolita](https://github.com/Insolita). + +- `PublicSuffix::labels` and `Domain::labels` to return the VO labels see [#241](https://github.com/jeremykendall/php-domain-parser/pull/241) + +- `IDNAConverterTrait::parse` (internal) + +### Fixed + +- Don't swallow cache errors [#232](https://github.com/jeremykendall/php-domain-parser/issues/232) +- Update travis settings to allow testing against future version of PHP. + +### Deprecated + +- `IDNAConverterTrait::setLabels` replaced by `IDNAConverterTrait::parse` (internal) + +### Removed + +- None + +## [5.4.0] - 2018-11-22 + +### Added + +- `Pdp\TopLevelDomains` to allow resolving domain againts IANA Root zone database +- `Pdp\TLDConverter` converts the IANA Root Zones database into an associative array +- `Pdp\Manager::getTLDs` a service to return a cache version of the IANA Root zone database +- `Pdp\Manager::refreshTLDs` a service to refresh the cache version of the IANA Root zone database +- added a new `$ttl` parameter to improve PSR-16 supports to + - `Pdp\Manager::__construct` + - `Pdp\Manager::getRules` + - `Pdp\Manager::refreshRules` +- `Pdp\Exception\CouldNotLoadTLDs` exception + +### Fixed + +- `Pdp\IDNAConverterTrait::setLabels` improve IDN domain handling +- `Pdp\IDNAConverterTrait` throws a `UnexpectedValueException` if the Intl extension is misconfigured see [#230](https://github.com/jeremykendall/php-domain-parser/issues/230) + +### Deprecated + +- None + +### Removed + +- None + +## [5.3.0] - 2018-05-22 + +### Added + +- `Pdp\PublicSuffixListSection` interface implemented by `Pdp\Rules` and `Pdp\PublicSuffix` +- `Pdp\DomainInterface` interface implemented by `Pdp\Domain` and `Pdp\PublicSuffix` +- `Pdp\Domain::getContent` replaces `Pdp\Domain::getDomain` +- `Pdp\Domain::withLabel` adds a new label to the `Pdp\Domain`. +- `Pdp\Domain::withoutLabel` removes labels from the `Pdp\Domain`. +- `Pdp\Domain::withPublicSuffix` updates the `Pdp\Domain` public suffix part. +- `Pdp\Domain::withSubDomain` updates the `Pdp\Domain` sub domain part. +- `Pdp\Domain::append` appends a label to `Pdp\Domain`. +- `Pdp\Domain::prepend` prepends a label to `Pdp\Domain`. +- `Pdp\Domain::resolve` attach a public suffix to the `Pdp\Domain`. +- `Pdp\Domain::isResolvable` tells whether the current `Pdp\Domain` can have a public suffix attached to it or not. +- `Pdp\PublicSuffix::createFromDomain` returns a new `Pdp\PublicSuffix` object from a `Pdp\Domain`object +- `Pdp\Exception` sub namespace to organize exception. All exception extends the `Pdp\Exception` class to prevent BC break. + +### Fixed + +- `Pdp\Domain` domain part computation (public suffix, registrable domain and sub domain) +- `Pdp\Domain` and `Pdp\PublicSuffix` host validation compliance to RFC improved +- Improve `Pdp\Converter` and `Pdp\Manager` class to better report error on IDN conversion. +- Improve `Pdp\Installer` vendor directory resolution see [PR #222](https://github.com/jeremykendall/php-domain-parser/pull/222) +- `Pdp\Exception` nows extends `InvalidArgumentException` instead of `RuntimeException` + +### Deprecated + +- `Pdp\Domain::getDomain` use instead `Pdp\Domain::getContent` +- `Pdp\Rules::ALL_DOMAINS` use the empty string instead + +### Removed + +- None + +## [5.2.0] - 2018-02-23 + +### Added + +- `Pdp\Rules::getPublicSuffix` returns a `Pdp\PublicSuffix` value object +- `Pdp\Rules::__set_state` is implemented +- `Pdp\Domain::toUnicode` returns a `Pdp\Domain` with its value converted to its Unicode form +- `Pdp\Domain::toAscii` returns a `Pdp\Domain` with its value converted to its AScii form +- `Pdp\PublicSuffix::toUnicode` returns a `Pdp\PublicSuffix` with its value converted to its Unicode form +- `Pdp\PublicSuffix::toAscii` returns a `Pdp\PublicSuffix` with its value converted to its AScii form + +### Fixed + +- `Pdp\Domain::getDomain` returns the normalized form of the domain name +- `Pdp\PublicSuffix` is no longer internal. +- Normalizes IDN conversion using a internal `IDNConverterTrait` +- Internal code improved by requiring PHPStan for development + +### Deprecated + +- None + +### Removed + +- None + +## [5.1.0] - 2017-12-18 + +### Added + +- `Pdp\Rules::createFromPath` named constructor to returns a new instance from a path +- `Pdp\Rules::createFromString` named constructor to returns a new instance from a string + +### Fixed + +- None + +### Deprecated + +- None + +### Removed + +- None + +## [5.0.0] - 2017-12-13 + +### Added + +- `Pdp\Exception` a base exception for the library +- `Pdp\Rules` a class to resolve domain name against the public suffix list +- `Pdp\Domain` an immutable value object to represents a parsed domain name +- `Pdp\Installer` a class to enable improve PSL maintenance +- `Pdp\Cache` a PSR-16 file cache implementation to cache a local copy of the PSL +- `Pdp\Manager` a class to enable managing PSL sources and `Rules` objects creation +- `Pdp\Converter` a class to convert the PSL into a PHP array + +### Fixed + +- invalid domain names improved supported +- idn_* conversion error better handled +- domain name with RFC3986 encoded string improved supported + +### Deprecated + +- None + +### Removed + +- PHP5 support +- URL Parsing capabilities and domain name validation +- `Pdp\PublicSuffixList` class replaced by the `Pdp\Rules` class +- `Pdp\PublicSuffixManager` class replaced by the `Pdp\Manager` class +- `Pdp\HttpAdapter\HttpAdapterInterface` interface replaced by the `Pdp\HttpClient` interface +- `Pdp\HttpAdapter\CurlHttpAdapter` class replaced by the `Pdp\CurlHttpClient` class + +[6.4.0]: https://github.com/jeremykendall/php-domain-parser/compare/6.3.0...6.4.0 +[6.3.0]: https://github.com/jeremykendall/php-domain-parser/compare/6.2.0...6.3.0 +[6.2.0]: https://github.com/jeremykendall/php-domain-parser/compare/6.1.2...6.2.0 +[6.1.2]: https://github.com/jeremykendall/php-domain-parser/compare/6.1.1...6.1.2 +[6.1.1]: https://github.com/jeremykendall/php-domain-parser/compare/6.1.0...6.1.1 +[6.1.0]: https://github.com/jeremykendall/php-domain-parser/compare/6.0.0...6.1.0 +[6.0.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.7.2...6.0.0 +[6.0.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.7.2...6.0.0 +[5.7.2]: https://github.com/jeremykendall/php-domain-parser/compare/5.7.1...5.7.2 +[5.7.1]: https://github.com/jeremykendall/php-domain-parser/compare/5.7.0...5.7.1 +[5.7.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.6.0...5.7.0 +[5.6.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.5.0...5.6.0 +[5.5.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.4.0...5.5.0 +[5.4.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.3.0...5.4.0 +[5.3.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.2.0...5.3.0 +[5.2.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.1.0...5.3.0 +[5.1.0]: https://github.com/jeremykendall/php-domain-parser/compare/5.0.0...5.1.0 +[5.0.0]: https://github.com/jeremykendall/php-domain-parser/compare/3.0.0...5.0.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 2513f4ef..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,22 +0,0 @@ -# How to Contribute - -## Pull Requests - -1. Create your own [fork](https://help.github.com/articles/fork-a-repo) of this repo -2. Create a new branch for each feature or improvement -3. Send a pull request from each feature branch to the **develop** branch - -It is very important to separate new features or improvements into separate -feature branches, and to send a pull request for each branch. This allows me to -review and pull in new features or improvements individually. - -## Style Guide - -All pull requests must adhere to the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). - -## Unit Testing - -All pull requests must be accompanied by passing PHPUnit unit tests and -complete code coverage. - -[Learn about PHPUnit](https://github.com/sebastianbergmann/phpunit/) diff --git a/LICENSE b/LICENSE index 1a0cad7a..f757ef1c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ -Copyright (C) 2013-2014 Jeremy Kendall, http://about.me/jeremykendall +The MIT License (MIT) + +Copyright (C) 2013 Jeremy Kendall, http://about.me/jeremykendall 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 diff --git a/README.md b/README.md index 91ad9979..96d3519e 100644 --- a/README.md +++ b/README.md @@ -1,431 +1,641 @@ # PHP Domain Parser -**PHP Domain Parser** is a [Public Suffix List](http://publicsuffix.org/) based -domain parser implemented in PHP. +**PHP Domain Parser** is a resource based domain parser implemented in PHP. -[![Build Status](https://travis-ci.org/jeremykendall/php-domain-parser.png?branch=master)](https://travis-ci.org/jeremykendall/php-domain-parser) -[![Total Downloads](https://poser.pugx.org/jeremykendall/php-domain-parser/downloads.png)](https://packagist.org/packages/jeremykendall/php-domain-parser) -[![Latest Stable Version](https://poser.pugx.org/jeremykendall/php-domain-parser/v/stable.png)](https://packagist.org/packages/jeremykendall/php-domain-parser) +[![Build Status][ico-github-actions-build]][link-github-actions-build] +[![Total Downloads][ico-packagist]][link-packagist] +[![Latest Stable Version][ico-release]][link-release] +[![Software License][ico-license]][link-license] ## Motivation While there are plenty of excellent URL parsers and builders available, there -are very few projects that can accurately parse a url into its component -subdomain, registrable domain, and public suffix parts. +are very few projects that can accurately parse a domain into its component +subdomain, registrable domain, second level domain and public suffix parts. Consider the domain www.pref.okinawa.jp. In this domain, the *public suffix* portion is **okinawa.jp**, the *registrable domain* is -**pref.okinawa.jp**, and the *subdomain* is **www**. You can't regex that. +**pref.okinawa.jp**, the *subdomain* is **www** and +the *second level domain* is **pref**. +You can't regex that. -Other similar libraries focus primarily on URL building, parsing, and -manipulation and additionally include public suffix domain parsing. PHP Domain -Parser was built around accurate Public Suffix List based parsing from the very -beginning, adding a URL object simply for the sake of completeness. +PHP Domain Parser is compliant around: -## Installation +- accurate Public Suffix List based parsing. +- accurate IANA Top Level Domain List parsing. -The only (currently) supported method of installation is via -[Composer](http://getcomposer.org). +## Installation -Create a `composer.json` file in the root of your project: +### Composer -``` json -{ - "require": { - "jeremykendall/php-domain-parser": "~2.0" - } -} -``` +~~~ +composer require jeremykendall/php-domain-parser:^6.0 +~~~ -And then run: `composer install` +### System Requirements -Add the autoloader to your project: +You need: -``` php -= 8.1** but the latest stable version of PHP is recommended +- a copy of the [Public Suffix List](https://publicsuffix.org/) data and/or a copy of the [IANA Top Level Domain List](https://www.iana.org/domains/root/files). Please refer to the [Managing external data source section](#managing-the-package-external-resources) for more information when using this package in production. -require_once 'vendor/autoload.php' -``` +Handling of an IDN host requires the presence of the `intl` extension or +a polyfill for the `intl` IDN functions like the `symfony/polyfill-intl-idn` +otherwise an exception will be thrown when attempting to validate or interact +with such a host. -You're now ready to begin using the PHP Domain Parser. +> [!WARNING] +> When upgrading to version `6.4` you MUST refresh your local cache for the fix on +> private domain resolution to take effect. ## Usage -### Parsing URLs +> [!WARNING] +> If you are upgrading from version 5 please check the [upgrading guide](UPGRADING.md) for known issues. -Parsing URLs into their component parts is as simple as the example you see below. +### Resolving Domains -``` php -getList()); -$host = 'http://user:pass@www.pref.okinawa.jp:8080/path/to/page.html?query=string#fragment'; -$url = $parser->parseUrl($host); -var_dump($url); -``` +For the [Public Suffix List](http://publicsuffix.org/) you need to use the +`Pdp\Rules` class as shown below: -The above will output: +~~~php + - string(4) "http" - private $host => - class Pdp\Uri\Url\Host#5 (3) { - private $subdomain => - string(3) "www" - private $registrableDomain => - string(15) "pref.okinawa.jp" - private $publicSuffix => - string(10) "okinawa.jp" - } - private $port => - int(8080) - private $user => - string(4) "user" - private $pass => - string(4) "pass" - private $path => - string(18) "/path/to/page.html" - private $query => - string(12) "query=string" - private $fragment => - string(8) "fragment" -} -``` +$publicSuffixList = Rules::fromPath('/path/to/cache/public-suffix-list.dat'); +$domain = Domain::fromIDNA2008('www.PreF.OkiNawA.jP'); -### Convenience Methods +$result = $publicSuffixList->resolve($domain); +echo $result->domain()->toString(); //display 'www.pref.okinawa.jp'; +echo $result->subDomain()->toString(); //display 'www'; +echo $result->secondLevelDomain()->toString(); //display 'pref'; +echo $result->registrableDomain()->toString(); //display 'pref.okinawa.jp'; +echo $result->suffix()->toString(); //display 'okinawa.jp'; +$result->suffix()->isICANN(); //return true; +~~~ -A magic [`__get()`](http://php.net/manual/en/language.oop5.overloading.php#object.get) -method is provided to access the above object properties. Obtaining the public -suffix for a parsed domain is as simple as: +For the [IANA Top Level Domain List](https://www.iana.org/domains/root/files), +the `Pdp\TopLevelDomains` class is use instead: -``` php +~~~php parseUrl($host); -$publicSuffix = $url->host->publicSuffix; - -// $publicSuffix = 'com.au' -``` - -### IDNA Support +use Pdp\Domain; +use Pdp\TopLevelDomains; -[IDN (Internationalized Domain Name)](http://en.wikipedia.org/wiki/Internationalized_domain_name) -support was added in version `1.4.0`. Both unicode domains and their ASCII -equivalents are supported. +$topLevelDomains = TopLevelDomains::fromPath('/path/to/cache/tlds-alpha-by-domain.txt'); +$domain = Domain::fromIDNA2008('www.PreF.OkiNawA.jP'); -**IMPORTANT**: +$result = $topLevelDomains->resolve($domain); +echo $result->domain()->toString(); //display 'www.pref.okinawa.jp'; +echo $result->suffix()->toString(); //display 'jp'; +echo $result->secondLevelDomain()->toString(); //display 'okinawa'; +echo $result->registrableDomain()->toString(); //display 'okinawa.jp'; +echo $result->subDomain()->toString(); //display 'www.pref'; +echo $result->suffix()->isIANA(); //return true +~~~ -* PHP's [intl](http://php.net/manual/en/book.intl.php) extension is -required for the [IDN functions](http://php.net/manual/en/ref.intl.idn.php). -* PHP's [mb_string](http://php.net/manual/en/book.mbstring.php) extension is -required for [mb_strtolower](http://php.net/manual/en/function.mb-strtolower.php). +In case of an error an exception which extends `Pdp\CannotProcessHost` is thrown. -#### Unicode +The `resolve` method will always return a `ResolvedDomain` even if the domain +syntax is invalid or if there is no match found in the resource data. +To work around this limitation, the library exposes more strict methods, +namely: -Parsing IDNA hosts is no different that parsing standard hosts. Setting `$host -= 'Яндекс.РФ';` (Russian-Cyrillic) in the *Parsing URLs* example would return: - -``` -class Pdp\Uri\Url#6 (8) { - private $scheme => - string(0) "" - private $host => - class Pdp\Uri\Url\Host#5 (4) { - private $subdomain => - NULL - private $registrableDomain => - string(17) "яндекс.рф" - private $publicSuffix => - string(4) "рф" - private $host => - string(17) "яндекс.рф" - } - private $port => - NULL - private $user => - NULL - private $pass => - NULL - private $path => - NULL - private $query => - NULL - private $fragment => - NULL -} -``` - -#### ASCII (Punycode) - -If you choose to provide the ASCII equivalent of the unicode domain name -(`$host = 'http://xn--d1acpjx3f.xn--p1ai';` in the case of the *Parsing URLs* example), -the ASCII equivalent will be returned by the parser: - -``` -class Pdp\Uri\Url#6 (8) { - private $scheme => - string(4) "http" - private $host => - class Pdp\Uri\Url\Host#5 (4) { - private $subdomain => - NULL - private $registrableDomain => - string(22) "xn--d1acpjx3f.xn--p1ai" - private $publicSuffix => - string(8) "xn--p1ai" - private $host => - string(22) "xn--d1acpjx3f.xn--p1ai" - } - private $port => - NULL - private $user => - NULL - private $pass => - NULL - private $path => - NULL - private $query => - NULL - private $fragment => - NULL -} -``` - -### IPv6 Support - -Parsing IPv6 hosts is no different that parsing standard hosts. Setting `$host -= 'http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8080/';` -in the *Parsing URLs* example would return: - -``` -class Pdp\Uri\Url#6 (8) { - private $scheme => - string(4) "http" - private $host => - class Pdp\Uri\Url\Host#5 (4) { - private $subdomain => - NULL - private $registrableDomain => - NULL - private $publicSuffix => - NULL - private $host => - string(38) "[2001:db8:85a3:8d3:1319:8a2e:370:7348]" - } - private $port => - string(4) "8080" - private $user => - NULL - private $pass => - NULL - private $path => - string(1) "/" - private $query => - NULL - private $fragment => - NULL -} -``` +- `Rules::getCookieDomain` +- `Rules::getICANNDomain` +- `Rules::getPrivateDomain` -**IMPORTANT**: IPv6 url host names *must* be enclosed in square brackets. They -will not be parsed properly otherwise. +for the Public Suffix List and the following method for the Top Level +Domain List: -> Hat tip to [@geekwright](https://github.com/geekwright) for adding IPv6 support in a -> [bugfix pull request](https://github.com/jeremykendall/php-domain-parser/pull/35). +- `TopLevelDomains::getIANADomain` -### Parsing Domains +These methods resolve the domain against their respective data source using +the same rules as the `resolve` method but will instead throw an exception +if no valid effective TLD is found or if the submitted domain is invalid. -If you'd like to parse the domain (or host) portion only, you can use -`Parser::parseHost()`. +> [!CAUTION] +> All these methods expect as their sole argument a `Pdp\Host` implementing +object, but other types (ie: `string`, `null` and stringable objects) are +supported with predefined conditions as explained in the remaining document. -```php +~~~php parseHost('a.b.c.cy'); -var_dump($host); -``` - -The above will output: - -``` -class Pdp\Uri\Url\Host#7 (3) { - private $subdomain => - string(1) "a" - private $registrableDomain => - string(6) "b.c.cy" - private $publicSuffix => - string(4) "c.cy" +use Pdp\Domain; +use Pdp\Rules; +use Pdp\TopLevelDomains; + +$publicSuffixList = Rules::fromPath('/path/to/cache/public-suffix-list.dat'); +$domain = Domain::fromIDNA2008('qfdsf.unknownTLD'); + +$publicSuffixList->getICANNDomain($domain); +// will throw because `.unknownTLD` is not part of the ICANN section + +$result = $publicSuffixList->getCookieDomain($domain); +$result->suffix()->value(); // returns 'unknownTLD' +$result->suffix()->isKnown(); // returns false +// will not throw because the domain syntax is correct. + +$publicSuffixList->getCookieDomain(Domain::fromIDNA2008('com')); +// will not throw because the domain syntax is invalid (ie: does not support public suffix) + +$result = $publicSuffixList->resolve(Domain::fromIDNA2008('com')); +$result->suffix()->value(); // returns null +$result->suffix()->isKnown(); // returns false +// will not throw but its public suffix value equal to NULL + +$topLevelDomains = TopLevelDomains::fromPath('/path/to/cache/public-suffix-list.dat'); +$topLevelDomains->getIANADomain(Domain::fromIDNA2008('com')); +// will not throw because the domain syntax is invalid (ie: does not support public suffix) +~~~ + +To instantiate each domain resolver you can use the following named constructor: + +- `fromString`: instantiate the resolver from a inline string representing the data source; +- `fromPath`: instantiate the resolver from a local path or online URL by relying on `fopen`; + +**If the instantiation does not work an exception will be thrown.** + +> [!WARNING] +> You SHOULD never resolve domain name this way in production, without, at +least, a caching mechanism to reduce external resource downloads. +> Using the Public Suffix List to determine what is a valid domain name and what +isn't is dangerous, and MAY lead to errors because of new gTLDs being registered +on a regular basis. +> If you are looking to know the validity of a Top Level Domain, you MUST use +the IANA Top Level Domain List as the proper source for this information or +alternatively the DNS. +> If you MUST use this library for any of the above purposes, you SHOULD consider +integrating an updating mechanism into your software. +> For more information go to the [Managing external data source section](#managing-the-package-external-resources)** + +### Resolved domain information. + +Whichever methods chosen to resolve the domain on success, the package will +return a `Pdp\ResolvedDomain` instance. + +The `Pdp\ResolvedDomain` decorates the `Pdp\Domain` class resolved but also +gives access as separate methods to the domain different components. + +~~~php +use Pdp\Domain; +use Pdp\TopLevelDomains; + +$domain = Domain::fromIDNA2008('www.PreF.OkiNawA.jP'); +/** @var TopLevelDomains $topLevelDomains */ +$result = $topLevelDomains->resolve($domain); +echo $result->domain()->toString(); //display 'www.pref.okinawa.jp'; +echo $result->suffix()->toString(); //display 'jp'; +echo $result->secondLevelDomain()->toString(); //display 'okinawa'; +echo $result->registrableDomain()->toString(); //display 'okinawa.jp'; +echo $result->subDomain()->toString(); //display 'www.pref'; +echo $result->suffix()->isIANA(); //return true +~~~ + +You can modify the returned `Pdp\ResolvedDomain` instance using the following methods: + +~~~php +resolve(Domain::fromIDNA2008('shop.example.com')); +$altResult = $result + ->withSubDomain(Domain::fromIDNA2008('foo.bar')) + ->withSecondLevelDomain(Domain::fromIDNA2008('test')) + ->withSuffix(Domain::fromIDNA2008('example')); + +echo $result->domain()->toString(); //display 'shop.example.com'; +$result->suffix()->isKnown(); //return true; + +echo $altResult->domain()->toString(); //display 'foo.bar.test.example'; +$altResult->suffix()->isKnown(); //return false; +~~~ + +> [!TIP] +> Always favor submitting a `Pdp\Suffix` object rather that any other +supported type to avoid unexpected results. By default, if the input is not a +`Pdp\Suffix` instance, the resulting public suffix will be labelled as +being unknown. For more information go to the [Public Suffix section](#public-suffix) + +> [!NOTE] +> Since version `6.4` Domain resolution is also adapted so that absolute domain +can effectively be resolved. Prior to version `6.4` an exception was thrown. + +### Domain Suffix + +The domain effective TLD is represented using the `Pdp\Suffix`. Depending on +the data source the object exposes different information regarding its +origin. + +~~~php +resolve(Domain::fromIDNA2008('example.github.io'))->suffix(); + +echo $suffix->domain()->toString(); //display 'github.io'; +$suffix->isICANN(); //will return false +$suffix->isPrivate(); //will return true +$suffix->isPublicSuffix(); //will return true +$suffix->isIANA(); //will return false +$suffix->isKnown(); //will return true +~~~ + +The public suffix state depends on its origin: + +- `isKnown` returns `true` if the value is present in the data resource. +- `isIANA` returns `true` if the value is present in the IANA Top Level Domain List. +- `isPublicSuffix` returns `true` if the value is present in the Public Suffix List. +- `isICANN` returns `true` if the value is present in the Public Suffix List ICANN section. +- `isPrivate` returns `true` if the value is present in the Public Suffix List private section. + +The same information is used when `Pdp\Suffix` object is +instantiate via its named constructors: + + ~~~php + resolve(Domain::from2008('www.bbc.co.uk')); +$domain = $result->domain(); +echo $domain->toString(); // display 'www.bbc.co.uk' +count($domain); // returns 4 +$domain->labels(); // returns ['uk', 'co', 'bbc', 'www']; +$domain->label(-1); // returns 'www' +$domain->label(0); // returns 'uk' +foreach ($domain as $label) { + echo $label, PHP_EOL; } -``` +// display +// uk +// co +// bbc +// www + +$publicSuffixDomain = $result->suffix()->domain(); +$publicSuffixDomain->labels(); // returns ['uk', 'co'] +~~~ + +You can also add or remove labels according to their key index using the +following methods: + +~~~php +resolve(Domain::from2008('www.ExAmpLE.cOM'))->domain(); + +$newDomain = $domain + ->withLabel(1, 'com') //replace 'example' by 'com' + ->withoutLabel(0, -1) //remove the first and last labels + ->append('www') + ->prepend('docs.example'); + +echo $domain->toString(); //display 'www.example.com' +echo $newDomain->toString(); //display 'docs.example.com.www' +$newDomain->clear()->labels(); //return [] +echo $domain->slice(2)->toString(); //display 'www' +~~~ + +Starting with version `6.4` it is possible to specify and handle absolute domain +with the following methods. + +~~~php +resolve(Domain::from2008('www.ExAmpLE.cOM'))->domain(); +$newDomain = $domain->withRootLabel(); + +echo $domain->toString(); //display 'www.example.com' +echo $newDomain->toString(); //display 'www.example.com.www.' +$domain->isAbsolute(); //return false +$newDomain->isAbsolute() //return true + +$domain->value() === $newDomain->withoutRootLabel()->value(); +~~~ + +> [!WARNING] +> Because of its definition, a domain name can be `null` or a string. + +To distinguish this possibility the object exposes two (2) formatting methods +`Domain::value` which can be `null` or a `string` and `Domain::toString` which +will always cast the domain value to a string. + + ~~~php +use Pdp\Domain; + +$nullDomain = Domain::fromIDNA2008(null); +$nullDomain->value(); // returns null; +$nullDomain->toString(); // returns ''; + +$emptyDomain = Domain::fromIDNA2008(''); +$emptyDomain->value(); // returns ''; +$emptyDomain->toString(); // returns ''; + ~~~ + +### ASCII and Unicode formats. + +Domain names originally only supported ASCII characters. Nowadays, +they can also be presented under a UNICODE representation. The conversion +between both formats is done using the compliant implementation of +[UTS#46](https://www.unicode.org/reports/tr46/), otherwise known as Unicode +IDNA Compatibility Processing. Domain objects expose a `toAscii` and a +`toUnicode` methods which returns a new instance in the converted format. + +~~~php +resolve('bébé.be')->domain(); +echo $unicodeDomain->toString(); // returns 'bébé.be' + +$asciiDomain = $publicSuffixList->resolve('xn--bb-bjab.be')->domain(); +echo $asciiDomain->toString(); // returns 'xn--bb-bjab.be' + +$asciiDomain->toUnicode()->toString() === $unicodeDomain->toString(); //returns true +$unicodeDomain->toAscii()->toString() === $asciiDomain->toString(); //returns true +~~~ + +By default, the library uses IDNA2008 algorithm to convert domain name between +both formats. It is still possible to use the legacy conversion algorithm known +as IDNA2003. + +Since direct conversion between both algorithms is not possible you need +to explicitly specific on construction which algorithm you will use +when creating a new domain instance via the `Pdp\Domain` object. This +is done via two (2) named constructors: -### Validation of Public Suffixes +- `Pdp\Domain::fromIDNA2008` +- `Pdp\Domain::fromIDNA2003` + +At any given moment the `Pdp\Domain` instance can tell you whether it is in +`ASCII` mode or not. + +> [!WARNING] +> Once instantiated there's no way to tell which algorithm is used to convert +the object from ascii to unicode and vice-versa + +~~~php +use Pdp\Domain; + +$domain = Domain::fromIDNA2008('faß.de'); +echo $domain->value(); // display 'faß.de' +$domain->isAscii(); // return false + +$asciiDomain = $domain->toAscii(); +echo $asciiDomain->value(); // display 'xn--fa-hia.de' +$asciiDomain->isAscii(); // returns true + +$domain = Domain::fromIDNA2003('faß.de'); +echo $domain->value(); // display 'fass.de' +$domain->isAscii(); // returns true + +$asciiDomain = $domain->toAscii(); +echo $asciiDomain->value(); // display 'fass.de' +$asciiDomain->isAscii(); // returns true +~~~ + +> [!TIP] +> Always favor submitting a `Pdp\Domain` object for resolution rather that a +string or an object that can be cast to a string to avoid unexpected format +conversion errors/results. By default, and with lack of information conversion +is done using IDNA 2008 rules. + +### Managing the package external resources + +Depending on your application, the mechanism to store your resources may differ, +nevertheless, the library comes bundle with a **optional service** which +enables resolving domain name without the constant network overhead of +continuously downloading the remote databases. + +The interfaces and classes defined under the `Pdp\Storage` namespace enable +integrating a resource managing system and provide an implementation example +using PHP-FIG PSR interfaces. + +#### Using PHP-FIG interfaces + +The `Pdp\Storage\PsrStorageFactory` enables returning storage instances that +retrieve, convert and cache the Public Suffix List and the IANA Top Level +Domain List using standard interfaces published by the PHP-FIG. + +To work as intended, the `Pdp\Storage\PsrStorageFactory` constructor requires: + +- a [PSR-16](http://www.php-fig.org/psr/psr-16/) Simple Cache implementing library. +- a [PSR-17](http://www.php-fig.org/psr/psr-17/) HTTP Factory implementing library. +- a [PSR-18](http://www.php-fig.org/psr/psr-18/) HTTP Client implementing library. + +When creating a new storage instance you will require: + +- a `$cachePrefix` argument to optionally add a prefix to your cache index, +default to the empty string; +- a `$ttl` argument if you need to set the default `$ttl`, default to `null` +to use the underlying caching default TTL; + +The `$ttl` argument can be: + +- an `int` representing time in second (see PSR-16); +- a `DateInterval` object (see PSR-16); +- a `DateTimeInterface` object representing the date and time when the item +will expire; + +The package does not provide any implementation of such interfaces as you can +find [robust](https://packagist.org/providers/psr/simple-cache-implementation) +and [battle tested](https://packagist.org/providers/psr/http-client-implementation) +[implementations](https://packagist.org/providers/psr/http-factory-implementation) +on packagist. -Public Suffix validation is available by calling `Parser::isSuffixValid()`: +#### Refreshing the resource using the provided factories + +> [!NOTE] +> THIS IS THE RECOMMENDED WAY OF USING THE LIBRARY -``` -var_dump($parser->isSuffixValid('www.example.faketld'); -// false +For the purpose of this example we will use our PSR powered solution with: + +- *Guzzle HTTP Client* as our PSR-18 HTTP client; +- *Guzzle PSR-7 package* which provide factories to create a PSR-7 objects using PSR-17 interfaces; +- *Symfony Cache Component* as our PSR-16 cache implementation provider; + +We will cache both external sources for 24 hours in a PostgreSQL database. + +You are free to use other libraries/solutions/settings as long as they +implement the required PSR interfaces. -var_dump($parser->isSuffixValid('www.example.com.au'); -// true -``` +~~~php + PDO::ERRMODE_EXCEPTION] +); +$cache = new Psr16Cache(new PdoAdapter($pdo, 'pdp', 43200)); +$client = new GuzzleHttp\Client(); +$requestFactory = new class implements RequestFactoryInterface { + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } +}; -A suffix is considered invalid if it is not contained in the -[Public Suffix List](http://publicsuffix.org/). +$cachePrefix = 'pdp_'; +$cacheTtl = new DateInterval('P1D'); +$factory = new PsrStorageFactory($cache, $client, $requestFactory); +$pslStorage = $factory->createPublicSuffixListStorage($cachePrefix, $cacheTtl); +$rzdStorage = $factory->createTopLevelDomainListStorage($cachePrefix, $cacheTtl); -> Huge thanks to [@SmellyFish](https://github.com/SmellyFish) for submitting -> [Add a way to validate TLDs](https://github.com/jeremykendall/php-domain-parser/pull/36) -> to add public suffix validation to the project. +// if you need to force refreshing the rules +// before calling them (to use in a refresh script) +// uncomment this part or adapt it to you script logic +// $pslStorage->delete(PsrStorageFactory::PUBLIC_SUFFIX_LIST_URI); +$publicSuffixList = $pslStorage->get(PsrStorageFactory::PUBLIC_SUFFIX_LIST_URI); -### Retrieving Domain Components Only ### +// if you need to force refreshing the rules +// before calling them (to use in a refresh script) +// uncomment this part or adapt it to you script logic +// $rzdStorage->delete(PsrStorageFactory::TOP_LEVEL_DOMAIN_LIST_URI); +$topLevelDomains = $rzdStorage->get(PsrStorageFactory::TOP_LEVEL_DOMAIN_LIST_URI); +~~~ -If you're only interested in a domain component, you can use the parser to -retrieve only the component you're interested in +> [!NOTE] +> Be sure to adapt the following code to your own application. +The following code is an example given without warranty of it working +out of the box. -```php - [!WARNING] +> You should use your dependency injection container to avoid repeating this +code in your application. -var_dump($parser->getSubdomain('www.scottwills.co.uk')); -var_dump($parser->getRegistrableDomain('www.scottwills.co.uk')); -var_dump($parser->getPublicSuffix('www.scottwills.co.uk')); -``` +### Automatic Updates -The above will output: +It is important to always have an up to date Public Suffix List and Top Level +Domain List. +This library no longer provide an out of the box script to do so as implementing +such a job heavily depends on your application setup. +You can use the above example script as a starting point to implement such a job. -``` -string(3) "www" -string(16) "scottwills.co.uk" -string(5) "co.uk" -``` +Changelog +------- -### Sanity Check +Please see [CHANGELOG](CHANGELOG.md) for more information about what has been +changed since version **5.0.0** was released. -You can quickly parse a url from the command line with the provided `parse` -vendor binary. From the root of your project, simply call: +Contributing +------- -``` bash -$ ./vendor/bin/parse -``` +Contributions are welcome and will be fully credited. Please see +[CONTRIBUTING](.github/CONTRIBUTING.md) for details. -If you pass a url to `parse`, that url will be parsed and the output printed -to screen. +Testing +------- -If you do not pass a url, `http://user:pass@www.pref.okinawa.jp:8080/path/to/page.html?query=string#fragment` -will be parsed and the output printed to screen. +`pdp-domain-parser` has: -Example: +- a [PHPUnit](https://phpunit.de) test suite +- a code analysis compliance test suite using [PHPStan](https://phpstan.org). +- a coding style compliance test suite using [PHP CS Fixer](https://cs.symfony.com). -``` bash -$ ./vendor/bin/parse http://www.waxaudio.com.au/ - -Array -( - [scheme] => http - [user] => - [pass] => - [host] => www.waxaudio.com.au - [subdomain] => www - [registrableDomain] => waxaudio.com.au - [publicSuffix] => com.au - [port] => - [path] => / - [query] => - [fragment] => -) -Host: http://www.waxaudio.com.au/ -``` - -### Example Script - -For more information on using the PHP Domain Parser, please see the provided -[example script](https://github.com/jeremykendall/php-domain-parser/blob/master/example.php). - -### Refreshing the Public Suffix List - -While a cached PHP copy of the Public Suffix List is provided for you in the -`data` directory, that copy may or may not be up to date (Mozilla provides an -[Atom change feed](http://hg.mozilla.org/mozilla-central/atom-log/default/netwerk/dns/effective_tld_names.dat) -to keep up with changes to the list). Please use the provided vendor binary to -refresh your cached copy of the Public Suffix List. - -From the root of your project, simply call: +To run the tests, run the following command from the project folder. ``` bash -$ ./vendor/bin/update-psl +$ composer test ``` -You may verify the update by checking the timestamp on the files located in the -`data` directory. - -**Important**: The vendor binary `update-psl` depends on an internet connection to -update the cached Public Suffix List. - -## Possible Unexpected Behavior +Security +------- -PHP Domain Parser is built around PHP's -[`parse_url()`](http://php.net/parse_url) function and, as such, exhibits most -of the same behaviors of that function. Just like `parse_url()`, this library -is not meant to validate URLs, but rather to break a URL into its component -parts. +If you discover any security related issues, please email nyamsprod@gmail.com +instead of using the issue tracker. -One specific, counterintuitive behavior is that PHP Domain Parser will happily -parse a URL with [spaces in the host part](https://github.com/jeremykendall/php-domain-parser/issues/45). +Credits +------- -## Contributing +- [Jeremy Kendall](https://github.com/jeremykendall) +- [Ignace Nyamagana Butera](https://github.com/nyamsprod) +- [All Contributors](https://github.com/jeremykendall/php-domain-parser/contributors) -Pull requests are *always* welcome! Please review the CONTRIBUTING.md document before -submitting pull requests. +License +------- -## Heads up: BC Break In All 1.4 Versions +The MIT License (MIT). Please see [License File](LICENSE) for more information. -The 1.4 series introduced a backwards incompatible change by adding PHP's `ext-mbstring` -and `ext-intl` as dependencies. This should have resulted in a major version -bump. Instead I bumped the minor version from 1.3.1 to 1.4. +Attribution +------- -I highly recommend reverting to 1.3.1 if you're running into extension issues and -do not want to or cannot install `ext-mbstring` and `ext-intl`. You will lose -IDNA and IPv6 support, however. Those are only available in versions >= 1.4. - -I apologize for any issues you may have encountered due my -[semver](http://semver.org/) error. - -## Attribution +Portions of the `Pdp\Rules` class are derivative works of the PHP +[registered-domain-libs](https://github.com/usrflo/registered-domain-libs). +I've included a copy of the Apache Software Foundation License 2.0 in this project. -The HTTP adapter interface and the cURL HTTP adapter were inspired by (er, -lifted from) Will Durand's excellent -[Geocoder](https://github.com/willdurand/Geocoder) project. His MIT license and -copyright notice are below. +[ico-github-actions-build]: https://img.shields.io/github/actions/workflow/status/jeremykendall/php-domain-parser/build.yaml?branch=develop&style=flat-square +[ico-packagist]: https://img.shields.io/packagist/dt/jeremykendall/php-domain-parser.svg?style=flat-square +[ico-release]: https://img.shields.io/github/release/jeremykendall/php-domain-parser.svg?style=flat-square +[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square -``` -Copyright (c) 2011-2013 William Durand - -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. -``` - -Portions of the PublicSuffixListManager and the DomainParser are derivative -works of the PHP -[registered-domain-libs](https://github.com/usrflo/registered-domain-libs). -Those parts of this codebase are heavily commented, and I've included a copy of -the Apache Software Foundation License 2.0 in this project. +[link-github-actions-build]: https://github.com/jeremykendall/php-domain-parser/actions?query=workflow%3ABuild +[link-packagist]: https://packagist.org/packages/jeremykendall/php-domain-parser +[link-release]: https://github.com/jeremykendall/php-domain-parser/releases +[link-license]: https://github.com/jeremykendall/php-domain-parser/blob/master/LICENSE diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..a0a21d76 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,220 @@ +# PHP Domain Parser Upgrade Guide + +This guide will help you migrate from a 5.x version to 6.0.0. It will only +explain backward compatibility breaks, it will not present the new features +([read the documentation](README.md) for that). + +## 5.0 to 6.0 + +In order to take advantage of PHP new features, the library dropped the +support of **all versions before and including PHP 7.3**. The minimum supported +PHP version is now **PHP 7.4**. + +**Version 6.0 no longer provides an out-of-the-box resource manager system.** + +### Backward Incompatibility Changes + +Domains resolution uses the `IDNA2008` algorithm by default, in v5, +by default, it is done `IDNA2003` instead. + +```diff +resolve('faß.de')->__toString(); //returns 'fass.de' ++ echo $rules->resolve('faß.de')->toString(); //returns 'faß.de' +``` + +#### Domain resolution + +The `Pdp\Rules::resolve` and `Pdp\TopLevelDomains::resolve` returns a +`ResolvedDomain` object instead of a `Pdp\Domain` object, thus, the `Domain` +object no longer exposes the components from resolution, this is done by the +new `ResolvedDomain` object instead. + +```diff +resolve('faß.de')->labels(); //returns ['de', 'fass'] ++ $rules->resolve('faß.de')->domain()->labels(); //returns ['de', 'faß'] +``` + +Public suffix properties are not longer **directly** accessible on the +returned object. + +```diff +resolve('faß.de')->isICANN(); //returns true ++ $rules->resolve('faß.de')->suffix()->isICANN(); //returns true +``` + +Domain components are objects and no longer nullable scalar type. + +```diff +resolve('www.example.org')->registrableDomain(); //returns 'example.org' ++ $rules->resolve('www.example.org')->registrableDomain()->toString(); //returns 'example.org' +``` + +The `Domain` **no longer has access** to component information. Updating +the resolved component is done on the `ResolvedDomain` and no longer on the +`Domain` object. + +```diff +resolve('www.example.org')->withPublicSuffix('com'); //returns 'example.com' ++ echo $rules->resolve('www.example.org')->withSuffix('com')->toString(); //returns 'example.com' +``` + +The `Pdp\PublicSuffix` object is replaced by the more generic `Pdp\Suffix` object + +```diff +getPublicSuffix('www.example.org'); //returns 'Pdp\PublicSuffix' instance ++ echo $rules->resolve('www.example.org')->suffix(); //returns 'Pdp\Suffix' instance +``` + +The `Pdp\Suffix` class **no longer has direct access** to the underlying domain properties. + +```diff +getLabel(-1); //returns 'co'; ++ $suffix = Suffix::fromICANN('co.uk'); ++ $suffix->domain()->label(-1); //returns 'co'; +``` + +#### Normalizing domain resolution + +The `Pdp\Rules::resolve` and `Pdp\TopLevelDomains::resolve` domain resolution +rules are identical. They will always return a result even if the domain +contains a syntax error. + +```diff +resolve('####'); //throws an Exception ++ $result = $topLevelDomain->resolve('####'); //returns a ResolvedDomain object +``` + +#### Strict domain resolution + +Domain resolution is stricter with getter methods in version 6. If no +valid resolution is possible, because of the domain syntax or because +it is not possible in the given section. The method will throw instead +of returning a response object. + +```diff +getICANNDomain('toto.foobar')->isICANN(); //returns false +- $rules->getPrivateDomain('ulb.ac.be')->isPrivate(); //returns false ++ $rules->getICANNDomain('toto.foobar'); //will throw an exception ++ $rules->getPrivateDomain('ulb.ac.be'); //will throw an exception +``` + +#### Domain format + +- The `Domain::__toString` is removed use `Domain::toString` instead. +- The `Domain::getContent` is removed use `Domain::value` instead. +- The `Domain::getLabel` is removed use `Domain::label` instead. +- The `Domain` constructor is private. To instantiate a domain object you +need to use on of the two (2) named constructor `Domain::fromIDNA2008` or +`Domain::fromIDNA2008`. + +```diff +getContent(); // can be a string or null +- echo $domain; // display 'faß.de' +- $domain->getLabel(-1); // returns 'faß' ++ $domain = Domain::fromIDNA2008('faß.de'); ++ $domain->value(); // can be a string or null ++ echo $domain->toString(); // display 'faß.de' ++ $domain->label(-1); // returns 'faß' +``` + +#### Methods renamed + +- The `create` prefix is removed from all named constructors. +- The `get` prefix is removed from `TopLevelDomains` methods. + +```diff +getVersion(); //returns 2018082200 +- $topLevelDomains->getModifiedDate(); //returns \DateTimeImmutable object ++ $publicSuffixList = Rules::fromPath('path/to/public-suffix-data.dat'); ++ $topLevelDomains = TopLevelDomains::fromString($rootZoneInlineContent); ++ $topLevelDomains->version(); //returns 2018082200 ++ $topLevelDomains->lastUpdated(); //returns \DateTimeImmutable object +``` + +#### Resource manager system + +The resource manager system (containing caching and refreshing resource) is removed. + +- `HttpClient` is removed without replacement. +- `Cache` is removed without replacement. +- `Installer` is removed without replacement. +- `Logger` is removed without replacement. +- The CLI script to update the cache is removed without replacement. +- `Manager` is removed and may be replace by the use of `Pdp\Storage\PsrStorageFactory`. + +*Please check the [README](README.md) documentation for more details* + +#### Methods removed + +- `__toString` is removed from all classes. +- `__debugInfo` is removed from all classes. +- `DomainInterface` is removed use `DomainName` or `ResolvedDomainName` instead. +- `Domain::isResolvable` is removed without replacement. +- `Domain::resolve` is removed without replacement. +- `Rules::getPublicSuffix` is removed use `ResolvedDomain::suffix` instead. +- All v5 IDNA related methods are removed, IDNA is fully handle within the `Domain` object. + +#### Methods return type changed + +- `Domain::jsonSerialize` no longer returns an array but returns the string +representation or `null` to allow better compatibility with URL components +representation in other languages. + +```diff +resolve('www.example.com'); +- json_encode($result); // returns { +- "domain":"www.example.com", +- "registrableDomain":"example.com", +- "subDomain":"www", +- "publicSuffix":"com", +- "isKnown":true, +- "isICANN":true, +- "isPrivate":false +- } ++ json_encode($result); // returns '"www.example.com"' ++ echo json_encode([ ++ 'domain' => $result->value(), ++ 'registrableDomain' => $result->registrableDomain()->value(), ++ 'subDomain' => $result->subDomain()->value(), ++ 'publicSuffix' => $result->suffix()->value(), ++ 'isKnown' => $result->suffix()->isKnown(), ++ 'isICANN' => $result->suffix()->isICANN(), ++ 'isPrivate' => $result->suffix()->isPrivate(), ++ ]); // to get the v5 result +``` + +#### Objects instantiation + +- `Rules::__construct` +- `TopLevelDomains::__construct` +- `Domain::__construct` + +methods are now all private please use the provided named constructors instead. diff --git a/bin/parse b/bin/parse deleted file mode 100755 index 45640392..00000000 --- a/bin/parse +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env php -getList()); - $url = $parser->parseUrl($domain); - $suffixValid = ($parser->isSuffixValid((string) $url->getHost())) ? 'IS' : 'IS NOT'; - - print_r($url->toArray()); - echo sprintf('Host: %s', $url) . PHP_EOL; - echo sprintf( - "'%s' %s a valid public suffix.", - $url->getHost()->getPublicSuffix(), - $suffixValid - ) . PHP_EOL; -} catch (\Exception $e) { - die($e->getMessage() . PHP_EOL); -} diff --git a/bin/update-psl b/bin/update-psl deleted file mode 100755 index ea1588a6..00000000 --- a/bin/update-psl +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env php -refreshPublicSuffixList(); - echo 'Update complete.' . PHP_EOL; - exit(0); -} catch (\Exception $e) { - echo 'An error occurred while updating the Public Suffix List.' . PHP_EOL; - echo $e->getMessage() . PHP_EOL; - exit(1); -} diff --git a/build.properties b/build.properties deleted file mode 100644 index 16caf0e8..00000000 --- a/build.properties +++ /dev/null @@ -1,2 +0,0 @@ -project.basedir = . -passthru = true diff --git a/build.xml b/build.xml deleted file mode 100644 index 85d0143f..00000000 --- a/build.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/composer.json b/composer.json index 73823c4b..245e9d22 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "jeremykendall/php-domain-parser", - "description": "Public Suffix List based URL parsing implemented in PHP.", + "description": "Public Suffix List and IANA Root Zone Database based Domain parsing implemented in PHP.", "homepage": "https://github.com/jeremykendall/php-domain-parser", "support": { "issues": "https://github.com/jeremykendall/php-domain-parser/issues", @@ -10,7 +10,12 @@ "authors": [ { "name": "Jeremy Kendall", - "homepage": "http://about.me/jeremykendall", + "homepage": "https://about.me/jeremykendall", + "role": "Developer" + }, + { + "name": "Ignace Nyamagana Butera", + "homepage": "https://nyamsprod.com", "role": "Developer" }, { @@ -18,37 +23,77 @@ "homepage": "https://github.com/jeremykendall/php-domain-parser/graphs/contributors" } ], - "bin": [ - "bin/parse", - "bin/update-psl" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nyamsprod" + } ], "keywords": [ "Public Suffix List", + "Top Level Domains", "domain parsing", - "url parsing" + "icann", + "iana", + "idn", + "tld", + "psl" ], "require": { - "php": ">=5.3.0", - "ext-curl": "*", - "ext-intl": "*", - "ext-mbstring": "*" + "php": "^8.1", + "ext-filter": "*" }, "require-dev": { - "mikey179/vfsStream": "~1.6", - "phpunit/phpunit": "~4.8", - "jeremykendall/debug-die": "0.0.1.*", - "phing/phing": "^2.13", - "fabpot/php-cs-fixer": "^1.11" + "friendsofphp/php-cs-fixer": "^3.65.0", + "guzzlehttp/guzzle": "^7.9.2", + "guzzlehttp/psr7": "^1.6 || ^2.7.0", + "phpstan/phpstan": "^1.12.13", + "phpstan/phpstan-phpunit": "^1.4.2", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^10.5.15 || ^11.5.1", + "psr/http-factory": "^1.1.0", + "psr/simple-cache": "^1.0.1 || ^2.0.0", + "symfony/cache": "^v5.0.0 || ^6.4.16", + "symfony/var-dumper": "^v6.4.18 || ^7.2" + }, + "suggest": { + "psr/http-client-implementation": "To use the storage functionality which depends on PSR-18", + "psr/http-factory-implementation": "To use the storage functionality which depends on PSR-17", + "psr/simple-cache-implementation": "To use the storage functionality which depends on PSR-16", + "league/uri": "To parse and extract the host from an URL using a RFC3986/RFC3987 URI parser", + "rowbot/url": "To parse and extract the host from an URL using a WHATWG URL parser", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "autoload": { - "psr-0": { + "psr-4": { "Pdp\\": "src/" - }, - "files": [ - "src/pdp-parse-url.php" - ] + } }, "scripts": { - "post-install-cmd": "php bin/update-psl" + "phpcs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -vvv --diff --dry-run --allow-risky=yes --ansi", + "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi", + "phpstan": "phpstan analyse -c phpstan.neon --ansi --memory-limit=192M", + "phpunit": "XDEBUG_MODE=coverage phpunit --coverage-text", + "phpunit:min": "phpunit --no-coverage", + "test": [ + "@phpunit", + "@phpstan", + "@phpcs" + ] + }, + "scripts-descriptions": { + "phpcs": "Runs coding style test suite", + "phpcs:fix": "Fix the package coding style", + "phpstan": "Runs complete codebase static analysis", + "phpunit": "Runs unit and functional testing", + "test": "Runs the complete test suite" + }, + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "config": { + "sort-packages": true } } diff --git a/data/public-suffix-list.php b/data/public-suffix-list.php deleted file mode 100644 index 49e02d86..00000000 --- a/data/public-suffix-list.php +++ /dev/null @@ -1,23700 +0,0 @@ - - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'mil' => - array ( - ), - 'org' => - array ( - ), - ), - 'ad' => - array ( - 'nom' => - array ( - ), - ), - 'ae' => - array ( - 'co' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sch' => - array ( - ), - 'ac' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'aero' => - array ( - 'accident-investigation' => - array ( - ), - 'accident-prevention' => - array ( - ), - 'aerobatic' => - array ( - ), - 'aeroclub' => - array ( - ), - 'aerodrome' => - array ( - ), - 'agents' => - array ( - ), - 'aircraft' => - array ( - ), - 'airline' => - array ( - ), - 'airport' => - array ( - ), - 'air-surveillance' => - array ( - ), - 'airtraffic' => - array ( - ), - 'air-traffic-control' => - array ( - ), - 'ambulance' => - array ( - ), - 'amusement' => - array ( - ), - 'association' => - array ( - ), - 'author' => - array ( - ), - 'ballooning' => - array ( - ), - 'broker' => - array ( - ), - 'caa' => - array ( - ), - 'cargo' => - array ( - ), - 'catering' => - array ( - ), - 'certification' => - array ( - ), - 'championship' => - array ( - ), - 'charter' => - array ( - ), - 'civilaviation' => - array ( - ), - 'club' => - array ( - ), - 'conference' => - array ( - ), - 'consultant' => - array ( - ), - 'consulting' => - array ( - ), - 'control' => - array ( - ), - 'council' => - array ( - ), - 'crew' => - array ( - ), - 'design' => - array ( - ), - 'dgca' => - array ( - ), - 'educator' => - array ( - ), - 'emergency' => - array ( - ), - 'engine' => - array ( - ), - 'engineer' => - array ( - ), - 'entertainment' => - array ( - ), - 'equipment' => - array ( - ), - 'exchange' => - array ( - ), - 'express' => - array ( - ), - 'federation' => - array ( - ), - 'flight' => - array ( - ), - 'freight' => - array ( - ), - 'fuel' => - array ( - ), - 'gliding' => - array ( - ), - 'government' => - array ( - ), - 'groundhandling' => - array ( - ), - 'group' => - array ( - ), - 'hanggliding' => - array ( - ), - 'homebuilt' => - array ( - ), - 'insurance' => - array ( - ), - 'journal' => - array ( - ), - 'journalist' => - array ( - ), - 'leasing' => - array ( - ), - 'logistics' => - array ( - ), - 'magazine' => - array ( - ), - 'maintenance' => - array ( - ), - 'media' => - array ( - ), - 'microlight' => - array ( - ), - 'modelling' => - array ( - ), - 'navigation' => - array ( - ), - 'parachuting' => - array ( - ), - 'paragliding' => - array ( - ), - 'passenger-association' => - array ( - ), - 'pilot' => - array ( - ), - 'press' => - array ( - ), - 'production' => - array ( - ), - 'recreation' => - array ( - ), - 'repbody' => - array ( - ), - 'res' => - array ( - ), - 'research' => - array ( - ), - 'rotorcraft' => - array ( - ), - 'safety' => - array ( - ), - 'scientist' => - array ( - ), - 'services' => - array ( - ), - 'show' => - array ( - ), - 'skydiving' => - array ( - ), - 'software' => - array ( - ), - 'student' => - array ( - ), - 'trader' => - array ( - ), - 'trading' => - array ( - ), - 'trainer' => - array ( - ), - 'union' => - array ( - ), - 'workinggroup' => - array ( - ), - 'works' => - array ( - ), - ), - 'af' => - array ( - 'gov' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - ), - 'ag' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'co' => - array ( - ), - 'nom' => - array ( - ), - ), - 'ai' => - array ( - 'off' => - array ( - ), - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'al' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'am' => - array ( - 'blogspot' => - array ( - ), - ), - 'ao' => - array ( - 'ed' => - array ( - ), - 'gv' => - array ( - ), - 'og' => - array ( - ), - 'co' => - array ( - ), - 'pb' => - array ( - ), - 'it' => - array ( - ), - ), - 'aq' => - array ( - ), - 'ar' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'gob' => - array ( - ), - 'gov' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'tur' => - array ( - ), - ), - 'arpa' => - array ( - 'e164' => - array ( - ), - 'in-addr' => - array ( - ), - 'ip6' => - array ( - ), - 'iris' => - array ( - ), - 'uri' => - array ( - ), - 'urn' => - array ( - ), - ), - 'as' => - array ( - 'gov' => - array ( - ), - ), - 'asia' => - array ( - ), - 'at' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'gv' => - array ( - ), - 'or' => - array ( - ), - 'biz' => - array ( - ), - 'info' => - array ( - ), - 'priv' => - array ( - ), - ), - 'au' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - 'act' => - array ( - ), - 'nsw' => - array ( - ), - 'nt' => - array ( - ), - 'qld' => - array ( - ), - 'sa' => - array ( - ), - 'tas' => - array ( - ), - 'vic' => - array ( - ), - 'wa' => - array ( - ), - ), - 'gov' => - array ( - 'qld' => - array ( - ), - 'sa' => - array ( - ), - 'tas' => - array ( - ), - 'vic' => - array ( - ), - 'wa' => - array ( - ), - ), - 'asn' => - array ( - ), - 'id' => - array ( - ), - 'info' => - array ( - ), - 'conf' => - array ( - ), - 'oz' => - array ( - ), - 'act' => - array ( - ), - 'nsw' => - array ( - ), - 'nt' => - array ( - ), - 'qld' => - array ( - ), - 'sa' => - array ( - ), - 'tas' => - array ( - ), - 'vic' => - array ( - ), - 'wa' => - array ( - ), - ), - 'aw' => - array ( - 'com' => - array ( - ), - ), - 'ax' => - array ( - ), - 'az' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'int' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'info' => - array ( - ), - 'pp' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - 'pro' => - array ( - ), - 'biz' => - array ( - ), - ), - 'ba' => - array ( - 'org' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'unsa' => - array ( - ), - 'unbi' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'rs' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'bb' => - array ( - 'biz' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'store' => - array ( - ), - 'tv' => - array ( - ), - ), - 'bd' => - array ( - '*' => - array ( - ), - ), - 'be' => - array ( - 'ac' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'bf' => - array ( - 'gov' => - array ( - ), - ), - 'bg' => - array ( - 'a' => - array ( - ), - 'b' => - array ( - ), - 'c' => - array ( - ), - 'd' => - array ( - ), - 'e' => - array ( - ), - 'f' => - array ( - ), - 'g' => - array ( - ), - 'h' => - array ( - ), - 'i' => - array ( - ), - 'j' => - array ( - ), - 'k' => - array ( - ), - 'l' => - array ( - ), - 'm' => - array ( - ), - 'n' => - array ( - ), - 'o' => - array ( - ), - 'p' => - array ( - ), - 'q' => - array ( - ), - 'r' => - array ( - ), - 's' => - array ( - ), - 't' => - array ( - ), - 'u' => - array ( - ), - 'v' => - array ( - ), - 'w' => - array ( - ), - 'x' => - array ( - ), - 'y' => - array ( - ), - 'z' => - array ( - ), - 0 => - array ( - ), - 1 => - array ( - ), - 2 => - array ( - ), - 3 => - array ( - ), - 4 => - array ( - ), - 5 => - array ( - ), - 6 => - array ( - ), - 7 => - array ( - ), - 8 => - array ( - ), - 9 => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'bh' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - ), - 'bi' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'or' => - array ( - ), - 'org' => - array ( - ), - ), - 'biz' => - array ( - 'dyndns' => - array ( - ), - 'for-better' => - array ( - ), - 'for-more' => - array ( - ), - 'for-some' => - array ( - ), - 'for-the' => - array ( - ), - 'selfip' => - array ( - ), - 'webhop' => - array ( - ), - 'dscloud' => - array ( - ), - ), - 'bj' => - array ( - 'asso' => - array ( - ), - 'barreau' => - array ( - ), - 'gouv' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'bm' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'bn' => - array ( - '*' => - array ( - ), - ), - 'bo' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'gob' => - array ( - ), - 'int' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'mil' => - array ( - ), - 'tv' => - array ( - ), - ), - 'br' => - array ( - 'adm' => - array ( - ), - 'adv' => - array ( - ), - 'agr' => - array ( - ), - 'am' => - array ( - ), - 'arq' => - array ( - ), - 'art' => - array ( - ), - 'ato' => - array ( - ), - 'b' => - array ( - ), - 'bio' => - array ( - ), - 'blog' => - array ( - ), - 'bmd' => - array ( - ), - 'cim' => - array ( - ), - 'cng' => - array ( - ), - 'cnt' => - array ( - ), - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'coop' => - array ( - ), - 'ecn' => - array ( - ), - 'eco' => - array ( - ), - 'edu' => - array ( - ), - 'emp' => - array ( - ), - 'eng' => - array ( - ), - 'esp' => - array ( - ), - 'etc' => - array ( - ), - 'eti' => - array ( - ), - 'far' => - array ( - ), - 'flog' => - array ( - ), - 'fm' => - array ( - ), - 'fnd' => - array ( - ), - 'fot' => - array ( - ), - 'fst' => - array ( - ), - 'g12' => - array ( - ), - 'ggf' => - array ( - ), - 'gov' => - array ( - ), - 'imb' => - array ( - ), - 'ind' => - array ( - ), - 'inf' => - array ( - ), - 'jor' => - array ( - ), - 'jus' => - array ( - ), - 'leg' => - array ( - ), - 'lel' => - array ( - ), - 'mat' => - array ( - ), - 'med' => - array ( - ), - 'mil' => - array ( - ), - 'mp' => - array ( - ), - 'mus' => - array ( - ), - 'net' => - array ( - ), - 'nom' => - array ( - '*' => - array ( - ), - ), - 'not' => - array ( - ), - 'ntr' => - array ( - ), - 'odo' => - array ( - ), - 'org' => - array ( - ), - 'ppg' => - array ( - ), - 'pro' => - array ( - ), - 'psc' => - array ( - ), - 'psi' => - array ( - ), - 'qsl' => - array ( - ), - 'radio' => - array ( - ), - 'rec' => - array ( - ), - 'slg' => - array ( - ), - 'srv' => - array ( - ), - 'taxi' => - array ( - ), - 'teo' => - array ( - ), - 'tmp' => - array ( - ), - 'trd' => - array ( - ), - 'tur' => - array ( - ), - 'tv' => - array ( - ), - 'vet' => - array ( - ), - 'vlog' => - array ( - ), - 'wiki' => - array ( - ), - 'zlg' => - array ( - ), - ), - 'bs' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - ), - 'bt' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'bv' => - array ( - ), - 'bw' => - array ( - 'co' => - array ( - ), - 'org' => - array ( - ), - ), - 'by' => - array ( - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'of' => - array ( - ), - ), - 'bz' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'za' => - array ( - ), - ), - 'ca' => - array ( - 'ab' => - array ( - ), - 'bc' => - array ( - ), - 'mb' => - array ( - ), - 'nb' => - array ( - ), - 'nf' => - array ( - ), - 'nl' => - array ( - ), - 'ns' => - array ( - ), - 'nt' => - array ( - ), - 'nu' => - array ( - ), - 'on' => - array ( - ), - 'pe' => - array ( - ), - 'qc' => - array ( - ), - 'sk' => - array ( - ), - 'yk' => - array ( - ), - 'gc' => - array ( - ), - 'co' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'cat' => - array ( - ), - 'cc' => - array ( - 'ftpaccess' => - array ( - ), - 'game-server' => - array ( - ), - 'myphotos' => - array ( - ), - 'scrapping' => - array ( - ), - ), - 'cd' => - array ( - 'gov' => - array ( - ), - ), - 'cf' => - array ( - 'blogspot' => - array ( - ), - ), - 'cg' => - array ( - ), - 'ch' => - array ( - 'blogspot' => - array ( - ), - ), - 'ci' => - array ( - 'org' => - array ( - ), - 'or' => - array ( - ), - 'com' => - array ( - ), - 'co' => - array ( - ), - 'edu' => - array ( - ), - 'ed' => - array ( - ), - 'ac' => - array ( - ), - 'net' => - array ( - ), - 'go' => - array ( - ), - 'asso' => - array ( - ), - 'xn--aroport-bya' => - array ( - ), - 'int' => - array ( - ), - 'presse' => - array ( - ), - 'md' => - array ( - ), - 'gouv' => - array ( - ), - ), - 'ck' => - array ( - '*' => - array ( - ), - 'www' => - array ( - '!' => '', - ), - ), - 'cl' => - array ( - 'gov' => - array ( - ), - 'gob' => - array ( - ), - 'co' => - array ( - ), - 'mil' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'cm' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - ), - 'cn' => - array ( - 'ac' => - array ( - ), - 'com' => - array ( - 'amazonaws' => - array ( - 'cn-north-1' => - array ( - 's3' => - array ( - ), - ), - ), - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'mil' => - array ( - ), - 'xn--55qx5d' => - array ( - ), - 'xn--io0a7i' => - array ( - ), - 'xn--od0alg' => - array ( - ), - 'ah' => - array ( - ), - 'bj' => - array ( - ), - 'cq' => - array ( - ), - 'fj' => - array ( - ), - 'gd' => - array ( - ), - 'gs' => - array ( - ), - 'gz' => - array ( - ), - 'gx' => - array ( - ), - 'ha' => - array ( - ), - 'hb' => - array ( - ), - 'he' => - array ( - ), - 'hi' => - array ( - ), - 'hl' => - array ( - ), - 'hn' => - array ( - ), - 'jl' => - array ( - ), - 'js' => - array ( - ), - 'jx' => - array ( - ), - 'ln' => - array ( - ), - 'nm' => - array ( - ), - 'nx' => - array ( - ), - 'qh' => - array ( - ), - 'sc' => - array ( - ), - 'sd' => - array ( - ), - 'sh' => - array ( - ), - 'sn' => - array ( - ), - 'sx' => - array ( - ), - 'tj' => - array ( - ), - 'xj' => - array ( - ), - 'xz' => - array ( - ), - 'yn' => - array ( - ), - 'zj' => - array ( - ), - 'hk' => - array ( - ), - 'mo' => - array ( - ), - 'tw' => - array ( - ), - 'amazonaws' => - array ( - 'compute' => - array ( - 'cn-north-1' => - array ( - ), - ), - ), - ), - 'co' => - array ( - 'arts' => - array ( - ), - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'firm' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'nom' => - array ( - ), - 'org' => - array ( - ), - 'rec' => - array ( - ), - 'web' => - array ( - ), - ), - 'com' => - array ( - 'amazonaws' => - array ( - 'compute' => - array ( - 'ap-northeast-1' => - array ( - ), - 'ap-southeast-1' => - array ( - ), - 'ap-southeast-2' => - array ( - ), - 'eu-west-1' => - array ( - ), - 'eu-central-1' => - array ( - ), - 'sa-east-1' => - array ( - ), - 'us-gov-west-1' => - array ( - ), - 'us-west-1' => - array ( - ), - 'us-west-2' => - array ( - ), - ), - 'compute-1' => - array ( - 'z-1' => - array ( - ), - 'z-2' => - array ( - ), - ), - 'us-east-1' => - array ( - ), - 'elb' => - array ( - ), - 's3' => - array ( - ), - 's3-ap-northeast-1' => - array ( - ), - 's3-ap-southeast-1' => - array ( - ), - 's3-ap-southeast-2' => - array ( - ), - 's3-external-1' => - array ( - ), - 's3-external-2' => - array ( - ), - 's3-fips-us-gov-west-1' => - array ( - ), - 's3-eu-central-1' => - array ( - ), - 's3-eu-west-1' => - array ( - ), - 's3-sa-east-1' => - array ( - ), - 's3-us-gov-west-1' => - array ( - ), - 's3-us-west-1' => - array ( - ), - 's3-us-west-2' => - array ( - ), - 'eu-central-1' => - array ( - 's3' => - array ( - ), - ), - ), - 'elasticbeanstalk' => - array ( - ), - 'betainabox' => - array ( - ), - 'ar' => - array ( - ), - 'br' => - array ( - ), - 'cn' => - array ( - ), - 'de' => - array ( - ), - 'eu' => - array ( - ), - 'gb' => - array ( - ), - 'hu' => - array ( - ), - 'jpn' => - array ( - ), - 'kr' => - array ( - ), - 'mex' => - array ( - ), - 'no' => - array ( - ), - 'qc' => - array ( - ), - 'ru' => - array ( - ), - 'sa' => - array ( - ), - 'se' => - array ( - ), - 'uk' => - array ( - ), - 'us' => - array ( - ), - 'uy' => - array ( - ), - 'za' => - array ( - ), - 'africa' => - array ( - ), - 'gr' => - array ( - ), - 'co' => - array ( - ), - 'cloudcontrolled' => - array ( - ), - 'cloudcontrolapp' => - array ( - ), - 'dreamhosters' => - array ( - ), - 'mydrobo' => - array ( - ), - 'dyndns-at-home' => - array ( - ), - 'dyndns-at-work' => - array ( - ), - 'dyndns-blog' => - array ( - ), - 'dyndns-free' => - array ( - ), - 'dyndns-home' => - array ( - ), - 'dyndns-ip' => - array ( - ), - 'dyndns-mail' => - array ( - ), - 'dyndns-office' => - array ( - ), - 'dyndns-pics' => - array ( - ), - 'dyndns-remote' => - array ( - ), - 'dyndns-server' => - array ( - ), - 'dyndns-web' => - array ( - ), - 'dyndns-wiki' => - array ( - ), - 'dyndns-work' => - array ( - ), - 'blogdns' => - array ( - ), - 'cechire' => - array ( - ), - 'dnsalias' => - array ( - ), - 'dnsdojo' => - array ( - ), - 'doesntexist' => - array ( - ), - 'dontexist' => - array ( - ), - 'doomdns' => - array ( - ), - 'dyn-o-saur' => - array ( - ), - 'dynalias' => - array ( - ), - 'est-a-la-maison' => - array ( - ), - 'est-a-la-masion' => - array ( - ), - 'est-le-patron' => - array ( - ), - 'est-mon-blogueur' => - array ( - ), - 'from-ak' => - array ( - ), - 'from-al' => - array ( - ), - 'from-ar' => - array ( - ), - 'from-ca' => - array ( - ), - 'from-ct' => - array ( - ), - 'from-dc' => - array ( - ), - 'from-de' => - array ( - ), - 'from-fl' => - array ( - ), - 'from-ga' => - array ( - ), - 'from-hi' => - array ( - ), - 'from-ia' => - array ( - ), - 'from-id' => - array ( - ), - 'from-il' => - array ( - ), - 'from-in' => - array ( - ), - 'from-ks' => - array ( - ), - 'from-ky' => - array ( - ), - 'from-ma' => - array ( - ), - 'from-md' => - array ( - ), - 'from-mi' => - array ( - ), - 'from-mn' => - array ( - ), - 'from-mo' => - array ( - ), - 'from-ms' => - array ( - ), - 'from-mt' => - array ( - ), - 'from-nc' => - array ( - ), - 'from-nd' => - array ( - ), - 'from-ne' => - array ( - ), - 'from-nh' => - array ( - ), - 'from-nj' => - array ( - ), - 'from-nm' => - array ( - ), - 'from-nv' => - array ( - ), - 'from-oh' => - array ( - ), - 'from-ok' => - array ( - ), - 'from-or' => - array ( - ), - 'from-pa' => - array ( - ), - 'from-pr' => - array ( - ), - 'from-ri' => - array ( - ), - 'from-sc' => - array ( - ), - 'from-sd' => - array ( - ), - 'from-tn' => - array ( - ), - 'from-tx' => - array ( - ), - 'from-ut' => - array ( - ), - 'from-va' => - array ( - ), - 'from-vt' => - array ( - ), - 'from-wa' => - array ( - ), - 'from-wi' => - array ( - ), - 'from-wv' => - array ( - ), - 'from-wy' => - array ( - ), - 'getmyip' => - array ( - ), - 'gotdns' => - array ( - ), - 'hobby-site' => - array ( - ), - 'homelinux' => - array ( - ), - 'homeunix' => - array ( - ), - 'iamallama' => - array ( - ), - 'is-a-anarchist' => - array ( - ), - 'is-a-blogger' => - array ( - ), - 'is-a-bookkeeper' => - array ( - ), - 'is-a-bulls-fan' => - array ( - ), - 'is-a-caterer' => - array ( - ), - 'is-a-chef' => - array ( - ), - 'is-a-conservative' => - array ( - ), - 'is-a-cpa' => - array ( - ), - 'is-a-cubicle-slave' => - array ( - ), - 'is-a-democrat' => - array ( - ), - 'is-a-designer' => - array ( - ), - 'is-a-doctor' => - array ( - ), - 'is-a-financialadvisor' => - array ( - ), - 'is-a-geek' => - array ( - ), - 'is-a-green' => - array ( - ), - 'is-a-guru' => - array ( - ), - 'is-a-hard-worker' => - array ( - ), - 'is-a-hunter' => - array ( - ), - 'is-a-landscaper' => - array ( - ), - 'is-a-lawyer' => - array ( - ), - 'is-a-liberal' => - array ( - ), - 'is-a-libertarian' => - array ( - ), - 'is-a-llama' => - array ( - ), - 'is-a-musician' => - array ( - ), - 'is-a-nascarfan' => - array ( - ), - 'is-a-nurse' => - array ( - ), - 'is-a-painter' => - array ( - ), - 'is-a-personaltrainer' => - array ( - ), - 'is-a-photographer' => - array ( - ), - 'is-a-player' => - array ( - ), - 'is-a-republican' => - array ( - ), - 'is-a-rockstar' => - array ( - ), - 'is-a-socialist' => - array ( - ), - 'is-a-student' => - array ( - ), - 'is-a-teacher' => - array ( - ), - 'is-a-techie' => - array ( - ), - 'is-a-therapist' => - array ( - ), - 'is-an-accountant' => - array ( - ), - 'is-an-actor' => - array ( - ), - 'is-an-actress' => - array ( - ), - 'is-an-anarchist' => - array ( - ), - 'is-an-artist' => - array ( - ), - 'is-an-engineer' => - array ( - ), - 'is-an-entertainer' => - array ( - ), - 'is-certified' => - array ( - ), - 'is-gone' => - array ( - ), - 'is-into-anime' => - array ( - ), - 'is-into-cars' => - array ( - ), - 'is-into-cartoons' => - array ( - ), - 'is-into-games' => - array ( - ), - 'is-leet' => - array ( - ), - 'is-not-certified' => - array ( - ), - 'is-slick' => - array ( - ), - 'is-uberleet' => - array ( - ), - 'is-with-theband' => - array ( - ), - 'isa-geek' => - array ( - ), - 'isa-hockeynut' => - array ( - ), - 'issmarterthanyou' => - array ( - ), - 'likes-pie' => - array ( - ), - 'likescandy' => - array ( - ), - 'neat-url' => - array ( - ), - 'saves-the-whales' => - array ( - ), - 'selfip' => - array ( - ), - 'sells-for-less' => - array ( - ), - 'sells-for-u' => - array ( - ), - 'servebbs' => - array ( - ), - 'simple-url' => - array ( - ), - 'space-to-rent' => - array ( - ), - 'teaches-yoga' => - array ( - ), - 'writesthisblog' => - array ( - ), - 'firebaseapp' => - array ( - ), - 'flynnhub' => - array ( - ), - 'githubusercontent' => - array ( - ), - 'ro' => - array ( - ), - 'appspot' => - array ( - ), - 'blogspot' => - array ( - ), - 'codespot' => - array ( - ), - 'googleapis' => - array ( - ), - 'googlecode' => - array ( - ), - 'pagespeedmobilizer' => - array ( - ), - 'withgoogle' => - array ( - ), - 'withyoutube' => - array ( - ), - 'herokuapp' => - array ( - ), - 'herokussl' => - array ( - ), - '4u' => - array ( - ), - 'nfshost' => - array ( - ), - 'operaunite' => - array ( - ), - 'outsystemscloud' => - array ( - ), - 'pagefrontapp' => - array ( - ), - 'gotpantheon' => - array ( - ), - 'prgmr' => - array ( - 'xen' => - array ( - ), - ), - 'qa2' => - array ( - ), - 'rackmaze' => - array ( - ), - 'rhcloud' => - array ( - ), - 'sinaapp' => - array ( - ), - 'vipsinaapp' => - array ( - ), - '1kapp' => - array ( - ), - 'dsmynas' => - array ( - ), - 'familyds' => - array ( - ), - 'hk' => - array ( - ), - 'yolasite' => - array ( - ), - ), - 'coop' => - array ( - ), - 'cr' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'ed' => - array ( - ), - 'fi' => - array ( - ), - 'go' => - array ( - ), - 'or' => - array ( - ), - 'sa' => - array ( - ), - ), - 'cu' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'inf' => - array ( - ), - ), - 'cv' => - array ( - 'blogspot' => - array ( - ), - ), - 'cw' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'cx' => - array ( - 'gov' => - array ( - ), - 'ath' => - array ( - ), - ), - 'cy' => - array ( - 'ac' => - array ( - ), - 'biz' => - array ( - ), - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'ekloges' => - array ( - ), - 'gov' => - array ( - ), - 'ltd' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'parliament' => - array ( - ), - 'press' => - array ( - ), - 'pro' => - array ( - ), - 'tm' => - array ( - ), - ), - 'cz' => - array ( - 'co' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'de' => - array ( - 'com' => - array ( - ), - 'fuettertdasnetz' => - array ( - ), - 'isteingeek' => - array ( - ), - 'istmein' => - array ( - ), - 'lebtimnetz' => - array ( - ), - 'leitungsen' => - array ( - ), - 'traeumtgerade' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'dj' => - array ( - ), - 'dk' => - array ( - 'blogspot' => - array ( - ), - ), - 'dm' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - ), - 'do' => - array ( - 'art' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gob' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sld' => - array ( - ), - 'web' => - array ( - ), - ), - 'dz' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'asso' => - array ( - ), - 'pol' => - array ( - ), - 'art' => - array ( - ), - ), - 'ec' => - array ( - 'com' => - array ( - ), - 'info' => - array ( - ), - 'net' => - array ( - ), - 'fin' => - array ( - ), - 'k12' => - array ( - ), - 'med' => - array ( - ), - 'pro' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'gob' => - array ( - ), - 'mil' => - array ( - ), - ), - 'edu' => - array ( - ), - 'ee' => - array ( - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'riik' => - array ( - ), - 'lib' => - array ( - ), - 'med' => - array ( - ), - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'pri' => - array ( - ), - 'aip' => - array ( - ), - 'org' => - array ( - ), - 'fie' => - array ( - ), - ), - 'eg' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'eun' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sci' => - array ( - ), - ), - 'er' => - array ( - '*' => - array ( - ), - ), - 'es' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'nom' => - array ( - ), - 'org' => - array ( - ), - 'gob' => - array ( - ), - 'edu' => - array ( - ), - ), - 'et' => - array ( - 'com' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'biz' => - array ( - ), - 'name' => - array ( - ), - 'info' => - array ( - ), - 'net' => - array ( - ), - ), - 'eu' => - array ( - ), - 'fi' => - array ( - 'aland' => - array ( - ), - 'blogspot' => - array ( - ), - 'iki' => - array ( - ), - ), - 'fj' => - array ( - '*' => - array ( - ), - ), - 'fk' => - array ( - '*' => - array ( - ), - ), - 'fm' => - array ( - ), - 'fo' => - array ( - ), - 'fr' => - array ( - 'com' => - array ( - ), - 'asso' => - array ( - ), - 'nom' => - array ( - ), - 'prd' => - array ( - ), - 'presse' => - array ( - ), - 'tm' => - array ( - ), - 'aeroport' => - array ( - ), - 'assedic' => - array ( - ), - 'avocat' => - array ( - ), - 'avoues' => - array ( - ), - 'cci' => - array ( - ), - 'chambagri' => - array ( - ), - 'chirurgiens-dentistes' => - array ( - ), - 'experts-comptables' => - array ( - ), - 'geometre-expert' => - array ( - ), - 'gouv' => - array ( - ), - 'greta' => - array ( - ), - 'huissier-justice' => - array ( - ), - 'medecin' => - array ( - ), - 'notaires' => - array ( - ), - 'pharmacien' => - array ( - ), - 'port' => - array ( - ), - 'veterinaire' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ga' => - array ( - ), - 'gb' => - array ( - ), - 'gd' => - array ( - ), - 'ge' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'pvt' => - array ( - ), - ), - 'gf' => - array ( - ), - 'gg' => - array ( - 'co' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'gh' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'mil' => - array ( - ), - ), - 'gi' => - array ( - 'com' => - array ( - ), - 'ltd' => - array ( - ), - 'gov' => - array ( - ), - 'mod' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - ), - 'gl' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'gm' => - array ( - ), - 'gn' => - array ( - 'ac' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - ), - 'gov' => - array ( - ), - 'gp' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'mobi' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'asso' => - array ( - ), - ), - 'gq' => - array ( - ), - 'gr' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'gs' => - array ( - ), - 'gt' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gob' => - array ( - ), - 'ind' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'gu' => - array ( - '*' => - array ( - ), - ), - 'gw' => - array ( - ), - 'gy' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'hk' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'idv' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'xn--55qx5d' => - array ( - ), - 'xn--wcvs22d' => - array ( - ), - 'xn--lcvr32d' => - array ( - ), - 'xn--mxtq1m' => - array ( - ), - 'xn--gmqw5a' => - array ( - ), - 'xn--ciqpn' => - array ( - ), - 'xn--gmq050i' => - array ( - ), - 'xn--zf0avx' => - array ( - ), - 'xn--io0a7i' => - array ( - ), - 'xn--mk0axi' => - array ( - ), - 'xn--od0alg' => - array ( - ), - 'xn--od0aq3b' => - array ( - ), - 'xn--tn0ag' => - array ( - ), - 'xn--uc0atv' => - array ( - ), - 'xn--uc0ay4a' => - array ( - ), - 'blogspot' => - array ( - ), - 'ltd' => - array ( - ), - 'inc' => - array ( - ), - ), - 'hm' => - array ( - ), - 'hn' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'mil' => - array ( - ), - 'gob' => - array ( - ), - ), - 'hr' => - array ( - 'iz' => - array ( - ), - 'from' => - array ( - ), - 'name' => - array ( - ), - 'com' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ht' => - array ( - 'com' => - array ( - ), - 'shop' => - array ( - ), - 'firm' => - array ( - ), - 'info' => - array ( - ), - 'adult' => - array ( - ), - 'net' => - array ( - ), - 'pro' => - array ( - ), - 'org' => - array ( - ), - 'med' => - array ( - ), - 'art' => - array ( - ), - 'coop' => - array ( - ), - 'pol' => - array ( - ), - 'asso' => - array ( - ), - 'edu' => - array ( - ), - 'rel' => - array ( - ), - 'gouv' => - array ( - ), - 'perso' => - array ( - ), - ), - 'hu' => - array ( - 'co' => - array ( - ), - 'info' => - array ( - ), - 'org' => - array ( - ), - 'priv' => - array ( - ), - 'sport' => - array ( - ), - 'tm' => - array ( - ), - 2000 => - array ( - ), - 'agrar' => - array ( - ), - 'bolt' => - array ( - ), - 'casino' => - array ( - ), - 'city' => - array ( - ), - 'erotica' => - array ( - ), - 'erotika' => - array ( - ), - 'film' => - array ( - ), - 'forum' => - array ( - ), - 'games' => - array ( - ), - 'hotel' => - array ( - ), - 'ingatlan' => - array ( - ), - 'jogasz' => - array ( - ), - 'konyvelo' => - array ( - ), - 'lakas' => - array ( - ), - 'media' => - array ( - ), - 'news' => - array ( - ), - 'reklam' => - array ( - ), - 'sex' => - array ( - ), - 'shop' => - array ( - ), - 'suli' => - array ( - ), - 'szex' => - array ( - ), - 'tozsde' => - array ( - ), - 'utazas' => - array ( - ), - 'video' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'id' => - array ( - 'ac' => - array ( - ), - 'biz' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'desa' => - array ( - ), - 'go' => - array ( - ), - 'mil' => - array ( - ), - 'my' => - array ( - ), - 'net' => - array ( - ), - 'or' => - array ( - ), - 'sch' => - array ( - ), - 'web' => - array ( - ), - ), - 'ie' => - array ( - 'gov' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'il' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'gov' => - array ( - ), - 'idf' => - array ( - ), - 'k12' => - array ( - ), - 'muni' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'im' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - 'ltd' => - array ( - ), - 'plc' => - array ( - ), - ), - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'tt' => - array ( - ), - 'tv' => - array ( - ), - ), - 'in' => - array ( - 'co' => - array ( - ), - 'firm' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gen' => - array ( - ), - 'ind' => - array ( - ), - 'nic' => - array ( - ), - 'ac' => - array ( - ), - 'edu' => - array ( - ), - 'res' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'info' => - array ( - 'dyndns' => - array ( - ), - 'barrel-of-knowledge' => - array ( - ), - 'barrell-of-knowledge' => - array ( - ), - 'for-our' => - array ( - ), - 'groks-the' => - array ( - ), - 'groks-this' => - array ( - ), - 'here-for-more' => - array ( - ), - 'knowsitall' => - array ( - ), - 'selfip' => - array ( - ), - 'webhop' => - array ( - ), - ), - 'int' => - array ( - 'eu' => - array ( - ), - ), - 'io' => - array ( - 'com' => - array ( - ), - 'github' => - array ( - ), - 'ngrok' => - array ( - ), - 'nid' => - array ( - ), - 'pantheon' => - array ( - ), - 'sandcats' => - array ( - ), - ), - 'iq' => - array ( - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - ), - 'ir' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'gov' => - array ( - ), - 'id' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sch' => - array ( - ), - 'xn--mgba3a4f16a' => - array ( - ), - 'xn--mgba3a4fra' => - array ( - ), - ), - 'is' => - array ( - 'net' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'int' => - array ( - ), - 'cupcake' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'it' => - array ( - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'abr' => - array ( - ), - 'abruzzo' => - array ( - ), - 'aosta-valley' => - array ( - ), - 'aostavalley' => - array ( - ), - 'bas' => - array ( - ), - 'basilicata' => - array ( - ), - 'cal' => - array ( - ), - 'calabria' => - array ( - ), - 'cam' => - array ( - ), - 'campania' => - array ( - ), - 'emilia-romagna' => - array ( - ), - 'emiliaromagna' => - array ( - ), - 'emr' => - array ( - ), - 'friuli-v-giulia' => - array ( - ), - 'friuli-ve-giulia' => - array ( - ), - 'friuli-vegiulia' => - array ( - ), - 'friuli-venezia-giulia' => - array ( - ), - 'friuli-veneziagiulia' => - array ( - ), - 'friuli-vgiulia' => - array ( - ), - 'friuliv-giulia' => - array ( - ), - 'friulive-giulia' => - array ( - ), - 'friulivegiulia' => - array ( - ), - 'friulivenezia-giulia' => - array ( - ), - 'friuliveneziagiulia' => - array ( - ), - 'friulivgiulia' => - array ( - ), - 'fvg' => - array ( - ), - 'laz' => - array ( - ), - 'lazio' => - array ( - ), - 'lig' => - array ( - ), - 'liguria' => - array ( - ), - 'lom' => - array ( - ), - 'lombardia' => - array ( - ), - 'lombardy' => - array ( - ), - 'lucania' => - array ( - ), - 'mar' => - array ( - ), - 'marche' => - array ( - ), - 'mol' => - array ( - ), - 'molise' => - array ( - ), - 'piedmont' => - array ( - ), - 'piemonte' => - array ( - ), - 'pmn' => - array ( - ), - 'pug' => - array ( - ), - 'puglia' => - array ( - ), - 'sar' => - array ( - ), - 'sardegna' => - array ( - ), - 'sardinia' => - array ( - ), - 'sic' => - array ( - ), - 'sicilia' => - array ( - ), - 'sicily' => - array ( - ), - 'taa' => - array ( - ), - 'tos' => - array ( - ), - 'toscana' => - array ( - ), - 'trentino-a-adige' => - array ( - ), - 'trentino-aadige' => - array ( - ), - 'trentino-alto-adige' => - array ( - ), - 'trentino-altoadige' => - array ( - ), - 'trentino-s-tirol' => - array ( - ), - 'trentino-stirol' => - array ( - ), - 'trentino-sud-tirol' => - array ( - ), - 'trentino-sudtirol' => - array ( - ), - 'trentino-sued-tirol' => - array ( - ), - 'trentino-suedtirol' => - array ( - ), - 'trentinoa-adige' => - array ( - ), - 'trentinoaadige' => - array ( - ), - 'trentinoalto-adige' => - array ( - ), - 'trentinoaltoadige' => - array ( - ), - 'trentinos-tirol' => - array ( - ), - 'trentinostirol' => - array ( - ), - 'trentinosud-tirol' => - array ( - ), - 'trentinosudtirol' => - array ( - ), - 'trentinosued-tirol' => - array ( - ), - 'trentinosuedtirol' => - array ( - ), - 'tuscany' => - array ( - ), - 'umb' => - array ( - ), - 'umbria' => - array ( - ), - 'val-d-aosta' => - array ( - ), - 'val-daosta' => - array ( - ), - 'vald-aosta' => - array ( - ), - 'valdaosta' => - array ( - ), - 'valle-aosta' => - array ( - ), - 'valle-d-aosta' => - array ( - ), - 'valle-daosta' => - array ( - ), - 'valleaosta' => - array ( - ), - 'valled-aosta' => - array ( - ), - 'valledaosta' => - array ( - ), - 'vallee-aoste' => - array ( - ), - 'valleeaoste' => - array ( - ), - 'vao' => - array ( - ), - 'vda' => - array ( - ), - 'ven' => - array ( - ), - 'veneto' => - array ( - ), - 'ag' => - array ( - ), - 'agrigento' => - array ( - ), - 'al' => - array ( - ), - 'alessandria' => - array ( - ), - 'alto-adige' => - array ( - ), - 'altoadige' => - array ( - ), - 'an' => - array ( - ), - 'ancona' => - array ( - ), - 'andria-barletta-trani' => - array ( - ), - 'andria-trani-barletta' => - array ( - ), - 'andriabarlettatrani' => - array ( - ), - 'andriatranibarletta' => - array ( - ), - 'ao' => - array ( - ), - 'aosta' => - array ( - ), - 'aoste' => - array ( - ), - 'ap' => - array ( - ), - 'aq' => - array ( - ), - 'aquila' => - array ( - ), - 'ar' => - array ( - ), - 'arezzo' => - array ( - ), - 'ascoli-piceno' => - array ( - ), - 'ascolipiceno' => - array ( - ), - 'asti' => - array ( - ), - 'at' => - array ( - ), - 'av' => - array ( - ), - 'avellino' => - array ( - ), - 'ba' => - array ( - ), - 'balsan' => - array ( - ), - 'bari' => - array ( - ), - 'barletta-trani-andria' => - array ( - ), - 'barlettatraniandria' => - array ( - ), - 'belluno' => - array ( - ), - 'benevento' => - array ( - ), - 'bergamo' => - array ( - ), - 'bg' => - array ( - ), - 'bi' => - array ( - ), - 'biella' => - array ( - ), - 'bl' => - array ( - ), - 'bn' => - array ( - ), - 'bo' => - array ( - ), - 'bologna' => - array ( - ), - 'bolzano' => - array ( - ), - 'bozen' => - array ( - ), - 'br' => - array ( - ), - 'brescia' => - array ( - ), - 'brindisi' => - array ( - ), - 'bs' => - array ( - ), - 'bt' => - array ( - ), - 'bz' => - array ( - ), - 'ca' => - array ( - ), - 'cagliari' => - array ( - ), - 'caltanissetta' => - array ( - ), - 'campidano-medio' => - array ( - ), - 'campidanomedio' => - array ( - ), - 'campobasso' => - array ( - ), - 'carbonia-iglesias' => - array ( - ), - 'carboniaiglesias' => - array ( - ), - 'carrara-massa' => - array ( - ), - 'carraramassa' => - array ( - ), - 'caserta' => - array ( - ), - 'catania' => - array ( - ), - 'catanzaro' => - array ( - ), - 'cb' => - array ( - ), - 'ce' => - array ( - ), - 'cesena-forli' => - array ( - ), - 'cesenaforli' => - array ( - ), - 'ch' => - array ( - ), - 'chieti' => - array ( - ), - 'ci' => - array ( - ), - 'cl' => - array ( - ), - 'cn' => - array ( - ), - 'co' => - array ( - ), - 'como' => - array ( - ), - 'cosenza' => - array ( - ), - 'cr' => - array ( - ), - 'cremona' => - array ( - ), - 'crotone' => - array ( - ), - 'cs' => - array ( - ), - 'ct' => - array ( - ), - 'cuneo' => - array ( - ), - 'cz' => - array ( - ), - 'dell-ogliastra' => - array ( - ), - 'dellogliastra' => - array ( - ), - 'en' => - array ( - ), - 'enna' => - array ( - ), - 'fc' => - array ( - ), - 'fe' => - array ( - ), - 'fermo' => - array ( - ), - 'ferrara' => - array ( - ), - 'fg' => - array ( - ), - 'fi' => - array ( - ), - 'firenze' => - array ( - ), - 'florence' => - array ( - ), - 'fm' => - array ( - ), - 'foggia' => - array ( - ), - 'forli-cesena' => - array ( - ), - 'forlicesena' => - array ( - ), - 'fr' => - array ( - ), - 'frosinone' => - array ( - ), - 'ge' => - array ( - ), - 'genoa' => - array ( - ), - 'genova' => - array ( - ), - 'go' => - array ( - ), - 'gorizia' => - array ( - ), - 'gr' => - array ( - ), - 'grosseto' => - array ( - ), - 'iglesias-carbonia' => - array ( - ), - 'iglesiascarbonia' => - array ( - ), - 'im' => - array ( - ), - 'imperia' => - array ( - ), - 'is' => - array ( - ), - 'isernia' => - array ( - ), - 'kr' => - array ( - ), - 'la-spezia' => - array ( - ), - 'laquila' => - array ( - ), - 'laspezia' => - array ( - ), - 'latina' => - array ( - ), - 'lc' => - array ( - ), - 'le' => - array ( - ), - 'lecce' => - array ( - ), - 'lecco' => - array ( - ), - 'li' => - array ( - ), - 'livorno' => - array ( - ), - 'lo' => - array ( - ), - 'lodi' => - array ( - ), - 'lt' => - array ( - ), - 'lu' => - array ( - ), - 'lucca' => - array ( - ), - 'macerata' => - array ( - ), - 'mantova' => - array ( - ), - 'massa-carrara' => - array ( - ), - 'massacarrara' => - array ( - ), - 'matera' => - array ( - ), - 'mb' => - array ( - ), - 'mc' => - array ( - ), - 'me' => - array ( - ), - 'medio-campidano' => - array ( - ), - 'mediocampidano' => - array ( - ), - 'messina' => - array ( - ), - 'mi' => - array ( - ), - 'milan' => - array ( - ), - 'milano' => - array ( - ), - 'mn' => - array ( - ), - 'mo' => - array ( - ), - 'modena' => - array ( - ), - 'monza-brianza' => - array ( - ), - 'monza-e-della-brianza' => - array ( - ), - 'monza' => - array ( - ), - 'monzabrianza' => - array ( - ), - 'monzaebrianza' => - array ( - ), - 'monzaedellabrianza' => - array ( - ), - 'ms' => - array ( - ), - 'mt' => - array ( - ), - 'na' => - array ( - ), - 'naples' => - array ( - ), - 'napoli' => - array ( - ), - 'no' => - array ( - ), - 'novara' => - array ( - ), - 'nu' => - array ( - ), - 'nuoro' => - array ( - ), - 'og' => - array ( - ), - 'ogliastra' => - array ( - ), - 'olbia-tempio' => - array ( - ), - 'olbiatempio' => - array ( - ), - 'or' => - array ( - ), - 'oristano' => - array ( - ), - 'ot' => - array ( - ), - 'pa' => - array ( - ), - 'padova' => - array ( - ), - 'padua' => - array ( - ), - 'palermo' => - array ( - ), - 'parma' => - array ( - ), - 'pavia' => - array ( - ), - 'pc' => - array ( - ), - 'pd' => - array ( - ), - 'pe' => - array ( - ), - 'perugia' => - array ( - ), - 'pesaro-urbino' => - array ( - ), - 'pesarourbino' => - array ( - ), - 'pescara' => - array ( - ), - 'pg' => - array ( - ), - 'pi' => - array ( - ), - 'piacenza' => - array ( - ), - 'pisa' => - array ( - ), - 'pistoia' => - array ( - ), - 'pn' => - array ( - ), - 'po' => - array ( - ), - 'pordenone' => - array ( - ), - 'potenza' => - array ( - ), - 'pr' => - array ( - ), - 'prato' => - array ( - ), - 'pt' => - array ( - ), - 'pu' => - array ( - ), - 'pv' => - array ( - ), - 'pz' => - array ( - ), - 'ra' => - array ( - ), - 'ragusa' => - array ( - ), - 'ravenna' => - array ( - ), - 'rc' => - array ( - ), - 're' => - array ( - ), - 'reggio-calabria' => - array ( - ), - 'reggio-emilia' => - array ( - ), - 'reggiocalabria' => - array ( - ), - 'reggioemilia' => - array ( - ), - 'rg' => - array ( - ), - 'ri' => - array ( - ), - 'rieti' => - array ( - ), - 'rimini' => - array ( - ), - 'rm' => - array ( - ), - 'rn' => - array ( - ), - 'ro' => - array ( - ), - 'roma' => - array ( - ), - 'rome' => - array ( - ), - 'rovigo' => - array ( - ), - 'sa' => - array ( - ), - 'salerno' => - array ( - ), - 'sassari' => - array ( - ), - 'savona' => - array ( - ), - 'si' => - array ( - ), - 'siena' => - array ( - ), - 'siracusa' => - array ( - ), - 'so' => - array ( - ), - 'sondrio' => - array ( - ), - 'sp' => - array ( - ), - 'sr' => - array ( - ), - 'ss' => - array ( - ), - 'suedtirol' => - array ( - ), - 'sv' => - array ( - ), - 'ta' => - array ( - ), - 'taranto' => - array ( - ), - 'te' => - array ( - ), - 'tempio-olbia' => - array ( - ), - 'tempioolbia' => - array ( - ), - 'teramo' => - array ( - ), - 'terni' => - array ( - ), - 'tn' => - array ( - ), - 'to' => - array ( - ), - 'torino' => - array ( - ), - 'tp' => - array ( - ), - 'tr' => - array ( - ), - 'trani-andria-barletta' => - array ( - ), - 'trani-barletta-andria' => - array ( - ), - 'traniandriabarletta' => - array ( - ), - 'tranibarlettaandria' => - array ( - ), - 'trapani' => - array ( - ), - 'trentino' => - array ( - ), - 'trento' => - array ( - ), - 'treviso' => - array ( - ), - 'trieste' => - array ( - ), - 'ts' => - array ( - ), - 'turin' => - array ( - ), - 'tv' => - array ( - ), - 'ud' => - array ( - ), - 'udine' => - array ( - ), - 'urbino-pesaro' => - array ( - ), - 'urbinopesaro' => - array ( - ), - 'va' => - array ( - ), - 'varese' => - array ( - ), - 'vb' => - array ( - ), - 'vc' => - array ( - ), - 've' => - array ( - ), - 'venezia' => - array ( - ), - 'venice' => - array ( - ), - 'verbania' => - array ( - ), - 'vercelli' => - array ( - ), - 'verona' => - array ( - ), - 'vi' => - array ( - ), - 'vibo-valentia' => - array ( - ), - 'vibovalentia' => - array ( - ), - 'vicenza' => - array ( - ), - 'viterbo' => - array ( - ), - 'vr' => - array ( - ), - 'vs' => - array ( - ), - 'vt' => - array ( - ), - 'vv' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'je' => - array ( - 'co' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'jm' => - array ( - '*' => - array ( - ), - ), - 'jo' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'sch' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - ), - 'jobs' => - array ( - ), - 'jp' => - array ( - 'ac' => - array ( - ), - 'ad' => - array ( - ), - 'co' => - array ( - ), - 'ed' => - array ( - ), - 'go' => - array ( - ), - 'gr' => - array ( - ), - 'lg' => - array ( - ), - 'ne' => - array ( - ), - 'or' => - array ( - ), - 'aichi' => - array ( - 'aisai' => - array ( - ), - 'ama' => - array ( - ), - 'anjo' => - array ( - ), - 'asuke' => - array ( - ), - 'chiryu' => - array ( - ), - 'chita' => - array ( - ), - 'fuso' => - array ( - ), - 'gamagori' => - array ( - ), - 'handa' => - array ( - ), - 'hazu' => - array ( - ), - 'hekinan' => - array ( - ), - 'higashiura' => - array ( - ), - 'ichinomiya' => - array ( - ), - 'inazawa' => - array ( - ), - 'inuyama' => - array ( - ), - 'isshiki' => - array ( - ), - 'iwakura' => - array ( - ), - 'kanie' => - array ( - ), - 'kariya' => - array ( - ), - 'kasugai' => - array ( - ), - 'kira' => - array ( - ), - 'kiyosu' => - array ( - ), - 'komaki' => - array ( - ), - 'konan' => - array ( - ), - 'kota' => - array ( - ), - 'mihama' => - array ( - ), - 'miyoshi' => - array ( - ), - 'nishio' => - array ( - ), - 'nisshin' => - array ( - ), - 'obu' => - array ( - ), - 'oguchi' => - array ( - ), - 'oharu' => - array ( - ), - 'okazaki' => - array ( - ), - 'owariasahi' => - array ( - ), - 'seto' => - array ( - ), - 'shikatsu' => - array ( - ), - 'shinshiro' => - array ( - ), - 'shitara' => - array ( - ), - 'tahara' => - array ( - ), - 'takahama' => - array ( - ), - 'tobishima' => - array ( - ), - 'toei' => - array ( - ), - 'togo' => - array ( - ), - 'tokai' => - array ( - ), - 'tokoname' => - array ( - ), - 'toyoake' => - array ( - ), - 'toyohashi' => - array ( - ), - 'toyokawa' => - array ( - ), - 'toyone' => - array ( - ), - 'toyota' => - array ( - ), - 'tsushima' => - array ( - ), - 'yatomi' => - array ( - ), - ), - 'akita' => - array ( - 'akita' => - array ( - ), - 'daisen' => - array ( - ), - 'fujisato' => - array ( - ), - 'gojome' => - array ( - ), - 'hachirogata' => - array ( - ), - 'happou' => - array ( - ), - 'higashinaruse' => - array ( - ), - 'honjo' => - array ( - ), - 'honjyo' => - array ( - ), - 'ikawa' => - array ( - ), - 'kamikoani' => - array ( - ), - 'kamioka' => - array ( - ), - 'katagami' => - array ( - ), - 'kazuno' => - array ( - ), - 'kitaakita' => - array ( - ), - 'kosaka' => - array ( - ), - 'kyowa' => - array ( - ), - 'misato' => - array ( - ), - 'mitane' => - array ( - ), - 'moriyoshi' => - array ( - ), - 'nikaho' => - array ( - ), - 'noshiro' => - array ( - ), - 'odate' => - array ( - ), - 'oga' => - array ( - ), - 'ogata' => - array ( - ), - 'semboku' => - array ( - ), - 'yokote' => - array ( - ), - 'yurihonjo' => - array ( - ), - ), - 'aomori' => - array ( - 'aomori' => - array ( - ), - 'gonohe' => - array ( - ), - 'hachinohe' => - array ( - ), - 'hashikami' => - array ( - ), - 'hiranai' => - array ( - ), - 'hirosaki' => - array ( - ), - 'itayanagi' => - array ( - ), - 'kuroishi' => - array ( - ), - 'misawa' => - array ( - ), - 'mutsu' => - array ( - ), - 'nakadomari' => - array ( - ), - 'noheji' => - array ( - ), - 'oirase' => - array ( - ), - 'owani' => - array ( - ), - 'rokunohe' => - array ( - ), - 'sannohe' => - array ( - ), - 'shichinohe' => - array ( - ), - 'shingo' => - array ( - ), - 'takko' => - array ( - ), - 'towada' => - array ( - ), - 'tsugaru' => - array ( - ), - 'tsuruta' => - array ( - ), - ), - 'chiba' => - array ( - 'abiko' => - array ( - ), - 'asahi' => - array ( - ), - 'chonan' => - array ( - ), - 'chosei' => - array ( - ), - 'choshi' => - array ( - ), - 'chuo' => - array ( - ), - 'funabashi' => - array ( - ), - 'futtsu' => - array ( - ), - 'hanamigawa' => - array ( - ), - 'ichihara' => - array ( - ), - 'ichikawa' => - array ( - ), - 'ichinomiya' => - array ( - ), - 'inzai' => - array ( - ), - 'isumi' => - array ( - ), - 'kamagaya' => - array ( - ), - 'kamogawa' => - array ( - ), - 'kashiwa' => - array ( - ), - 'katori' => - array ( - ), - 'katsuura' => - array ( - ), - 'kimitsu' => - array ( - ), - 'kisarazu' => - array ( - ), - 'kozaki' => - array ( - ), - 'kujukuri' => - array ( - ), - 'kyonan' => - array ( - ), - 'matsudo' => - array ( - ), - 'midori' => - array ( - ), - 'mihama' => - array ( - ), - 'minamiboso' => - array ( - ), - 'mobara' => - array ( - ), - 'mutsuzawa' => - array ( - ), - 'nagara' => - array ( - ), - 'nagareyama' => - array ( - ), - 'narashino' => - array ( - ), - 'narita' => - array ( - ), - 'noda' => - array ( - ), - 'oamishirasato' => - array ( - ), - 'omigawa' => - array ( - ), - 'onjuku' => - array ( - ), - 'otaki' => - array ( - ), - 'sakae' => - array ( - ), - 'sakura' => - array ( - ), - 'shimofusa' => - array ( - ), - 'shirako' => - array ( - ), - 'shiroi' => - array ( - ), - 'shisui' => - array ( - ), - 'sodegaura' => - array ( - ), - 'sosa' => - array ( - ), - 'tako' => - array ( - ), - 'tateyama' => - array ( - ), - 'togane' => - array ( - ), - 'tohnosho' => - array ( - ), - 'tomisato' => - array ( - ), - 'urayasu' => - array ( - ), - 'yachimata' => - array ( - ), - 'yachiyo' => - array ( - ), - 'yokaichiba' => - array ( - ), - 'yokoshibahikari' => - array ( - ), - 'yotsukaido' => - array ( - ), - ), - 'ehime' => - array ( - 'ainan' => - array ( - ), - 'honai' => - array ( - ), - 'ikata' => - array ( - ), - 'imabari' => - array ( - ), - 'iyo' => - array ( - ), - 'kamijima' => - array ( - ), - 'kihoku' => - array ( - ), - 'kumakogen' => - array ( - ), - 'masaki' => - array ( - ), - 'matsuno' => - array ( - ), - 'matsuyama' => - array ( - ), - 'namikata' => - array ( - ), - 'niihama' => - array ( - ), - 'ozu' => - array ( - ), - 'saijo' => - array ( - ), - 'seiyo' => - array ( - ), - 'shikokuchuo' => - array ( - ), - 'tobe' => - array ( - ), - 'toon' => - array ( - ), - 'uchiko' => - array ( - ), - 'uwajima' => - array ( - ), - 'yawatahama' => - array ( - ), - ), - 'fukui' => - array ( - 'echizen' => - array ( - ), - 'eiheiji' => - array ( - ), - 'fukui' => - array ( - ), - 'ikeda' => - array ( - ), - 'katsuyama' => - array ( - ), - 'mihama' => - array ( - ), - 'minamiechizen' => - array ( - ), - 'obama' => - array ( - ), - 'ohi' => - array ( - ), - 'ono' => - array ( - ), - 'sabae' => - array ( - ), - 'sakai' => - array ( - ), - 'takahama' => - array ( - ), - 'tsuruga' => - array ( - ), - 'wakasa' => - array ( - ), - ), - 'fukuoka' => - array ( - 'ashiya' => - array ( - ), - 'buzen' => - array ( - ), - 'chikugo' => - array ( - ), - 'chikuho' => - array ( - ), - 'chikujo' => - array ( - ), - 'chikushino' => - array ( - ), - 'chikuzen' => - array ( - ), - 'chuo' => - array ( - ), - 'dazaifu' => - array ( - ), - 'fukuchi' => - array ( - ), - 'hakata' => - array ( - ), - 'higashi' => - array ( - ), - 'hirokawa' => - array ( - ), - 'hisayama' => - array ( - ), - 'iizuka' => - array ( - ), - 'inatsuki' => - array ( - ), - 'kaho' => - array ( - ), - 'kasuga' => - array ( - ), - 'kasuya' => - array ( - ), - 'kawara' => - array ( - ), - 'keisen' => - array ( - ), - 'koga' => - array ( - ), - 'kurate' => - array ( - ), - 'kurogi' => - array ( - ), - 'kurume' => - array ( - ), - 'minami' => - array ( - ), - 'miyako' => - array ( - ), - 'miyama' => - array ( - ), - 'miyawaka' => - array ( - ), - 'mizumaki' => - array ( - ), - 'munakata' => - array ( - ), - 'nakagawa' => - array ( - ), - 'nakama' => - array ( - ), - 'nishi' => - array ( - ), - 'nogata' => - array ( - ), - 'ogori' => - array ( - ), - 'okagaki' => - array ( - ), - 'okawa' => - array ( - ), - 'oki' => - array ( - ), - 'omuta' => - array ( - ), - 'onga' => - array ( - ), - 'onojo' => - array ( - ), - 'oto' => - array ( - ), - 'saigawa' => - array ( - ), - 'sasaguri' => - array ( - ), - 'shingu' => - array ( - ), - 'shinyoshitomi' => - array ( - ), - 'shonai' => - array ( - ), - 'soeda' => - array ( - ), - 'sue' => - array ( - ), - 'tachiarai' => - array ( - ), - 'tagawa' => - array ( - ), - 'takata' => - array ( - ), - 'toho' => - array ( - ), - 'toyotsu' => - array ( - ), - 'tsuiki' => - array ( - ), - 'ukiha' => - array ( - ), - 'umi' => - array ( - ), - 'usui' => - array ( - ), - 'yamada' => - array ( - ), - 'yame' => - array ( - ), - 'yanagawa' => - array ( - ), - 'yukuhashi' => - array ( - ), - ), - 'fukushima' => - array ( - 'aizubange' => - array ( - ), - 'aizumisato' => - array ( - ), - 'aizuwakamatsu' => - array ( - ), - 'asakawa' => - array ( - ), - 'bandai' => - array ( - ), - 'date' => - array ( - ), - 'fukushima' => - array ( - ), - 'furudono' => - array ( - ), - 'futaba' => - array ( - ), - 'hanawa' => - array ( - ), - 'higashi' => - array ( - ), - 'hirata' => - array ( - ), - 'hirono' => - array ( - ), - 'iitate' => - array ( - ), - 'inawashiro' => - array ( - ), - 'ishikawa' => - array ( - ), - 'iwaki' => - array ( - ), - 'izumizaki' => - array ( - ), - 'kagamiishi' => - array ( - ), - 'kaneyama' => - array ( - ), - 'kawamata' => - array ( - ), - 'kitakata' => - array ( - ), - 'kitashiobara' => - array ( - ), - 'koori' => - array ( - ), - 'koriyama' => - array ( - ), - 'kunimi' => - array ( - ), - 'miharu' => - array ( - ), - 'mishima' => - array ( - ), - 'namie' => - array ( - ), - 'nango' => - array ( - ), - 'nishiaizu' => - array ( - ), - 'nishigo' => - array ( - ), - 'okuma' => - array ( - ), - 'omotego' => - array ( - ), - 'ono' => - array ( - ), - 'otama' => - array ( - ), - 'samegawa' => - array ( - ), - 'shimogo' => - array ( - ), - 'shirakawa' => - array ( - ), - 'showa' => - array ( - ), - 'soma' => - array ( - ), - 'sukagawa' => - array ( - ), - 'taishin' => - array ( - ), - 'tamakawa' => - array ( - ), - 'tanagura' => - array ( - ), - 'tenei' => - array ( - ), - 'yabuki' => - array ( - ), - 'yamato' => - array ( - ), - 'yamatsuri' => - array ( - ), - 'yanaizu' => - array ( - ), - 'yugawa' => - array ( - ), - ), - 'gifu' => - array ( - 'anpachi' => - array ( - ), - 'ena' => - array ( - ), - 'gifu' => - array ( - ), - 'ginan' => - array ( - ), - 'godo' => - array ( - ), - 'gujo' => - array ( - ), - 'hashima' => - array ( - ), - 'hichiso' => - array ( - ), - 'hida' => - array ( - ), - 'higashishirakawa' => - array ( - ), - 'ibigawa' => - array ( - ), - 'ikeda' => - array ( - ), - 'kakamigahara' => - array ( - ), - 'kani' => - array ( - ), - 'kasahara' => - array ( - ), - 'kasamatsu' => - array ( - ), - 'kawaue' => - array ( - ), - 'kitagata' => - array ( - ), - 'mino' => - array ( - ), - 'minokamo' => - array ( - ), - 'mitake' => - array ( - ), - 'mizunami' => - array ( - ), - 'motosu' => - array ( - ), - 'nakatsugawa' => - array ( - ), - 'ogaki' => - array ( - ), - 'sakahogi' => - array ( - ), - 'seki' => - array ( - ), - 'sekigahara' => - array ( - ), - 'shirakawa' => - array ( - ), - 'tajimi' => - array ( - ), - 'takayama' => - array ( - ), - 'tarui' => - array ( - ), - 'toki' => - array ( - ), - 'tomika' => - array ( - ), - 'wanouchi' => - array ( - ), - 'yamagata' => - array ( - ), - 'yaotsu' => - array ( - ), - 'yoro' => - array ( - ), - ), - 'gunma' => - array ( - 'annaka' => - array ( - ), - 'chiyoda' => - array ( - ), - 'fujioka' => - array ( - ), - 'higashiagatsuma' => - array ( - ), - 'isesaki' => - array ( - ), - 'itakura' => - array ( - ), - 'kanna' => - array ( - ), - 'kanra' => - array ( - ), - 'katashina' => - array ( - ), - 'kawaba' => - array ( - ), - 'kiryu' => - array ( - ), - 'kusatsu' => - array ( - ), - 'maebashi' => - array ( - ), - 'meiwa' => - array ( - ), - 'midori' => - array ( - ), - 'minakami' => - array ( - ), - 'naganohara' => - array ( - ), - 'nakanojo' => - array ( - ), - 'nanmoku' => - array ( - ), - 'numata' => - array ( - ), - 'oizumi' => - array ( - ), - 'ora' => - array ( - ), - 'ota' => - array ( - ), - 'shibukawa' => - array ( - ), - 'shimonita' => - array ( - ), - 'shinto' => - array ( - ), - 'showa' => - array ( - ), - 'takasaki' => - array ( - ), - 'takayama' => - array ( - ), - 'tamamura' => - array ( - ), - 'tatebayashi' => - array ( - ), - 'tomioka' => - array ( - ), - 'tsukiyono' => - array ( - ), - 'tsumagoi' => - array ( - ), - 'ueno' => - array ( - ), - 'yoshioka' => - array ( - ), - ), - 'hiroshima' => - array ( - 'asaminami' => - array ( - ), - 'daiwa' => - array ( - ), - 'etajima' => - array ( - ), - 'fuchu' => - array ( - ), - 'fukuyama' => - array ( - ), - 'hatsukaichi' => - array ( - ), - 'higashihiroshima' => - array ( - ), - 'hongo' => - array ( - ), - 'jinsekikogen' => - array ( - ), - 'kaita' => - array ( - ), - 'kui' => - array ( - ), - 'kumano' => - array ( - ), - 'kure' => - array ( - ), - 'mihara' => - array ( - ), - 'miyoshi' => - array ( - ), - 'naka' => - array ( - ), - 'onomichi' => - array ( - ), - 'osakikamijima' => - array ( - ), - 'otake' => - array ( - ), - 'saka' => - array ( - ), - 'sera' => - array ( - ), - 'seranishi' => - array ( - ), - 'shinichi' => - array ( - ), - 'shobara' => - array ( - ), - 'takehara' => - array ( - ), - ), - 'hokkaido' => - array ( - 'abashiri' => - array ( - ), - 'abira' => - array ( - ), - 'aibetsu' => - array ( - ), - 'akabira' => - array ( - ), - 'akkeshi' => - array ( - ), - 'asahikawa' => - array ( - ), - 'ashibetsu' => - array ( - ), - 'ashoro' => - array ( - ), - 'assabu' => - array ( - ), - 'atsuma' => - array ( - ), - 'bibai' => - array ( - ), - 'biei' => - array ( - ), - 'bifuka' => - array ( - ), - 'bihoro' => - array ( - ), - 'biratori' => - array ( - ), - 'chippubetsu' => - array ( - ), - 'chitose' => - array ( - ), - 'date' => - array ( - ), - 'ebetsu' => - array ( - ), - 'embetsu' => - array ( - ), - 'eniwa' => - array ( - ), - 'erimo' => - array ( - ), - 'esan' => - array ( - ), - 'esashi' => - array ( - ), - 'fukagawa' => - array ( - ), - 'fukushima' => - array ( - ), - 'furano' => - array ( - ), - 'furubira' => - array ( - ), - 'haboro' => - array ( - ), - 'hakodate' => - array ( - ), - 'hamatonbetsu' => - array ( - ), - 'hidaka' => - array ( - ), - 'higashikagura' => - array ( - ), - 'higashikawa' => - array ( - ), - 'hiroo' => - array ( - ), - 'hokuryu' => - array ( - ), - 'hokuto' => - array ( - ), - 'honbetsu' => - array ( - ), - 'horokanai' => - array ( - ), - 'horonobe' => - array ( - ), - 'ikeda' => - array ( - ), - 'imakane' => - array ( - ), - 'ishikari' => - array ( - ), - 'iwamizawa' => - array ( - ), - 'iwanai' => - array ( - ), - 'kamifurano' => - array ( - ), - 'kamikawa' => - array ( - ), - 'kamishihoro' => - array ( - ), - 'kamisunagawa' => - array ( - ), - 'kamoenai' => - array ( - ), - 'kayabe' => - array ( - ), - 'kembuchi' => - array ( - ), - 'kikonai' => - array ( - ), - 'kimobetsu' => - array ( - ), - 'kitahiroshima' => - array ( - ), - 'kitami' => - array ( - ), - 'kiyosato' => - array ( - ), - 'koshimizu' => - array ( - ), - 'kunneppu' => - array ( - ), - 'kuriyama' => - array ( - ), - 'kuromatsunai' => - array ( - ), - 'kushiro' => - array ( - ), - 'kutchan' => - array ( - ), - 'kyowa' => - array ( - ), - 'mashike' => - array ( - ), - 'matsumae' => - array ( - ), - 'mikasa' => - array ( - ), - 'minamifurano' => - array ( - ), - 'mombetsu' => - array ( - ), - 'moseushi' => - array ( - ), - 'mukawa' => - array ( - ), - 'muroran' => - array ( - ), - 'naie' => - array ( - ), - 'nakagawa' => - array ( - ), - 'nakasatsunai' => - array ( - ), - 'nakatombetsu' => - array ( - ), - 'nanae' => - array ( - ), - 'nanporo' => - array ( - ), - 'nayoro' => - array ( - ), - 'nemuro' => - array ( - ), - 'niikappu' => - array ( - ), - 'niki' => - array ( - ), - 'nishiokoppe' => - array ( - ), - 'noboribetsu' => - array ( - ), - 'numata' => - array ( - ), - 'obihiro' => - array ( - ), - 'obira' => - array ( - ), - 'oketo' => - array ( - ), - 'okoppe' => - array ( - ), - 'otaru' => - array ( - ), - 'otobe' => - array ( - ), - 'otofuke' => - array ( - ), - 'otoineppu' => - array ( - ), - 'oumu' => - array ( - ), - 'ozora' => - array ( - ), - 'pippu' => - array ( - ), - 'rankoshi' => - array ( - ), - 'rebun' => - array ( - ), - 'rikubetsu' => - array ( - ), - 'rishiri' => - array ( - ), - 'rishirifuji' => - array ( - ), - 'saroma' => - array ( - ), - 'sarufutsu' => - array ( - ), - 'shakotan' => - array ( - ), - 'shari' => - array ( - ), - 'shibecha' => - array ( - ), - 'shibetsu' => - array ( - ), - 'shikabe' => - array ( - ), - 'shikaoi' => - array ( - ), - 'shimamaki' => - array ( - ), - 'shimizu' => - array ( - ), - 'shimokawa' => - array ( - ), - 'shinshinotsu' => - array ( - ), - 'shintoku' => - array ( - ), - 'shiranuka' => - array ( - ), - 'shiraoi' => - array ( - ), - 'shiriuchi' => - array ( - ), - 'sobetsu' => - array ( - ), - 'sunagawa' => - array ( - ), - 'taiki' => - array ( - ), - 'takasu' => - array ( - ), - 'takikawa' => - array ( - ), - 'takinoue' => - array ( - ), - 'teshikaga' => - array ( - ), - 'tobetsu' => - array ( - ), - 'tohma' => - array ( - ), - 'tomakomai' => - array ( - ), - 'tomari' => - array ( - ), - 'toya' => - array ( - ), - 'toyako' => - array ( - ), - 'toyotomi' => - array ( - ), - 'toyoura' => - array ( - ), - 'tsubetsu' => - array ( - ), - 'tsukigata' => - array ( - ), - 'urakawa' => - array ( - ), - 'urausu' => - array ( - ), - 'uryu' => - array ( - ), - 'utashinai' => - array ( - ), - 'wakkanai' => - array ( - ), - 'wassamu' => - array ( - ), - 'yakumo' => - array ( - ), - 'yoichi' => - array ( - ), - ), - 'hyogo' => - array ( - 'aioi' => - array ( - ), - 'akashi' => - array ( - ), - 'ako' => - array ( - ), - 'amagasaki' => - array ( - ), - 'aogaki' => - array ( - ), - 'asago' => - array ( - ), - 'ashiya' => - array ( - ), - 'awaji' => - array ( - ), - 'fukusaki' => - array ( - ), - 'goshiki' => - array ( - ), - 'harima' => - array ( - ), - 'himeji' => - array ( - ), - 'ichikawa' => - array ( - ), - 'inagawa' => - array ( - ), - 'itami' => - array ( - ), - 'kakogawa' => - array ( - ), - 'kamigori' => - array ( - ), - 'kamikawa' => - array ( - ), - 'kasai' => - array ( - ), - 'kasuga' => - array ( - ), - 'kawanishi' => - array ( - ), - 'miki' => - array ( - ), - 'minamiawaji' => - array ( - ), - 'nishinomiya' => - array ( - ), - 'nishiwaki' => - array ( - ), - 'ono' => - array ( - ), - 'sanda' => - array ( - ), - 'sannan' => - array ( - ), - 'sasayama' => - array ( - ), - 'sayo' => - array ( - ), - 'shingu' => - array ( - ), - 'shinonsen' => - array ( - ), - 'shiso' => - array ( - ), - 'sumoto' => - array ( - ), - 'taishi' => - array ( - ), - 'taka' => - array ( - ), - 'takarazuka' => - array ( - ), - 'takasago' => - array ( - ), - 'takino' => - array ( - ), - 'tamba' => - array ( - ), - 'tatsuno' => - array ( - ), - 'toyooka' => - array ( - ), - 'yabu' => - array ( - ), - 'yashiro' => - array ( - ), - 'yoka' => - array ( - ), - 'yokawa' => - array ( - ), - ), - 'ibaraki' => - array ( - 'ami' => - array ( - ), - 'asahi' => - array ( - ), - 'bando' => - array ( - ), - 'chikusei' => - array ( - ), - 'daigo' => - array ( - ), - 'fujishiro' => - array ( - ), - 'hitachi' => - array ( - ), - 'hitachinaka' => - array ( - ), - 'hitachiomiya' => - array ( - ), - 'hitachiota' => - array ( - ), - 'ibaraki' => - array ( - ), - 'ina' => - array ( - ), - 'inashiki' => - array ( - ), - 'itako' => - array ( - ), - 'iwama' => - array ( - ), - 'joso' => - array ( - ), - 'kamisu' => - array ( - ), - 'kasama' => - array ( - ), - 'kashima' => - array ( - ), - 'kasumigaura' => - array ( - ), - 'koga' => - array ( - ), - 'miho' => - array ( - ), - 'mito' => - array ( - ), - 'moriya' => - array ( - ), - 'naka' => - array ( - ), - 'namegata' => - array ( - ), - 'oarai' => - array ( - ), - 'ogawa' => - array ( - ), - 'omitama' => - array ( - ), - 'ryugasaki' => - array ( - ), - 'sakai' => - array ( - ), - 'sakuragawa' => - array ( - ), - 'shimodate' => - array ( - ), - 'shimotsuma' => - array ( - ), - 'shirosato' => - array ( - ), - 'sowa' => - array ( - ), - 'suifu' => - array ( - ), - 'takahagi' => - array ( - ), - 'tamatsukuri' => - array ( - ), - 'tokai' => - array ( - ), - 'tomobe' => - array ( - ), - 'tone' => - array ( - ), - 'toride' => - array ( - ), - 'tsuchiura' => - array ( - ), - 'tsukuba' => - array ( - ), - 'uchihara' => - array ( - ), - 'ushiku' => - array ( - ), - 'yachiyo' => - array ( - ), - 'yamagata' => - array ( - ), - 'yawara' => - array ( - ), - 'yuki' => - array ( - ), - ), - 'ishikawa' => - array ( - 'anamizu' => - array ( - ), - 'hakui' => - array ( - ), - 'hakusan' => - array ( - ), - 'kaga' => - array ( - ), - 'kahoku' => - array ( - ), - 'kanazawa' => - array ( - ), - 'kawakita' => - array ( - ), - 'komatsu' => - array ( - ), - 'nakanoto' => - array ( - ), - 'nanao' => - array ( - ), - 'nomi' => - array ( - ), - 'nonoichi' => - array ( - ), - 'noto' => - array ( - ), - 'shika' => - array ( - ), - 'suzu' => - array ( - ), - 'tsubata' => - array ( - ), - 'tsurugi' => - array ( - ), - 'uchinada' => - array ( - ), - 'wajima' => - array ( - ), - ), - 'iwate' => - array ( - 'fudai' => - array ( - ), - 'fujisawa' => - array ( - ), - 'hanamaki' => - array ( - ), - 'hiraizumi' => - array ( - ), - 'hirono' => - array ( - ), - 'ichinohe' => - array ( - ), - 'ichinoseki' => - array ( - ), - 'iwaizumi' => - array ( - ), - 'iwate' => - array ( - ), - 'joboji' => - array ( - ), - 'kamaishi' => - array ( - ), - 'kanegasaki' => - array ( - ), - 'karumai' => - array ( - ), - 'kawai' => - array ( - ), - 'kitakami' => - array ( - ), - 'kuji' => - array ( - ), - 'kunohe' => - array ( - ), - 'kuzumaki' => - array ( - ), - 'miyako' => - array ( - ), - 'mizusawa' => - array ( - ), - 'morioka' => - array ( - ), - 'ninohe' => - array ( - ), - 'noda' => - array ( - ), - 'ofunato' => - array ( - ), - 'oshu' => - array ( - ), - 'otsuchi' => - array ( - ), - 'rikuzentakata' => - array ( - ), - 'shiwa' => - array ( - ), - 'shizukuishi' => - array ( - ), - 'sumita' => - array ( - ), - 'tanohata' => - array ( - ), - 'tono' => - array ( - ), - 'yahaba' => - array ( - ), - 'yamada' => - array ( - ), - ), - 'kagawa' => - array ( - 'ayagawa' => - array ( - ), - 'higashikagawa' => - array ( - ), - 'kanonji' => - array ( - ), - 'kotohira' => - array ( - ), - 'manno' => - array ( - ), - 'marugame' => - array ( - ), - 'mitoyo' => - array ( - ), - 'naoshima' => - array ( - ), - 'sanuki' => - array ( - ), - 'tadotsu' => - array ( - ), - 'takamatsu' => - array ( - ), - 'tonosho' => - array ( - ), - 'uchinomi' => - array ( - ), - 'utazu' => - array ( - ), - 'zentsuji' => - array ( - ), - ), - 'kagoshima' => - array ( - 'akune' => - array ( - ), - 'amami' => - array ( - ), - 'hioki' => - array ( - ), - 'isa' => - array ( - ), - 'isen' => - array ( - ), - 'izumi' => - array ( - ), - 'kagoshima' => - array ( - ), - 'kanoya' => - array ( - ), - 'kawanabe' => - array ( - ), - 'kinko' => - array ( - ), - 'kouyama' => - array ( - ), - 'makurazaki' => - array ( - ), - 'matsumoto' => - array ( - ), - 'minamitane' => - array ( - ), - 'nakatane' => - array ( - ), - 'nishinoomote' => - array ( - ), - 'satsumasendai' => - array ( - ), - 'soo' => - array ( - ), - 'tarumizu' => - array ( - ), - 'yusui' => - array ( - ), - ), - 'kanagawa' => - array ( - 'aikawa' => - array ( - ), - 'atsugi' => - array ( - ), - 'ayase' => - array ( - ), - 'chigasaki' => - array ( - ), - 'ebina' => - array ( - ), - 'fujisawa' => - array ( - ), - 'hadano' => - array ( - ), - 'hakone' => - array ( - ), - 'hiratsuka' => - array ( - ), - 'isehara' => - array ( - ), - 'kaisei' => - array ( - ), - 'kamakura' => - array ( - ), - 'kiyokawa' => - array ( - ), - 'matsuda' => - array ( - ), - 'minamiashigara' => - array ( - ), - 'miura' => - array ( - ), - 'nakai' => - array ( - ), - 'ninomiya' => - array ( - ), - 'odawara' => - array ( - ), - 'oi' => - array ( - ), - 'oiso' => - array ( - ), - 'sagamihara' => - array ( - ), - 'samukawa' => - array ( - ), - 'tsukui' => - array ( - ), - 'yamakita' => - array ( - ), - 'yamato' => - array ( - ), - 'yokosuka' => - array ( - ), - 'yugawara' => - array ( - ), - 'zama' => - array ( - ), - 'zushi' => - array ( - ), - ), - 'kochi' => - array ( - 'aki' => - array ( - ), - 'geisei' => - array ( - ), - 'hidaka' => - array ( - ), - 'higashitsuno' => - array ( - ), - 'ino' => - array ( - ), - 'kagami' => - array ( - ), - 'kami' => - array ( - ), - 'kitagawa' => - array ( - ), - 'kochi' => - array ( - ), - 'mihara' => - array ( - ), - 'motoyama' => - array ( - ), - 'muroto' => - array ( - ), - 'nahari' => - array ( - ), - 'nakamura' => - array ( - ), - 'nankoku' => - array ( - ), - 'nishitosa' => - array ( - ), - 'niyodogawa' => - array ( - ), - 'ochi' => - array ( - ), - 'okawa' => - array ( - ), - 'otoyo' => - array ( - ), - 'otsuki' => - array ( - ), - 'sakawa' => - array ( - ), - 'sukumo' => - array ( - ), - 'susaki' => - array ( - ), - 'tosa' => - array ( - ), - 'tosashimizu' => - array ( - ), - 'toyo' => - array ( - ), - 'tsuno' => - array ( - ), - 'umaji' => - array ( - ), - 'yasuda' => - array ( - ), - 'yusuhara' => - array ( - ), - ), - 'kumamoto' => - array ( - 'amakusa' => - array ( - ), - 'arao' => - array ( - ), - 'aso' => - array ( - ), - 'choyo' => - array ( - ), - 'gyokuto' => - array ( - ), - 'hitoyoshi' => - array ( - ), - 'kamiamakusa' => - array ( - ), - 'kashima' => - array ( - ), - 'kikuchi' => - array ( - ), - 'kosa' => - array ( - ), - 'kumamoto' => - array ( - ), - 'mashiki' => - array ( - ), - 'mifune' => - array ( - ), - 'minamata' => - array ( - ), - 'minamioguni' => - array ( - ), - 'nagasu' => - array ( - ), - 'nishihara' => - array ( - ), - 'oguni' => - array ( - ), - 'ozu' => - array ( - ), - 'sumoto' => - array ( - ), - 'takamori' => - array ( - ), - 'uki' => - array ( - ), - 'uto' => - array ( - ), - 'yamaga' => - array ( - ), - 'yamato' => - array ( - ), - 'yatsushiro' => - array ( - ), - ), - 'kyoto' => - array ( - 'ayabe' => - array ( - ), - 'fukuchiyama' => - array ( - ), - 'higashiyama' => - array ( - ), - 'ide' => - array ( - ), - 'ine' => - array ( - ), - 'joyo' => - array ( - ), - 'kameoka' => - array ( - ), - 'kamo' => - array ( - ), - 'kita' => - array ( - ), - 'kizu' => - array ( - ), - 'kumiyama' => - array ( - ), - 'kyotamba' => - array ( - ), - 'kyotanabe' => - array ( - ), - 'kyotango' => - array ( - ), - 'maizuru' => - array ( - ), - 'minami' => - array ( - ), - 'minamiyamashiro' => - array ( - ), - 'miyazu' => - array ( - ), - 'muko' => - array ( - ), - 'nagaokakyo' => - array ( - ), - 'nakagyo' => - array ( - ), - 'nantan' => - array ( - ), - 'oyamazaki' => - array ( - ), - 'sakyo' => - array ( - ), - 'seika' => - array ( - ), - 'tanabe' => - array ( - ), - 'uji' => - array ( - ), - 'ujitawara' => - array ( - ), - 'wazuka' => - array ( - ), - 'yamashina' => - array ( - ), - 'yawata' => - array ( - ), - ), - 'mie' => - array ( - 'asahi' => - array ( - ), - 'inabe' => - array ( - ), - 'ise' => - array ( - ), - 'kameyama' => - array ( - ), - 'kawagoe' => - array ( - ), - 'kiho' => - array ( - ), - 'kisosaki' => - array ( - ), - 'kiwa' => - array ( - ), - 'komono' => - array ( - ), - 'kumano' => - array ( - ), - 'kuwana' => - array ( - ), - 'matsusaka' => - array ( - ), - 'meiwa' => - array ( - ), - 'mihama' => - array ( - ), - 'minamiise' => - array ( - ), - 'misugi' => - array ( - ), - 'miyama' => - array ( - ), - 'nabari' => - array ( - ), - 'shima' => - array ( - ), - 'suzuka' => - array ( - ), - 'tado' => - array ( - ), - 'taiki' => - array ( - ), - 'taki' => - array ( - ), - 'tamaki' => - array ( - ), - 'toba' => - array ( - ), - 'tsu' => - array ( - ), - 'udono' => - array ( - ), - 'ureshino' => - array ( - ), - 'watarai' => - array ( - ), - 'yokkaichi' => - array ( - ), - ), - 'miyagi' => - array ( - 'furukawa' => - array ( - ), - 'higashimatsushima' => - array ( - ), - 'ishinomaki' => - array ( - ), - 'iwanuma' => - array ( - ), - 'kakuda' => - array ( - ), - 'kami' => - array ( - ), - 'kawasaki' => - array ( - ), - 'kesennuma' => - array ( - ), - 'marumori' => - array ( - ), - 'matsushima' => - array ( - ), - 'minamisanriku' => - array ( - ), - 'misato' => - array ( - ), - 'murata' => - array ( - ), - 'natori' => - array ( - ), - 'ogawara' => - array ( - ), - 'ohira' => - array ( - ), - 'onagawa' => - array ( - ), - 'osaki' => - array ( - ), - 'rifu' => - array ( - ), - 'semine' => - array ( - ), - 'shibata' => - array ( - ), - 'shichikashuku' => - array ( - ), - 'shikama' => - array ( - ), - 'shiogama' => - array ( - ), - 'shiroishi' => - array ( - ), - 'tagajo' => - array ( - ), - 'taiwa' => - array ( - ), - 'tome' => - array ( - ), - 'tomiya' => - array ( - ), - 'wakuya' => - array ( - ), - 'watari' => - array ( - ), - 'yamamoto' => - array ( - ), - 'zao' => - array ( - ), - ), - 'miyazaki' => - array ( - 'aya' => - array ( - ), - 'ebino' => - array ( - ), - 'gokase' => - array ( - ), - 'hyuga' => - array ( - ), - 'kadogawa' => - array ( - ), - 'kawaminami' => - array ( - ), - 'kijo' => - array ( - ), - 'kitagawa' => - array ( - ), - 'kitakata' => - array ( - ), - 'kitaura' => - array ( - ), - 'kobayashi' => - array ( - ), - 'kunitomi' => - array ( - ), - 'kushima' => - array ( - ), - 'mimata' => - array ( - ), - 'miyakonojo' => - array ( - ), - 'miyazaki' => - array ( - ), - 'morotsuka' => - array ( - ), - 'nichinan' => - array ( - ), - 'nishimera' => - array ( - ), - 'nobeoka' => - array ( - ), - 'saito' => - array ( - ), - 'shiiba' => - array ( - ), - 'shintomi' => - array ( - ), - 'takaharu' => - array ( - ), - 'takanabe' => - array ( - ), - 'takazaki' => - array ( - ), - 'tsuno' => - array ( - ), - ), - 'nagano' => - array ( - 'achi' => - array ( - ), - 'agematsu' => - array ( - ), - 'anan' => - array ( - ), - 'aoki' => - array ( - ), - 'asahi' => - array ( - ), - 'azumino' => - array ( - ), - 'chikuhoku' => - array ( - ), - 'chikuma' => - array ( - ), - 'chino' => - array ( - ), - 'fujimi' => - array ( - ), - 'hakuba' => - array ( - ), - 'hara' => - array ( - ), - 'hiraya' => - array ( - ), - 'iida' => - array ( - ), - 'iijima' => - array ( - ), - 'iiyama' => - array ( - ), - 'iizuna' => - array ( - ), - 'ikeda' => - array ( - ), - 'ikusaka' => - array ( - ), - 'ina' => - array ( - ), - 'karuizawa' => - array ( - ), - 'kawakami' => - array ( - ), - 'kiso' => - array ( - ), - 'kisofukushima' => - array ( - ), - 'kitaaiki' => - array ( - ), - 'komagane' => - array ( - ), - 'komoro' => - array ( - ), - 'matsukawa' => - array ( - ), - 'matsumoto' => - array ( - ), - 'miasa' => - array ( - ), - 'minamiaiki' => - array ( - ), - 'minamimaki' => - array ( - ), - 'minamiminowa' => - array ( - ), - 'minowa' => - array ( - ), - 'miyada' => - array ( - ), - 'miyota' => - array ( - ), - 'mochizuki' => - array ( - ), - 'nagano' => - array ( - ), - 'nagawa' => - array ( - ), - 'nagiso' => - array ( - ), - 'nakagawa' => - array ( - ), - 'nakano' => - array ( - ), - 'nozawaonsen' => - array ( - ), - 'obuse' => - array ( - ), - 'ogawa' => - array ( - ), - 'okaya' => - array ( - ), - 'omachi' => - array ( - ), - 'omi' => - array ( - ), - 'ookuwa' => - array ( - ), - 'ooshika' => - array ( - ), - 'otaki' => - array ( - ), - 'otari' => - array ( - ), - 'sakae' => - array ( - ), - 'sakaki' => - array ( - ), - 'saku' => - array ( - ), - 'sakuho' => - array ( - ), - 'shimosuwa' => - array ( - ), - 'shinanomachi' => - array ( - ), - 'shiojiri' => - array ( - ), - 'suwa' => - array ( - ), - 'suzaka' => - array ( - ), - 'takagi' => - array ( - ), - 'takamori' => - array ( - ), - 'takayama' => - array ( - ), - 'tateshina' => - array ( - ), - 'tatsuno' => - array ( - ), - 'togakushi' => - array ( - ), - 'togura' => - array ( - ), - 'tomi' => - array ( - ), - 'ueda' => - array ( - ), - 'wada' => - array ( - ), - 'yamagata' => - array ( - ), - 'yamanouchi' => - array ( - ), - 'yasaka' => - array ( - ), - 'yasuoka' => - array ( - ), - ), - 'nagasaki' => - array ( - 'chijiwa' => - array ( - ), - 'futsu' => - array ( - ), - 'goto' => - array ( - ), - 'hasami' => - array ( - ), - 'hirado' => - array ( - ), - 'iki' => - array ( - ), - 'isahaya' => - array ( - ), - 'kawatana' => - array ( - ), - 'kuchinotsu' => - array ( - ), - 'matsuura' => - array ( - ), - 'nagasaki' => - array ( - ), - 'obama' => - array ( - ), - 'omura' => - array ( - ), - 'oseto' => - array ( - ), - 'saikai' => - array ( - ), - 'sasebo' => - array ( - ), - 'seihi' => - array ( - ), - 'shimabara' => - array ( - ), - 'shinkamigoto' => - array ( - ), - 'togitsu' => - array ( - ), - 'tsushima' => - array ( - ), - 'unzen' => - array ( - ), - ), - 'nara' => - array ( - 'ando' => - array ( - ), - 'gose' => - array ( - ), - 'heguri' => - array ( - ), - 'higashiyoshino' => - array ( - ), - 'ikaruga' => - array ( - ), - 'ikoma' => - array ( - ), - 'kamikitayama' => - array ( - ), - 'kanmaki' => - array ( - ), - 'kashiba' => - array ( - ), - 'kashihara' => - array ( - ), - 'katsuragi' => - array ( - ), - 'kawai' => - array ( - ), - 'kawakami' => - array ( - ), - 'kawanishi' => - array ( - ), - 'koryo' => - array ( - ), - 'kurotaki' => - array ( - ), - 'mitsue' => - array ( - ), - 'miyake' => - array ( - ), - 'nara' => - array ( - ), - 'nosegawa' => - array ( - ), - 'oji' => - array ( - ), - 'ouda' => - array ( - ), - 'oyodo' => - array ( - ), - 'sakurai' => - array ( - ), - 'sango' => - array ( - ), - 'shimoichi' => - array ( - ), - 'shimokitayama' => - array ( - ), - 'shinjo' => - array ( - ), - 'soni' => - array ( - ), - 'takatori' => - array ( - ), - 'tawaramoto' => - array ( - ), - 'tenkawa' => - array ( - ), - 'tenri' => - array ( - ), - 'uda' => - array ( - ), - 'yamatokoriyama' => - array ( - ), - 'yamatotakada' => - array ( - ), - 'yamazoe' => - array ( - ), - 'yoshino' => - array ( - ), - ), - 'niigata' => - array ( - 'aga' => - array ( - ), - 'agano' => - array ( - ), - 'gosen' => - array ( - ), - 'itoigawa' => - array ( - ), - 'izumozaki' => - array ( - ), - 'joetsu' => - array ( - ), - 'kamo' => - array ( - ), - 'kariwa' => - array ( - ), - 'kashiwazaki' => - array ( - ), - 'minamiuonuma' => - array ( - ), - 'mitsuke' => - array ( - ), - 'muika' => - array ( - ), - 'murakami' => - array ( - ), - 'myoko' => - array ( - ), - 'nagaoka' => - array ( - ), - 'niigata' => - array ( - ), - 'ojiya' => - array ( - ), - 'omi' => - array ( - ), - 'sado' => - array ( - ), - 'sanjo' => - array ( - ), - 'seiro' => - array ( - ), - 'seirou' => - array ( - ), - 'sekikawa' => - array ( - ), - 'shibata' => - array ( - ), - 'tagami' => - array ( - ), - 'tainai' => - array ( - ), - 'tochio' => - array ( - ), - 'tokamachi' => - array ( - ), - 'tsubame' => - array ( - ), - 'tsunan' => - array ( - ), - 'uonuma' => - array ( - ), - 'yahiko' => - array ( - ), - 'yoita' => - array ( - ), - 'yuzawa' => - array ( - ), - ), - 'oita' => - array ( - 'beppu' => - array ( - ), - 'bungoono' => - array ( - ), - 'bungotakada' => - array ( - ), - 'hasama' => - array ( - ), - 'hiji' => - array ( - ), - 'himeshima' => - array ( - ), - 'hita' => - array ( - ), - 'kamitsue' => - array ( - ), - 'kokonoe' => - array ( - ), - 'kuju' => - array ( - ), - 'kunisaki' => - array ( - ), - 'kusu' => - array ( - ), - 'oita' => - array ( - ), - 'saiki' => - array ( - ), - 'taketa' => - array ( - ), - 'tsukumi' => - array ( - ), - 'usa' => - array ( - ), - 'usuki' => - array ( - ), - 'yufu' => - array ( - ), - ), - 'okayama' => - array ( - 'akaiwa' => - array ( - ), - 'asakuchi' => - array ( - ), - 'bizen' => - array ( - ), - 'hayashima' => - array ( - ), - 'ibara' => - array ( - ), - 'kagamino' => - array ( - ), - 'kasaoka' => - array ( - ), - 'kibichuo' => - array ( - ), - 'kumenan' => - array ( - ), - 'kurashiki' => - array ( - ), - 'maniwa' => - array ( - ), - 'misaki' => - array ( - ), - 'nagi' => - array ( - ), - 'niimi' => - array ( - ), - 'nishiawakura' => - array ( - ), - 'okayama' => - array ( - ), - 'satosho' => - array ( - ), - 'setouchi' => - array ( - ), - 'shinjo' => - array ( - ), - 'shoo' => - array ( - ), - 'soja' => - array ( - ), - 'takahashi' => - array ( - ), - 'tamano' => - array ( - ), - 'tsuyama' => - array ( - ), - 'wake' => - array ( - ), - 'yakage' => - array ( - ), - ), - 'okinawa' => - array ( - 'aguni' => - array ( - ), - 'ginowan' => - array ( - ), - 'ginoza' => - array ( - ), - 'gushikami' => - array ( - ), - 'haebaru' => - array ( - ), - 'higashi' => - array ( - ), - 'hirara' => - array ( - ), - 'iheya' => - array ( - ), - 'ishigaki' => - array ( - ), - 'ishikawa' => - array ( - ), - 'itoman' => - array ( - ), - 'izena' => - array ( - ), - 'kadena' => - array ( - ), - 'kin' => - array ( - ), - 'kitadaito' => - array ( - ), - 'kitanakagusuku' => - array ( - ), - 'kumejima' => - array ( - ), - 'kunigami' => - array ( - ), - 'minamidaito' => - array ( - ), - 'motobu' => - array ( - ), - 'nago' => - array ( - ), - 'naha' => - array ( - ), - 'nakagusuku' => - array ( - ), - 'nakijin' => - array ( - ), - 'nanjo' => - array ( - ), - 'nishihara' => - array ( - ), - 'ogimi' => - array ( - ), - 'okinawa' => - array ( - ), - 'onna' => - array ( - ), - 'shimoji' => - array ( - ), - 'taketomi' => - array ( - ), - 'tarama' => - array ( - ), - 'tokashiki' => - array ( - ), - 'tomigusuku' => - array ( - ), - 'tonaki' => - array ( - ), - 'urasoe' => - array ( - ), - 'uruma' => - array ( - ), - 'yaese' => - array ( - ), - 'yomitan' => - array ( - ), - 'yonabaru' => - array ( - ), - 'yonaguni' => - array ( - ), - 'zamami' => - array ( - ), - ), - 'osaka' => - array ( - 'abeno' => - array ( - ), - 'chihayaakasaka' => - array ( - ), - 'chuo' => - array ( - ), - 'daito' => - array ( - ), - 'fujiidera' => - array ( - ), - 'habikino' => - array ( - ), - 'hannan' => - array ( - ), - 'higashiosaka' => - array ( - ), - 'higashisumiyoshi' => - array ( - ), - 'higashiyodogawa' => - array ( - ), - 'hirakata' => - array ( - ), - 'ibaraki' => - array ( - ), - 'ikeda' => - array ( - ), - 'izumi' => - array ( - ), - 'izumiotsu' => - array ( - ), - 'izumisano' => - array ( - ), - 'kadoma' => - array ( - ), - 'kaizuka' => - array ( - ), - 'kanan' => - array ( - ), - 'kashiwara' => - array ( - ), - 'katano' => - array ( - ), - 'kawachinagano' => - array ( - ), - 'kishiwada' => - array ( - ), - 'kita' => - array ( - ), - 'kumatori' => - array ( - ), - 'matsubara' => - array ( - ), - 'minato' => - array ( - ), - 'minoh' => - array ( - ), - 'misaki' => - array ( - ), - 'moriguchi' => - array ( - ), - 'neyagawa' => - array ( - ), - 'nishi' => - array ( - ), - 'nose' => - array ( - ), - 'osakasayama' => - array ( - ), - 'sakai' => - array ( - ), - 'sayama' => - array ( - ), - 'sennan' => - array ( - ), - 'settsu' => - array ( - ), - 'shijonawate' => - array ( - ), - 'shimamoto' => - array ( - ), - 'suita' => - array ( - ), - 'tadaoka' => - array ( - ), - 'taishi' => - array ( - ), - 'tajiri' => - array ( - ), - 'takaishi' => - array ( - ), - 'takatsuki' => - array ( - ), - 'tondabayashi' => - array ( - ), - 'toyonaka' => - array ( - ), - 'toyono' => - array ( - ), - 'yao' => - array ( - ), - ), - 'saga' => - array ( - 'ariake' => - array ( - ), - 'arita' => - array ( - ), - 'fukudomi' => - array ( - ), - 'genkai' => - array ( - ), - 'hamatama' => - array ( - ), - 'hizen' => - array ( - ), - 'imari' => - array ( - ), - 'kamimine' => - array ( - ), - 'kanzaki' => - array ( - ), - 'karatsu' => - array ( - ), - 'kashima' => - array ( - ), - 'kitagata' => - array ( - ), - 'kitahata' => - array ( - ), - 'kiyama' => - array ( - ), - 'kouhoku' => - array ( - ), - 'kyuragi' => - array ( - ), - 'nishiarita' => - array ( - ), - 'ogi' => - array ( - ), - 'omachi' => - array ( - ), - 'ouchi' => - array ( - ), - 'saga' => - array ( - ), - 'shiroishi' => - array ( - ), - 'taku' => - array ( - ), - 'tara' => - array ( - ), - 'tosu' => - array ( - ), - 'yoshinogari' => - array ( - ), - ), - 'saitama' => - array ( - 'arakawa' => - array ( - ), - 'asaka' => - array ( - ), - 'chichibu' => - array ( - ), - 'fujimi' => - array ( - ), - 'fujimino' => - array ( - ), - 'fukaya' => - array ( - ), - 'hanno' => - array ( - ), - 'hanyu' => - array ( - ), - 'hasuda' => - array ( - ), - 'hatogaya' => - array ( - ), - 'hatoyama' => - array ( - ), - 'hidaka' => - array ( - ), - 'higashichichibu' => - array ( - ), - 'higashimatsuyama' => - array ( - ), - 'honjo' => - array ( - ), - 'ina' => - array ( - ), - 'iruma' => - array ( - ), - 'iwatsuki' => - array ( - ), - 'kamiizumi' => - array ( - ), - 'kamikawa' => - array ( - ), - 'kamisato' => - array ( - ), - 'kasukabe' => - array ( - ), - 'kawagoe' => - array ( - ), - 'kawaguchi' => - array ( - ), - 'kawajima' => - array ( - ), - 'kazo' => - array ( - ), - 'kitamoto' => - array ( - ), - 'koshigaya' => - array ( - ), - 'kounosu' => - array ( - ), - 'kuki' => - array ( - ), - 'kumagaya' => - array ( - ), - 'matsubushi' => - array ( - ), - 'minano' => - array ( - ), - 'misato' => - array ( - ), - 'miyashiro' => - array ( - ), - 'miyoshi' => - array ( - ), - 'moroyama' => - array ( - ), - 'nagatoro' => - array ( - ), - 'namegawa' => - array ( - ), - 'niiza' => - array ( - ), - 'ogano' => - array ( - ), - 'ogawa' => - array ( - ), - 'ogose' => - array ( - ), - 'okegawa' => - array ( - ), - 'omiya' => - array ( - ), - 'otaki' => - array ( - ), - 'ranzan' => - array ( - ), - 'ryokami' => - array ( - ), - 'saitama' => - array ( - ), - 'sakado' => - array ( - ), - 'satte' => - array ( - ), - 'sayama' => - array ( - ), - 'shiki' => - array ( - ), - 'shiraoka' => - array ( - ), - 'soka' => - array ( - ), - 'sugito' => - array ( - ), - 'toda' => - array ( - ), - 'tokigawa' => - array ( - ), - 'tokorozawa' => - array ( - ), - 'tsurugashima' => - array ( - ), - 'urawa' => - array ( - ), - 'warabi' => - array ( - ), - 'yashio' => - array ( - ), - 'yokoze' => - array ( - ), - 'yono' => - array ( - ), - 'yorii' => - array ( - ), - 'yoshida' => - array ( - ), - 'yoshikawa' => - array ( - ), - 'yoshimi' => - array ( - ), - ), - 'shiga' => - array ( - 'aisho' => - array ( - ), - 'gamo' => - array ( - ), - 'higashiomi' => - array ( - ), - 'hikone' => - array ( - ), - 'koka' => - array ( - ), - 'konan' => - array ( - ), - 'kosei' => - array ( - ), - 'koto' => - array ( - ), - 'kusatsu' => - array ( - ), - 'maibara' => - array ( - ), - 'moriyama' => - array ( - ), - 'nagahama' => - array ( - ), - 'nishiazai' => - array ( - ), - 'notogawa' => - array ( - ), - 'omihachiman' => - array ( - ), - 'otsu' => - array ( - ), - 'ritto' => - array ( - ), - 'ryuoh' => - array ( - ), - 'takashima' => - array ( - ), - 'takatsuki' => - array ( - ), - 'torahime' => - array ( - ), - 'toyosato' => - array ( - ), - 'yasu' => - array ( - ), - ), - 'shimane' => - array ( - 'akagi' => - array ( - ), - 'ama' => - array ( - ), - 'gotsu' => - array ( - ), - 'hamada' => - array ( - ), - 'higashiizumo' => - array ( - ), - 'hikawa' => - array ( - ), - 'hikimi' => - array ( - ), - 'izumo' => - array ( - ), - 'kakinoki' => - array ( - ), - 'masuda' => - array ( - ), - 'matsue' => - array ( - ), - 'misato' => - array ( - ), - 'nishinoshima' => - array ( - ), - 'ohda' => - array ( - ), - 'okinoshima' => - array ( - ), - 'okuizumo' => - array ( - ), - 'shimane' => - array ( - ), - 'tamayu' => - array ( - ), - 'tsuwano' => - array ( - ), - 'unnan' => - array ( - ), - 'yakumo' => - array ( - ), - 'yasugi' => - array ( - ), - 'yatsuka' => - array ( - ), - ), - 'shizuoka' => - array ( - 'arai' => - array ( - ), - 'atami' => - array ( - ), - 'fuji' => - array ( - ), - 'fujieda' => - array ( - ), - 'fujikawa' => - array ( - ), - 'fujinomiya' => - array ( - ), - 'fukuroi' => - array ( - ), - 'gotemba' => - array ( - ), - 'haibara' => - array ( - ), - 'hamamatsu' => - array ( - ), - 'higashiizu' => - array ( - ), - 'ito' => - array ( - ), - 'iwata' => - array ( - ), - 'izu' => - array ( - ), - 'izunokuni' => - array ( - ), - 'kakegawa' => - array ( - ), - 'kannami' => - array ( - ), - 'kawanehon' => - array ( - ), - 'kawazu' => - array ( - ), - 'kikugawa' => - array ( - ), - 'kosai' => - array ( - ), - 'makinohara' => - array ( - ), - 'matsuzaki' => - array ( - ), - 'minamiizu' => - array ( - ), - 'mishima' => - array ( - ), - 'morimachi' => - array ( - ), - 'nishiizu' => - array ( - ), - 'numazu' => - array ( - ), - 'omaezaki' => - array ( - ), - 'shimada' => - array ( - ), - 'shimizu' => - array ( - ), - 'shimoda' => - array ( - ), - 'shizuoka' => - array ( - ), - 'susono' => - array ( - ), - 'yaizu' => - array ( - ), - 'yoshida' => - array ( - ), - ), - 'tochigi' => - array ( - 'ashikaga' => - array ( - ), - 'bato' => - array ( - ), - 'haga' => - array ( - ), - 'ichikai' => - array ( - ), - 'iwafune' => - array ( - ), - 'kaminokawa' => - array ( - ), - 'kanuma' => - array ( - ), - 'karasuyama' => - array ( - ), - 'kuroiso' => - array ( - ), - 'mashiko' => - array ( - ), - 'mibu' => - array ( - ), - 'moka' => - array ( - ), - 'motegi' => - array ( - ), - 'nasu' => - array ( - ), - 'nasushiobara' => - array ( - ), - 'nikko' => - array ( - ), - 'nishikata' => - array ( - ), - 'nogi' => - array ( - ), - 'ohira' => - array ( - ), - 'ohtawara' => - array ( - ), - 'oyama' => - array ( - ), - 'sakura' => - array ( - ), - 'sano' => - array ( - ), - 'shimotsuke' => - array ( - ), - 'shioya' => - array ( - ), - 'takanezawa' => - array ( - ), - 'tochigi' => - array ( - ), - 'tsuga' => - array ( - ), - 'ujiie' => - array ( - ), - 'utsunomiya' => - array ( - ), - 'yaita' => - array ( - ), - ), - 'tokushima' => - array ( - 'aizumi' => - array ( - ), - 'anan' => - array ( - ), - 'ichiba' => - array ( - ), - 'itano' => - array ( - ), - 'kainan' => - array ( - ), - 'komatsushima' => - array ( - ), - 'matsushige' => - array ( - ), - 'mima' => - array ( - ), - 'minami' => - array ( - ), - 'miyoshi' => - array ( - ), - 'mugi' => - array ( - ), - 'nakagawa' => - array ( - ), - 'naruto' => - array ( - ), - 'sanagochi' => - array ( - ), - 'shishikui' => - array ( - ), - 'tokushima' => - array ( - ), - 'wajiki' => - array ( - ), - ), - 'tokyo' => - array ( - 'adachi' => - array ( - ), - 'akiruno' => - array ( - ), - 'akishima' => - array ( - ), - 'aogashima' => - array ( - ), - 'arakawa' => - array ( - ), - 'bunkyo' => - array ( - ), - 'chiyoda' => - array ( - ), - 'chofu' => - array ( - ), - 'chuo' => - array ( - ), - 'edogawa' => - array ( - ), - 'fuchu' => - array ( - ), - 'fussa' => - array ( - ), - 'hachijo' => - array ( - ), - 'hachioji' => - array ( - ), - 'hamura' => - array ( - ), - 'higashikurume' => - array ( - ), - 'higashimurayama' => - array ( - ), - 'higashiyamato' => - array ( - ), - 'hino' => - array ( - ), - 'hinode' => - array ( - ), - 'hinohara' => - array ( - ), - 'inagi' => - array ( - ), - 'itabashi' => - array ( - ), - 'katsushika' => - array ( - ), - 'kita' => - array ( - ), - 'kiyose' => - array ( - ), - 'kodaira' => - array ( - ), - 'koganei' => - array ( - ), - 'kokubunji' => - array ( - ), - 'komae' => - array ( - ), - 'koto' => - array ( - ), - 'kouzushima' => - array ( - ), - 'kunitachi' => - array ( - ), - 'machida' => - array ( - ), - 'meguro' => - array ( - ), - 'minato' => - array ( - ), - 'mitaka' => - array ( - ), - 'mizuho' => - array ( - ), - 'musashimurayama' => - array ( - ), - 'musashino' => - array ( - ), - 'nakano' => - array ( - ), - 'nerima' => - array ( - ), - 'ogasawara' => - array ( - ), - 'okutama' => - array ( - ), - 'ome' => - array ( - ), - 'oshima' => - array ( - ), - 'ota' => - array ( - ), - 'setagaya' => - array ( - ), - 'shibuya' => - array ( - ), - 'shinagawa' => - array ( - ), - 'shinjuku' => - array ( - ), - 'suginami' => - array ( - ), - 'sumida' => - array ( - ), - 'tachikawa' => - array ( - ), - 'taito' => - array ( - ), - 'tama' => - array ( - ), - 'toshima' => - array ( - ), - ), - 'tottori' => - array ( - 'chizu' => - array ( - ), - 'hino' => - array ( - ), - 'kawahara' => - array ( - ), - 'koge' => - array ( - ), - 'kotoura' => - array ( - ), - 'misasa' => - array ( - ), - 'nanbu' => - array ( - ), - 'nichinan' => - array ( - ), - 'sakaiminato' => - array ( - ), - 'tottori' => - array ( - ), - 'wakasa' => - array ( - ), - 'yazu' => - array ( - ), - 'yonago' => - array ( - ), - ), - 'toyama' => - array ( - 'asahi' => - array ( - ), - 'fuchu' => - array ( - ), - 'fukumitsu' => - array ( - ), - 'funahashi' => - array ( - ), - 'himi' => - array ( - ), - 'imizu' => - array ( - ), - 'inami' => - array ( - ), - 'johana' => - array ( - ), - 'kamiichi' => - array ( - ), - 'kurobe' => - array ( - ), - 'nakaniikawa' => - array ( - ), - 'namerikawa' => - array ( - ), - 'nanto' => - array ( - ), - 'nyuzen' => - array ( - ), - 'oyabe' => - array ( - ), - 'taira' => - array ( - ), - 'takaoka' => - array ( - ), - 'tateyama' => - array ( - ), - 'toga' => - array ( - ), - 'tonami' => - array ( - ), - 'toyama' => - array ( - ), - 'unazuki' => - array ( - ), - 'uozu' => - array ( - ), - 'yamada' => - array ( - ), - ), - 'wakayama' => - array ( - 'arida' => - array ( - ), - 'aridagawa' => - array ( - ), - 'gobo' => - array ( - ), - 'hashimoto' => - array ( - ), - 'hidaka' => - array ( - ), - 'hirogawa' => - array ( - ), - 'inami' => - array ( - ), - 'iwade' => - array ( - ), - 'kainan' => - array ( - ), - 'kamitonda' => - array ( - ), - 'katsuragi' => - array ( - ), - 'kimino' => - array ( - ), - 'kinokawa' => - array ( - ), - 'kitayama' => - array ( - ), - 'koya' => - array ( - ), - 'koza' => - array ( - ), - 'kozagawa' => - array ( - ), - 'kudoyama' => - array ( - ), - 'kushimoto' => - array ( - ), - 'mihama' => - array ( - ), - 'misato' => - array ( - ), - 'nachikatsuura' => - array ( - ), - 'shingu' => - array ( - ), - 'shirahama' => - array ( - ), - 'taiji' => - array ( - ), - 'tanabe' => - array ( - ), - 'wakayama' => - array ( - ), - 'yuasa' => - array ( - ), - 'yura' => - array ( - ), - ), - 'yamagata' => - array ( - 'asahi' => - array ( - ), - 'funagata' => - array ( - ), - 'higashine' => - array ( - ), - 'iide' => - array ( - ), - 'kahoku' => - array ( - ), - 'kaminoyama' => - array ( - ), - 'kaneyama' => - array ( - ), - 'kawanishi' => - array ( - ), - 'mamurogawa' => - array ( - ), - 'mikawa' => - array ( - ), - 'murayama' => - array ( - ), - 'nagai' => - array ( - ), - 'nakayama' => - array ( - ), - 'nanyo' => - array ( - ), - 'nishikawa' => - array ( - ), - 'obanazawa' => - array ( - ), - 'oe' => - array ( - ), - 'oguni' => - array ( - ), - 'ohkura' => - array ( - ), - 'oishida' => - array ( - ), - 'sagae' => - array ( - ), - 'sakata' => - array ( - ), - 'sakegawa' => - array ( - ), - 'shinjo' => - array ( - ), - 'shirataka' => - array ( - ), - 'shonai' => - array ( - ), - 'takahata' => - array ( - ), - 'tendo' => - array ( - ), - 'tozawa' => - array ( - ), - 'tsuruoka' => - array ( - ), - 'yamagata' => - array ( - ), - 'yamanobe' => - array ( - ), - 'yonezawa' => - array ( - ), - 'yuza' => - array ( - ), - ), - 'yamaguchi' => - array ( - 'abu' => - array ( - ), - 'hagi' => - array ( - ), - 'hikari' => - array ( - ), - 'hofu' => - array ( - ), - 'iwakuni' => - array ( - ), - 'kudamatsu' => - array ( - ), - 'mitou' => - array ( - ), - 'nagato' => - array ( - ), - 'oshima' => - array ( - ), - 'shimonoseki' => - array ( - ), - 'shunan' => - array ( - ), - 'tabuse' => - array ( - ), - 'tokuyama' => - array ( - ), - 'toyota' => - array ( - ), - 'ube' => - array ( - ), - 'yuu' => - array ( - ), - ), - 'yamanashi' => - array ( - 'chuo' => - array ( - ), - 'doshi' => - array ( - ), - 'fuefuki' => - array ( - ), - 'fujikawa' => - array ( - ), - 'fujikawaguchiko' => - array ( - ), - 'fujiyoshida' => - array ( - ), - 'hayakawa' => - array ( - ), - 'hokuto' => - array ( - ), - 'ichikawamisato' => - array ( - ), - 'kai' => - array ( - ), - 'kofu' => - array ( - ), - 'koshu' => - array ( - ), - 'kosuge' => - array ( - ), - 'minami-alps' => - array ( - ), - 'minobu' => - array ( - ), - 'nakamichi' => - array ( - ), - 'nanbu' => - array ( - ), - 'narusawa' => - array ( - ), - 'nirasaki' => - array ( - ), - 'nishikatsura' => - array ( - ), - 'oshino' => - array ( - ), - 'otsuki' => - array ( - ), - 'showa' => - array ( - ), - 'tabayama' => - array ( - ), - 'tsuru' => - array ( - ), - 'uenohara' => - array ( - ), - 'yamanakako' => - array ( - ), - 'yamanashi' => - array ( - ), - ), - 'xn--4pvxs' => - array ( - ), - 'xn--vgu402c' => - array ( - ), - 'xn--c3s14m' => - array ( - ), - 'xn--f6qx53a' => - array ( - ), - 'xn--8pvr4u' => - array ( - ), - 'xn--uist22h' => - array ( - ), - 'xn--djrs72d6uy' => - array ( - ), - 'xn--mkru45i' => - array ( - ), - 'xn--0trq7p7nn' => - array ( - ), - 'xn--8ltr62k' => - array ( - ), - 'xn--2m4a15e' => - array ( - ), - 'xn--efvn9s' => - array ( - ), - 'xn--32vp30h' => - array ( - ), - 'xn--4it797k' => - array ( - ), - 'xn--1lqs71d' => - array ( - ), - 'xn--5rtp49c' => - array ( - ), - 'xn--5js045d' => - array ( - ), - 'xn--ehqz56n' => - array ( - ), - 'xn--1lqs03n' => - array ( - ), - 'xn--qqqt11m' => - array ( - ), - 'xn--kbrq7o' => - array ( - ), - 'xn--pssu33l' => - array ( - ), - 'xn--ntsq17g' => - array ( - ), - 'xn--uisz3g' => - array ( - ), - 'xn--6btw5a' => - array ( - ), - 'xn--1ctwo' => - array ( - ), - 'xn--6orx2r' => - array ( - ), - 'xn--rht61e' => - array ( - ), - 'xn--rht27z' => - array ( - ), - 'xn--djty4k' => - array ( - ), - 'xn--nit225k' => - array ( - ), - 'xn--rht3d' => - array ( - ), - 'xn--klty5x' => - array ( - ), - 'xn--kltx9a' => - array ( - ), - 'xn--kltp7d' => - array ( - ), - 'xn--uuwu58a' => - array ( - ), - 'xn--zbx025d' => - array ( - ), - 'xn--ntso0iqx3a' => - array ( - ), - 'xn--elqq16h' => - array ( - ), - 'xn--4it168d' => - array ( - ), - 'xn--klt787d' => - array ( - ), - 'xn--rny31h' => - array ( - ), - 'xn--7t0a264c' => - array ( - ), - 'xn--5rtq34k' => - array ( - ), - 'xn--k7yn95e' => - array ( - ), - 'xn--tor131o' => - array ( - ), - 'xn--d5qv7z876c' => - array ( - ), - 'kawasaki' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'kitakyushu' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'kobe' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'nagoya' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'sapporo' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'sendai' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'yokohama' => - array ( - '*' => - array ( - ), - 'city' => - array ( - '!' => '', - ), - ), - 'blogspot' => - array ( - ), - ), - 'ke' => - array ( - '*' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - ), - 'kg' => - array ( - 'org' => - array ( - ), - 'net' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - ), - 'kh' => - array ( - '*' => - array ( - ), - ), - 'ki' => - array ( - 'edu' => - array ( - ), - 'biz' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - 'com' => - array ( - ), - ), - 'km' => - array ( - 'org' => - array ( - ), - 'nom' => - array ( - ), - 'gov' => - array ( - ), - 'prd' => - array ( - ), - 'tm' => - array ( - ), - 'edu' => - array ( - ), - 'mil' => - array ( - ), - 'ass' => - array ( - ), - 'com' => - array ( - ), - 'coop' => - array ( - ), - 'asso' => - array ( - ), - 'presse' => - array ( - ), - 'medecin' => - array ( - ), - 'notaires' => - array ( - ), - 'pharmaciens' => - array ( - ), - 'veterinaire' => - array ( - ), - 'gouv' => - array ( - ), - ), - 'kn' => - array ( - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - ), - 'kp' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'rep' => - array ( - ), - 'tra' => - array ( - ), - ), - 'kr' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'es' => - array ( - ), - 'go' => - array ( - ), - 'hs' => - array ( - ), - 'kg' => - array ( - ), - 'mil' => - array ( - ), - 'ms' => - array ( - ), - 'ne' => - array ( - ), - 'or' => - array ( - ), - 'pe' => - array ( - ), - 're' => - array ( - ), - 'sc' => - array ( - ), - 'busan' => - array ( - ), - 'chungbuk' => - array ( - ), - 'chungnam' => - array ( - ), - 'daegu' => - array ( - ), - 'daejeon' => - array ( - ), - 'gangwon' => - array ( - ), - 'gwangju' => - array ( - ), - 'gyeongbuk' => - array ( - ), - 'gyeonggi' => - array ( - ), - 'gyeongnam' => - array ( - ), - 'incheon' => - array ( - ), - 'jeju' => - array ( - ), - 'jeonbuk' => - array ( - ), - 'jeonnam' => - array ( - ), - 'seoul' => - array ( - ), - 'ulsan' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'kw' => - array ( - '*' => - array ( - ), - ), - 'ky' => - array ( - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - ), - 'kz' => - array ( - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - ), - ), - 'la' => - array ( - 'int' => - array ( - ), - 'net' => - array ( - ), - 'info' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'per' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'c' => - array ( - ), - ), - 'lb' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'lc' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'co' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - ), - 'li' => - array ( - 'blogspot' => - array ( - ), - ), - 'lk' => - array ( - 'gov' => - array ( - ), - 'sch' => - array ( - ), - 'net' => - array ( - ), - 'int' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'ngo' => - array ( - ), - 'soc' => - array ( - ), - 'web' => - array ( - ), - 'ltd' => - array ( - ), - 'assn' => - array ( - ), - 'grp' => - array ( - ), - 'hotel' => - array ( - ), - 'ac' => - array ( - ), - ), - 'lr' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - ), - 'ls' => - array ( - 'co' => - array ( - ), - 'org' => - array ( - ), - ), - 'lt' => - array ( - 'gov' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'lu' => - array ( - 'blogspot' => - array ( - ), - ), - 'lv' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'mil' => - array ( - ), - 'id' => - array ( - ), - 'net' => - array ( - ), - 'asn' => - array ( - ), - 'conf' => - array ( - ), - ), - 'ly' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'plc' => - array ( - ), - 'edu' => - array ( - ), - 'sch' => - array ( - ), - 'med' => - array ( - ), - 'org' => - array ( - ), - 'id' => - array ( - ), - ), - 'ma' => - array ( - 'co' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'ac' => - array ( - ), - 'press' => - array ( - ), - ), - 'mc' => - array ( - 'tm' => - array ( - ), - 'asso' => - array ( - ), - ), - 'md' => - array ( - 'blogspot' => - array ( - ), - ), - 'me' => - array ( - 'co' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'ac' => - array ( - ), - 'gov' => - array ( - ), - 'its' => - array ( - ), - 'priv' => - array ( - ), - 'diskstation' => - array ( - ), - 'dscloud' => - array ( - ), - 'i234' => - array ( - ), - 'myds' => - array ( - ), - 'synology' => - array ( - ), - ), - 'mg' => - array ( - 'org' => - array ( - ), - 'nom' => - array ( - ), - 'gov' => - array ( - ), - 'prd' => - array ( - ), - 'tm' => - array ( - ), - 'edu' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - ), - 'co' => - array ( - ), - ), - 'mh' => - array ( - ), - 'mil' => - array ( - ), - 'mk' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'inf' => - array ( - ), - 'name' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ml' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gouv' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'presse' => - array ( - ), - ), - 'mm' => - array ( - '*' => - array ( - ), - ), - 'mn' => - array ( - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'nyc' => - array ( - ), - ), - 'mo' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - ), - 'mobi' => - array ( - 'dscloud' => - array ( - ), - ), - 'mp' => - array ( - ), - 'mq' => - array ( - ), - 'mr' => - array ( - 'gov' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ms' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'mt' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'mu' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'or' => - array ( - ), - ), - 'museum' => - array ( - 'academy' => - array ( - ), - 'agriculture' => - array ( - ), - 'air' => - array ( - ), - 'airguard' => - array ( - ), - 'alabama' => - array ( - ), - 'alaska' => - array ( - ), - 'amber' => - array ( - ), - 'ambulance' => - array ( - ), - 'american' => - array ( - ), - 'americana' => - array ( - ), - 'americanantiques' => - array ( - ), - 'americanart' => - array ( - ), - 'amsterdam' => - array ( - ), - 'and' => - array ( - ), - 'annefrank' => - array ( - ), - 'anthro' => - array ( - ), - 'anthropology' => - array ( - ), - 'antiques' => - array ( - ), - 'aquarium' => - array ( - ), - 'arboretum' => - array ( - ), - 'archaeological' => - array ( - ), - 'archaeology' => - array ( - ), - 'architecture' => - array ( - ), - 'art' => - array ( - ), - 'artanddesign' => - array ( - ), - 'artcenter' => - array ( - ), - 'artdeco' => - array ( - ), - 'arteducation' => - array ( - ), - 'artgallery' => - array ( - ), - 'arts' => - array ( - ), - 'artsandcrafts' => - array ( - ), - 'asmatart' => - array ( - ), - 'assassination' => - array ( - ), - 'assisi' => - array ( - ), - 'association' => - array ( - ), - 'astronomy' => - array ( - ), - 'atlanta' => - array ( - ), - 'austin' => - array ( - ), - 'australia' => - array ( - ), - 'automotive' => - array ( - ), - 'aviation' => - array ( - ), - 'axis' => - array ( - ), - 'badajoz' => - array ( - ), - 'baghdad' => - array ( - ), - 'bahn' => - array ( - ), - 'bale' => - array ( - ), - 'baltimore' => - array ( - ), - 'barcelona' => - array ( - ), - 'baseball' => - array ( - ), - 'basel' => - array ( - ), - 'baths' => - array ( - ), - 'bauern' => - array ( - ), - 'beauxarts' => - array ( - ), - 'beeldengeluid' => - array ( - ), - 'bellevue' => - array ( - ), - 'bergbau' => - array ( - ), - 'berkeley' => - array ( - ), - 'berlin' => - array ( - ), - 'bern' => - array ( - ), - 'bible' => - array ( - ), - 'bilbao' => - array ( - ), - 'bill' => - array ( - ), - 'birdart' => - array ( - ), - 'birthplace' => - array ( - ), - 'bonn' => - array ( - ), - 'boston' => - array ( - ), - 'botanical' => - array ( - ), - 'botanicalgarden' => - array ( - ), - 'botanicgarden' => - array ( - ), - 'botany' => - array ( - ), - 'brandywinevalley' => - array ( - ), - 'brasil' => - array ( - ), - 'bristol' => - array ( - ), - 'british' => - array ( - ), - 'britishcolumbia' => - array ( - ), - 'broadcast' => - array ( - ), - 'brunel' => - array ( - ), - 'brussel' => - array ( - ), - 'brussels' => - array ( - ), - 'bruxelles' => - array ( - ), - 'building' => - array ( - ), - 'burghof' => - array ( - ), - 'bus' => - array ( - ), - 'bushey' => - array ( - ), - 'cadaques' => - array ( - ), - 'california' => - array ( - ), - 'cambridge' => - array ( - ), - 'can' => - array ( - ), - 'canada' => - array ( - ), - 'capebreton' => - array ( - ), - 'carrier' => - array ( - ), - 'cartoonart' => - array ( - ), - 'casadelamoneda' => - array ( - ), - 'castle' => - array ( - ), - 'castres' => - array ( - ), - 'celtic' => - array ( - ), - 'center' => - array ( - ), - 'chattanooga' => - array ( - ), - 'cheltenham' => - array ( - ), - 'chesapeakebay' => - array ( - ), - 'chicago' => - array ( - ), - 'children' => - array ( - ), - 'childrens' => - array ( - ), - 'childrensgarden' => - array ( - ), - 'chiropractic' => - array ( - ), - 'chocolate' => - array ( - ), - 'christiansburg' => - array ( - ), - 'cincinnati' => - array ( - ), - 'cinema' => - array ( - ), - 'circus' => - array ( - ), - 'civilisation' => - array ( - ), - 'civilization' => - array ( - ), - 'civilwar' => - array ( - ), - 'clinton' => - array ( - ), - 'clock' => - array ( - ), - 'coal' => - array ( - ), - 'coastaldefence' => - array ( - ), - 'cody' => - array ( - ), - 'coldwar' => - array ( - ), - 'collection' => - array ( - ), - 'colonialwilliamsburg' => - array ( - ), - 'coloradoplateau' => - array ( - ), - 'columbia' => - array ( - ), - 'columbus' => - array ( - ), - 'communication' => - array ( - ), - 'communications' => - array ( - ), - 'community' => - array ( - ), - 'computer' => - array ( - ), - 'computerhistory' => - array ( - ), - 'xn--comunicaes-v6a2o' => - array ( - ), - 'contemporary' => - array ( - ), - 'contemporaryart' => - array ( - ), - 'convent' => - array ( - ), - 'copenhagen' => - array ( - ), - 'corporation' => - array ( - ), - 'xn--correios-e-telecomunicaes-ghc29a' => - array ( - ), - 'corvette' => - array ( - ), - 'costume' => - array ( - ), - 'countryestate' => - array ( - ), - 'county' => - array ( - ), - 'crafts' => - array ( - ), - 'cranbrook' => - array ( - ), - 'creation' => - array ( - ), - 'cultural' => - array ( - ), - 'culturalcenter' => - array ( - ), - 'culture' => - array ( - ), - 'cyber' => - array ( - ), - 'cymru' => - array ( - ), - 'dali' => - array ( - ), - 'dallas' => - array ( - ), - 'database' => - array ( - ), - 'ddr' => - array ( - ), - 'decorativearts' => - array ( - ), - 'delaware' => - array ( - ), - 'delmenhorst' => - array ( - ), - 'denmark' => - array ( - ), - 'depot' => - array ( - ), - 'design' => - array ( - ), - 'detroit' => - array ( - ), - 'dinosaur' => - array ( - ), - 'discovery' => - array ( - ), - 'dolls' => - array ( - ), - 'donostia' => - array ( - ), - 'durham' => - array ( - ), - 'eastafrica' => - array ( - ), - 'eastcoast' => - array ( - ), - 'education' => - array ( - ), - 'educational' => - array ( - ), - 'egyptian' => - array ( - ), - 'eisenbahn' => - array ( - ), - 'elburg' => - array ( - ), - 'elvendrell' => - array ( - ), - 'embroidery' => - array ( - ), - 'encyclopedic' => - array ( - ), - 'england' => - array ( - ), - 'entomology' => - array ( - ), - 'environment' => - array ( - ), - 'environmentalconservation' => - array ( - ), - 'epilepsy' => - array ( - ), - 'essex' => - array ( - ), - 'estate' => - array ( - ), - 'ethnology' => - array ( - ), - 'exeter' => - array ( - ), - 'exhibition' => - array ( - ), - 'family' => - array ( - ), - 'farm' => - array ( - ), - 'farmequipment' => - array ( - ), - 'farmers' => - array ( - ), - 'farmstead' => - array ( - ), - 'field' => - array ( - ), - 'figueres' => - array ( - ), - 'filatelia' => - array ( - ), - 'film' => - array ( - ), - 'fineart' => - array ( - ), - 'finearts' => - array ( - ), - 'finland' => - array ( - ), - 'flanders' => - array ( - ), - 'florida' => - array ( - ), - 'force' => - array ( - ), - 'fortmissoula' => - array ( - ), - 'fortworth' => - array ( - ), - 'foundation' => - array ( - ), - 'francaise' => - array ( - ), - 'frankfurt' => - array ( - ), - 'franziskaner' => - array ( - ), - 'freemasonry' => - array ( - ), - 'freiburg' => - array ( - ), - 'fribourg' => - array ( - ), - 'frog' => - array ( - ), - 'fundacio' => - array ( - ), - 'furniture' => - array ( - ), - 'gallery' => - array ( - ), - 'garden' => - array ( - ), - 'gateway' => - array ( - ), - 'geelvinck' => - array ( - ), - 'gemological' => - array ( - ), - 'geology' => - array ( - ), - 'georgia' => - array ( - ), - 'giessen' => - array ( - ), - 'glas' => - array ( - ), - 'glass' => - array ( - ), - 'gorge' => - array ( - ), - 'grandrapids' => - array ( - ), - 'graz' => - array ( - ), - 'guernsey' => - array ( - ), - 'halloffame' => - array ( - ), - 'hamburg' => - array ( - ), - 'handson' => - array ( - ), - 'harvestcelebration' => - array ( - ), - 'hawaii' => - array ( - ), - 'health' => - array ( - ), - 'heimatunduhren' => - array ( - ), - 'hellas' => - array ( - ), - 'helsinki' => - array ( - ), - 'hembygdsforbund' => - array ( - ), - 'heritage' => - array ( - ), - 'histoire' => - array ( - ), - 'historical' => - array ( - ), - 'historicalsociety' => - array ( - ), - 'historichouses' => - array ( - ), - 'historisch' => - array ( - ), - 'historisches' => - array ( - ), - 'history' => - array ( - ), - 'historyofscience' => - array ( - ), - 'horology' => - array ( - ), - 'house' => - array ( - ), - 'humanities' => - array ( - ), - 'illustration' => - array ( - ), - 'imageandsound' => - array ( - ), - 'indian' => - array ( - ), - 'indiana' => - array ( - ), - 'indianapolis' => - array ( - ), - 'indianmarket' => - array ( - ), - 'intelligence' => - array ( - ), - 'interactive' => - array ( - ), - 'iraq' => - array ( - ), - 'iron' => - array ( - ), - 'isleofman' => - array ( - ), - 'jamison' => - array ( - ), - 'jefferson' => - array ( - ), - 'jerusalem' => - array ( - ), - 'jewelry' => - array ( - ), - 'jewish' => - array ( - ), - 'jewishart' => - array ( - ), - 'jfk' => - array ( - ), - 'journalism' => - array ( - ), - 'judaica' => - array ( - ), - 'judygarland' => - array ( - ), - 'juedisches' => - array ( - ), - 'juif' => - array ( - ), - 'karate' => - array ( - ), - 'karikatur' => - array ( - ), - 'kids' => - array ( - ), - 'koebenhavn' => - array ( - ), - 'koeln' => - array ( - ), - 'kunst' => - array ( - ), - 'kunstsammlung' => - array ( - ), - 'kunstunddesign' => - array ( - ), - 'labor' => - array ( - ), - 'labour' => - array ( - ), - 'lajolla' => - array ( - ), - 'lancashire' => - array ( - ), - 'landes' => - array ( - ), - 'lans' => - array ( - ), - 'xn--lns-qla' => - array ( - ), - 'larsson' => - array ( - ), - 'lewismiller' => - array ( - ), - 'lincoln' => - array ( - ), - 'linz' => - array ( - ), - 'living' => - array ( - ), - 'livinghistory' => - array ( - ), - 'localhistory' => - array ( - ), - 'london' => - array ( - ), - 'losangeles' => - array ( - ), - 'louvre' => - array ( - ), - 'loyalist' => - array ( - ), - 'lucerne' => - array ( - ), - 'luxembourg' => - array ( - ), - 'luzern' => - array ( - ), - 'mad' => - array ( - ), - 'madrid' => - array ( - ), - 'mallorca' => - array ( - ), - 'manchester' => - array ( - ), - 'mansion' => - array ( - ), - 'mansions' => - array ( - ), - 'manx' => - array ( - ), - 'marburg' => - array ( - ), - 'maritime' => - array ( - ), - 'maritimo' => - array ( - ), - 'maryland' => - array ( - ), - 'marylhurst' => - array ( - ), - 'media' => - array ( - ), - 'medical' => - array ( - ), - 'medizinhistorisches' => - array ( - ), - 'meeres' => - array ( - ), - 'memorial' => - array ( - ), - 'mesaverde' => - array ( - ), - 'michigan' => - array ( - ), - 'midatlantic' => - array ( - ), - 'military' => - array ( - ), - 'mill' => - array ( - ), - 'miners' => - array ( - ), - 'mining' => - array ( - ), - 'minnesota' => - array ( - ), - 'missile' => - array ( - ), - 'missoula' => - array ( - ), - 'modern' => - array ( - ), - 'moma' => - array ( - ), - 'money' => - array ( - ), - 'monmouth' => - array ( - ), - 'monticello' => - array ( - ), - 'montreal' => - array ( - ), - 'moscow' => - array ( - ), - 'motorcycle' => - array ( - ), - 'muenchen' => - array ( - ), - 'muenster' => - array ( - ), - 'mulhouse' => - array ( - ), - 'muncie' => - array ( - ), - 'museet' => - array ( - ), - 'museumcenter' => - array ( - ), - 'museumvereniging' => - array ( - ), - 'music' => - array ( - ), - 'national' => - array ( - ), - 'nationalfirearms' => - array ( - ), - 'nationalheritage' => - array ( - ), - 'nativeamerican' => - array ( - ), - 'naturalhistory' => - array ( - ), - 'naturalhistorymuseum' => - array ( - ), - 'naturalsciences' => - array ( - ), - 'nature' => - array ( - ), - 'naturhistorisches' => - array ( - ), - 'natuurwetenschappen' => - array ( - ), - 'naumburg' => - array ( - ), - 'naval' => - array ( - ), - 'nebraska' => - array ( - ), - 'neues' => - array ( - ), - 'newhampshire' => - array ( - ), - 'newjersey' => - array ( - ), - 'newmexico' => - array ( - ), - 'newport' => - array ( - ), - 'newspaper' => - array ( - ), - 'newyork' => - array ( - ), - 'niepce' => - array ( - ), - 'norfolk' => - array ( - ), - 'north' => - array ( - ), - 'nrw' => - array ( - ), - 'nuernberg' => - array ( - ), - 'nuremberg' => - array ( - ), - 'nyc' => - array ( - ), - 'nyny' => - array ( - ), - 'oceanographic' => - array ( - ), - 'oceanographique' => - array ( - ), - 'omaha' => - array ( - ), - 'online' => - array ( - ), - 'ontario' => - array ( - ), - 'openair' => - array ( - ), - 'oregon' => - array ( - ), - 'oregontrail' => - array ( - ), - 'otago' => - array ( - ), - 'oxford' => - array ( - ), - 'pacific' => - array ( - ), - 'paderborn' => - array ( - ), - 'palace' => - array ( - ), - 'paleo' => - array ( - ), - 'palmsprings' => - array ( - ), - 'panama' => - array ( - ), - 'paris' => - array ( - ), - 'pasadena' => - array ( - ), - 'pharmacy' => - array ( - ), - 'philadelphia' => - array ( - ), - 'philadelphiaarea' => - array ( - ), - 'philately' => - array ( - ), - 'phoenix' => - array ( - ), - 'photography' => - array ( - ), - 'pilots' => - array ( - ), - 'pittsburgh' => - array ( - ), - 'planetarium' => - array ( - ), - 'plantation' => - array ( - ), - 'plants' => - array ( - ), - 'plaza' => - array ( - ), - 'portal' => - array ( - ), - 'portland' => - array ( - ), - 'portlligat' => - array ( - ), - 'posts-and-telecommunications' => - array ( - ), - 'preservation' => - array ( - ), - 'presidio' => - array ( - ), - 'press' => - array ( - ), - 'project' => - array ( - ), - 'public' => - array ( - ), - 'pubol' => - array ( - ), - 'quebec' => - array ( - ), - 'railroad' => - array ( - ), - 'railway' => - array ( - ), - 'research' => - array ( - ), - 'resistance' => - array ( - ), - 'riodejaneiro' => - array ( - ), - 'rochester' => - array ( - ), - 'rockart' => - array ( - ), - 'roma' => - array ( - ), - 'russia' => - array ( - ), - 'saintlouis' => - array ( - ), - 'salem' => - array ( - ), - 'salvadordali' => - array ( - ), - 'salzburg' => - array ( - ), - 'sandiego' => - array ( - ), - 'sanfrancisco' => - array ( - ), - 'santabarbara' => - array ( - ), - 'santacruz' => - array ( - ), - 'santafe' => - array ( - ), - 'saskatchewan' => - array ( - ), - 'satx' => - array ( - ), - 'savannahga' => - array ( - ), - 'schlesisches' => - array ( - ), - 'schoenbrunn' => - array ( - ), - 'schokoladen' => - array ( - ), - 'school' => - array ( - ), - 'schweiz' => - array ( - ), - 'science' => - array ( - ), - 'scienceandhistory' => - array ( - ), - 'scienceandindustry' => - array ( - ), - 'sciencecenter' => - array ( - ), - 'sciencecenters' => - array ( - ), - 'science-fiction' => - array ( - ), - 'sciencehistory' => - array ( - ), - 'sciences' => - array ( - ), - 'sciencesnaturelles' => - array ( - ), - 'scotland' => - array ( - ), - 'seaport' => - array ( - ), - 'settlement' => - array ( - ), - 'settlers' => - array ( - ), - 'shell' => - array ( - ), - 'sherbrooke' => - array ( - ), - 'sibenik' => - array ( - ), - 'silk' => - array ( - ), - 'ski' => - array ( - ), - 'skole' => - array ( - ), - 'society' => - array ( - ), - 'sologne' => - array ( - ), - 'soundandvision' => - array ( - ), - 'southcarolina' => - array ( - ), - 'southwest' => - array ( - ), - 'space' => - array ( - ), - 'spy' => - array ( - ), - 'square' => - array ( - ), - 'stadt' => - array ( - ), - 'stalbans' => - array ( - ), - 'starnberg' => - array ( - ), - 'state' => - array ( - ), - 'stateofdelaware' => - array ( - ), - 'station' => - array ( - ), - 'steam' => - array ( - ), - 'steiermark' => - array ( - ), - 'stjohn' => - array ( - ), - 'stockholm' => - array ( - ), - 'stpetersburg' => - array ( - ), - 'stuttgart' => - array ( - ), - 'suisse' => - array ( - ), - 'surgeonshall' => - array ( - ), - 'surrey' => - array ( - ), - 'svizzera' => - array ( - ), - 'sweden' => - array ( - ), - 'sydney' => - array ( - ), - 'tank' => - array ( - ), - 'tcm' => - array ( - ), - 'technology' => - array ( - ), - 'telekommunikation' => - array ( - ), - 'television' => - array ( - ), - 'texas' => - array ( - ), - 'textile' => - array ( - ), - 'theater' => - array ( - ), - 'time' => - array ( - ), - 'timekeeping' => - array ( - ), - 'topology' => - array ( - ), - 'torino' => - array ( - ), - 'touch' => - array ( - ), - 'town' => - array ( - ), - 'transport' => - array ( - ), - 'tree' => - array ( - ), - 'trolley' => - array ( - ), - 'trust' => - array ( - ), - 'trustee' => - array ( - ), - 'uhren' => - array ( - ), - 'ulm' => - array ( - ), - 'undersea' => - array ( - ), - 'university' => - array ( - ), - 'usa' => - array ( - ), - 'usantiques' => - array ( - ), - 'usarts' => - array ( - ), - 'uscountryestate' => - array ( - ), - 'usculture' => - array ( - ), - 'usdecorativearts' => - array ( - ), - 'usgarden' => - array ( - ), - 'ushistory' => - array ( - ), - 'ushuaia' => - array ( - ), - 'uslivinghistory' => - array ( - ), - 'utah' => - array ( - ), - 'uvic' => - array ( - ), - 'valley' => - array ( - ), - 'vantaa' => - array ( - ), - 'versailles' => - array ( - ), - 'viking' => - array ( - ), - 'village' => - array ( - ), - 'virginia' => - array ( - ), - 'virtual' => - array ( - ), - 'virtuel' => - array ( - ), - 'vlaanderen' => - array ( - ), - 'volkenkunde' => - array ( - ), - 'wales' => - array ( - ), - 'wallonie' => - array ( - ), - 'war' => - array ( - ), - 'washingtondc' => - array ( - ), - 'watchandclock' => - array ( - ), - 'watch-and-clock' => - array ( - ), - 'western' => - array ( - ), - 'westfalen' => - array ( - ), - 'whaling' => - array ( - ), - 'wildlife' => - array ( - ), - 'williamsburg' => - array ( - ), - 'windmill' => - array ( - ), - 'workshop' => - array ( - ), - 'york' => - array ( - ), - 'yorkshire' => - array ( - ), - 'yosemite' => - array ( - ), - 'youth' => - array ( - ), - 'zoological' => - array ( - ), - 'zoology' => - array ( - ), - 'xn--9dbhblg6di' => - array ( - ), - 'xn--h1aegh' => - array ( - ), - ), - 'mv' => - array ( - 'aero' => - array ( - ), - 'biz' => - array ( - ), - 'com' => - array ( - ), - 'coop' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'museum' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'pro' => - array ( - ), - ), - 'mw' => - array ( - 'ac' => - array ( - ), - 'biz' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'coop' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'int' => - array ( - ), - 'museum' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'mx' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'gob' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'my' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'mz' => - array ( - '*' => - array ( - ), - 'teledata' => - array ( - '!' => '', - ), - ), - 'na' => - array ( - 'info' => - array ( - ), - 'pro' => - array ( - ), - 'name' => - array ( - ), - 'school' => - array ( - ), - 'or' => - array ( - ), - 'dr' => - array ( - ), - 'us' => - array ( - ), - 'mx' => - array ( - ), - 'ca' => - array ( - ), - 'in' => - array ( - ), - 'cc' => - array ( - ), - 'tv' => - array ( - ), - 'ws' => - array ( - ), - 'mobi' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - ), - 'name' => - array ( - 'her' => - array ( - 'forgot' => - array ( - ), - ), - 'his' => - array ( - 'forgot' => - array ( - ), - ), - ), - 'nc' => - array ( - 'asso' => - array ( - ), - ), - 'ne' => - array ( - ), - 'net' => - array ( - 'cloudfront' => - array ( - ), - 'gb' => - array ( - ), - 'hu' => - array ( - ), - 'jp' => - array ( - ), - 'se' => - array ( - ), - 'uk' => - array ( - ), - 'in' => - array ( - ), - 'cdn77-ssl' => - array ( - ), - 'cdn77' => - array ( - 'r' => - array ( - ), - ), - 'at-band-camp' => - array ( - ), - 'blogdns' => - array ( - ), - 'broke-it' => - array ( - ), - 'buyshouses' => - array ( - ), - 'dnsalias' => - array ( - ), - 'dnsdojo' => - array ( - ), - 'does-it' => - array ( - ), - 'dontexist' => - array ( - ), - 'dynalias' => - array ( - ), - 'dynathome' => - array ( - ), - 'endofinternet' => - array ( - ), - 'from-az' => - array ( - ), - 'from-co' => - array ( - ), - 'from-la' => - array ( - ), - 'from-ny' => - array ( - ), - 'gets-it' => - array ( - ), - 'ham-radio-op' => - array ( - ), - 'homeftp' => - array ( - ), - 'homeip' => - array ( - ), - 'homelinux' => - array ( - ), - 'homeunix' => - array ( - ), - 'in-the-band' => - array ( - ), - 'is-a-chef' => - array ( - ), - 'is-a-geek' => - array ( - ), - 'isa-geek' => - array ( - ), - 'kicks-ass' => - array ( - ), - 'office-on-the' => - array ( - ), - 'podzone' => - array ( - ), - 'scrapper-site' => - array ( - ), - 'selfip' => - array ( - ), - 'sells-it' => - array ( - ), - 'servebbs' => - array ( - ), - 'serveftp' => - array ( - ), - 'thruhere' => - array ( - ), - 'webhop' => - array ( - ), - 'fastly' => - array ( - 'ssl' => - array ( - 'a' => - array ( - ), - 'b' => - array ( - ), - 'global' => - array ( - ), - ), - 'prod' => - array ( - 'a' => - array ( - ), - 'global' => - array ( - ), - ), - ), - 'cloudfunctions' => - array ( - ), - 'azurewebsites' => - array ( - ), - 'azure-mobile' => - array ( - ), - 'cloudapp' => - array ( - ), - 'rackmaze' => - array ( - ), - 'dsmynas' => - array ( - ), - 'familyds' => - array ( - ), - 'za' => - array ( - ), - ), - 'nf' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'per' => - array ( - ), - 'rec' => - array ( - ), - 'web' => - array ( - ), - 'arts' => - array ( - ), - 'firm' => - array ( - ), - 'info' => - array ( - ), - 'other' => - array ( - ), - 'store' => - array ( - ), - ), - 'ng' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'i' => - array ( - ), - 'mil' => - array ( - ), - 'mobi' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sch' => - array ( - ), - ), - 'ni' => - array ( - 'com' => - array ( - ), - 'gob' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'nom' => - array ( - ), - 'net' => - array ( - ), - 'mil' => - array ( - ), - 'co' => - array ( - ), - 'biz' => - array ( - ), - 'web' => - array ( - ), - 'int' => - array ( - ), - 'ac' => - array ( - ), - 'in' => - array ( - ), - 'info' => - array ( - ), - ), - 'nl' => - array ( - 'bv' => - array ( - ), - 'co' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'no' => - array ( - 'fhs' => - array ( - ), - 'vgs' => - array ( - ), - 'fylkesbibl' => - array ( - ), - 'folkebibl' => - array ( - ), - 'museum' => - array ( - ), - 'idrett' => - array ( - ), - 'priv' => - array ( - ), - 'mil' => - array ( - ), - 'stat' => - array ( - ), - 'dep' => - array ( - ), - 'kommune' => - array ( - ), - 'herad' => - array ( - ), - 'aa' => - array ( - 'gs' => - array ( - ), - ), - 'ah' => - array ( - 'gs' => - array ( - ), - ), - 'bu' => - array ( - 'gs' => - array ( - ), - ), - 'fm' => - array ( - 'gs' => - array ( - ), - ), - 'hl' => - array ( - 'gs' => - array ( - ), - ), - 'hm' => - array ( - 'gs' => - array ( - ), - ), - 'jan-mayen' => - array ( - 'gs' => - array ( - ), - ), - 'mr' => - array ( - 'gs' => - array ( - ), - ), - 'nl' => - array ( - 'gs' => - array ( - ), - ), - 'nt' => - array ( - 'gs' => - array ( - ), - ), - 'of' => - array ( - 'gs' => - array ( - ), - ), - 'ol' => - array ( - 'gs' => - array ( - ), - ), - 'oslo' => - array ( - 'gs' => - array ( - ), - ), - 'rl' => - array ( - 'gs' => - array ( - ), - ), - 'sf' => - array ( - 'gs' => - array ( - ), - ), - 'st' => - array ( - 'gs' => - array ( - ), - ), - 'svalbard' => - array ( - 'gs' => - array ( - ), - ), - 'tm' => - array ( - 'gs' => - array ( - ), - ), - 'tr' => - array ( - 'gs' => - array ( - ), - ), - 'va' => - array ( - 'gs' => - array ( - ), - ), - 'vf' => - array ( - 'gs' => - array ( - ), - ), - 'akrehamn' => - array ( - ), - 'xn--krehamn-dxa' => - array ( - ), - 'algard' => - array ( - ), - 'xn--lgrd-poac' => - array ( - ), - 'arna' => - array ( - ), - 'brumunddal' => - array ( - ), - 'bryne' => - array ( - ), - 'bronnoysund' => - array ( - ), - 'xn--brnnysund-m8ac' => - array ( - ), - 'drobak' => - array ( - ), - 'xn--drbak-wua' => - array ( - ), - 'egersund' => - array ( - ), - 'fetsund' => - array ( - ), - 'floro' => - array ( - ), - 'xn--flor-jra' => - array ( - ), - 'fredrikstad' => - array ( - ), - 'hokksund' => - array ( - ), - 'honefoss' => - array ( - ), - 'xn--hnefoss-q1a' => - array ( - ), - 'jessheim' => - array ( - ), - 'jorpeland' => - array ( - ), - 'xn--jrpeland-54a' => - array ( - ), - 'kirkenes' => - array ( - ), - 'kopervik' => - array ( - ), - 'krokstadelva' => - array ( - ), - 'langevag' => - array ( - ), - 'xn--langevg-jxa' => - array ( - ), - 'leirvik' => - array ( - ), - 'mjondalen' => - array ( - ), - 'xn--mjndalen-64a' => - array ( - ), - 'mo-i-rana' => - array ( - ), - 'mosjoen' => - array ( - ), - 'xn--mosjen-eya' => - array ( - ), - 'nesoddtangen' => - array ( - ), - 'orkanger' => - array ( - ), - 'osoyro' => - array ( - ), - 'xn--osyro-wua' => - array ( - ), - 'raholt' => - array ( - ), - 'xn--rholt-mra' => - array ( - ), - 'sandnessjoen' => - array ( - ), - 'xn--sandnessjen-ogb' => - array ( - ), - 'skedsmokorset' => - array ( - ), - 'slattum' => - array ( - ), - 'spjelkavik' => - array ( - ), - 'stathelle' => - array ( - ), - 'stavern' => - array ( - ), - 'stjordalshalsen' => - array ( - ), - 'xn--stjrdalshalsen-sqb' => - array ( - ), - 'tananger' => - array ( - ), - 'tranby' => - array ( - ), - 'vossevangen' => - array ( - ), - 'afjord' => - array ( - ), - 'xn--fjord-lra' => - array ( - ), - 'agdenes' => - array ( - ), - 'al' => - array ( - ), - 'xn--l-1fa' => - array ( - ), - 'alesund' => - array ( - ), - 'xn--lesund-hua' => - array ( - ), - 'alstahaug' => - array ( - ), - 'alta' => - array ( - ), - 'xn--lt-liac' => - array ( - ), - 'alaheadju' => - array ( - ), - 'xn--laheadju-7ya' => - array ( - ), - 'alvdal' => - array ( - ), - 'amli' => - array ( - ), - 'xn--mli-tla' => - array ( - ), - 'amot' => - array ( - ), - 'xn--mot-tla' => - array ( - ), - 'andebu' => - array ( - ), - 'andoy' => - array ( - ), - 'xn--andy-ira' => - array ( - ), - 'andasuolo' => - array ( - ), - 'ardal' => - array ( - ), - 'xn--rdal-poa' => - array ( - ), - 'aremark' => - array ( - ), - 'arendal' => - array ( - ), - 'xn--s-1fa' => - array ( - ), - 'aseral' => - array ( - ), - 'xn--seral-lra' => - array ( - ), - 'asker' => - array ( - ), - 'askim' => - array ( - ), - 'askvoll' => - array ( - ), - 'askoy' => - array ( - ), - 'xn--asky-ira' => - array ( - ), - 'asnes' => - array ( - ), - 'xn--snes-poa' => - array ( - ), - 'audnedaln' => - array ( - ), - 'aukra' => - array ( - ), - 'aure' => - array ( - ), - 'aurland' => - array ( - ), - 'aurskog-holand' => - array ( - ), - 'xn--aurskog-hland-jnb' => - array ( - ), - 'austevoll' => - array ( - ), - 'austrheim' => - array ( - ), - 'averoy' => - array ( - ), - 'xn--avery-yua' => - array ( - ), - 'balestrand' => - array ( - ), - 'ballangen' => - array ( - ), - 'balat' => - array ( - ), - 'xn--blt-elab' => - array ( - ), - 'balsfjord' => - array ( - ), - 'bahccavuotna' => - array ( - ), - 'xn--bhccavuotna-k7a' => - array ( - ), - 'bamble' => - array ( - ), - 'bardu' => - array ( - ), - 'beardu' => - array ( - ), - 'beiarn' => - array ( - ), - 'bajddar' => - array ( - ), - 'xn--bjddar-pta' => - array ( - ), - 'baidar' => - array ( - ), - 'xn--bidr-5nac' => - array ( - ), - 'berg' => - array ( - ), - 'bergen' => - array ( - ), - 'berlevag' => - array ( - ), - 'xn--berlevg-jxa' => - array ( - ), - 'bearalvahki' => - array ( - ), - 'xn--bearalvhki-y4a' => - array ( - ), - 'bindal' => - array ( - ), - 'birkenes' => - array ( - ), - 'bjarkoy' => - array ( - ), - 'xn--bjarky-fya' => - array ( - ), - 'bjerkreim' => - array ( - ), - 'bjugn' => - array ( - ), - 'bodo' => - array ( - ), - 'xn--bod-2na' => - array ( - ), - 'badaddja' => - array ( - ), - 'xn--bdddj-mrabd' => - array ( - ), - 'budejju' => - array ( - ), - 'bokn' => - array ( - ), - 'bremanger' => - array ( - ), - 'bronnoy' => - array ( - ), - 'xn--brnny-wuac' => - array ( - ), - 'bygland' => - array ( - ), - 'bykle' => - array ( - ), - 'barum' => - array ( - ), - 'xn--brum-voa' => - array ( - ), - 'telemark' => - array ( - 'bo' => - array ( - ), - 'xn--b-5ga' => - array ( - ), - ), - 'nordland' => - array ( - 'bo' => - array ( - ), - 'xn--b-5ga' => - array ( - ), - 'heroy' => - array ( - ), - 'xn--hery-ira' => - array ( - ), - ), - 'bievat' => - array ( - ), - 'xn--bievt-0qa' => - array ( - ), - 'bomlo' => - array ( - ), - 'xn--bmlo-gra' => - array ( - ), - 'batsfjord' => - array ( - ), - 'xn--btsfjord-9za' => - array ( - ), - 'bahcavuotna' => - array ( - ), - 'xn--bhcavuotna-s4a' => - array ( - ), - 'dovre' => - array ( - ), - 'drammen' => - array ( - ), - 'drangedal' => - array ( - ), - 'dyroy' => - array ( - ), - 'xn--dyry-ira' => - array ( - ), - 'donna' => - array ( - ), - 'xn--dnna-gra' => - array ( - ), - 'eid' => - array ( - ), - 'eidfjord' => - array ( - ), - 'eidsberg' => - array ( - ), - 'eidskog' => - array ( - ), - 'eidsvoll' => - array ( - ), - 'eigersund' => - array ( - ), - 'elverum' => - array ( - ), - 'enebakk' => - array ( - ), - 'engerdal' => - array ( - ), - 'etne' => - array ( - ), - 'etnedal' => - array ( - ), - 'evenes' => - array ( - ), - 'evenassi' => - array ( - ), - 'xn--eveni-0qa01ga' => - array ( - ), - 'evje-og-hornnes' => - array ( - ), - 'farsund' => - array ( - ), - 'fauske' => - array ( - ), - 'fuossko' => - array ( - ), - 'fuoisku' => - array ( - ), - 'fedje' => - array ( - ), - 'fet' => - array ( - ), - 'finnoy' => - array ( - ), - 'xn--finny-yua' => - array ( - ), - 'fitjar' => - array ( - ), - 'fjaler' => - array ( - ), - 'fjell' => - array ( - ), - 'flakstad' => - array ( - ), - 'flatanger' => - array ( - ), - 'flekkefjord' => - array ( - ), - 'flesberg' => - array ( - ), - 'flora' => - array ( - ), - 'fla' => - array ( - ), - 'xn--fl-zia' => - array ( - ), - 'folldal' => - array ( - ), - 'forsand' => - array ( - ), - 'fosnes' => - array ( - ), - 'frei' => - array ( - ), - 'frogn' => - array ( - ), - 'froland' => - array ( - ), - 'frosta' => - array ( - ), - 'frana' => - array ( - ), - 'xn--frna-woa' => - array ( - ), - 'froya' => - array ( - ), - 'xn--frya-hra' => - array ( - ), - 'fusa' => - array ( - ), - 'fyresdal' => - array ( - ), - 'forde' => - array ( - ), - 'xn--frde-gra' => - array ( - ), - 'gamvik' => - array ( - ), - 'gangaviika' => - array ( - ), - 'xn--ggaviika-8ya47h' => - array ( - ), - 'gaular' => - array ( - ), - 'gausdal' => - array ( - ), - 'gildeskal' => - array ( - ), - 'xn--gildeskl-g0a' => - array ( - ), - 'giske' => - array ( - ), - 'gjemnes' => - array ( - ), - 'gjerdrum' => - array ( - ), - 'gjerstad' => - array ( - ), - 'gjesdal' => - array ( - ), - 'gjovik' => - array ( - ), - 'xn--gjvik-wua' => - array ( - ), - 'gloppen' => - array ( - ), - 'gol' => - array ( - ), - 'gran' => - array ( - ), - 'grane' => - array ( - ), - 'granvin' => - array ( - ), - 'gratangen' => - array ( - ), - 'grimstad' => - array ( - ), - 'grong' => - array ( - ), - 'kraanghke' => - array ( - ), - 'xn--kranghke-b0a' => - array ( - ), - 'grue' => - array ( - ), - 'gulen' => - array ( - ), - 'hadsel' => - array ( - ), - 'halden' => - array ( - ), - 'halsa' => - array ( - ), - 'hamar' => - array ( - ), - 'hamaroy' => - array ( - ), - 'habmer' => - array ( - ), - 'xn--hbmer-xqa' => - array ( - ), - 'hapmir' => - array ( - ), - 'xn--hpmir-xqa' => - array ( - ), - 'hammerfest' => - array ( - ), - 'hammarfeasta' => - array ( - ), - 'xn--hmmrfeasta-s4ac' => - array ( - ), - 'haram' => - array ( - ), - 'hareid' => - array ( - ), - 'harstad' => - array ( - ), - 'hasvik' => - array ( - ), - 'aknoluokta' => - array ( - ), - 'xn--koluokta-7ya57h' => - array ( - ), - 'hattfjelldal' => - array ( - ), - 'aarborte' => - array ( - ), - 'haugesund' => - array ( - ), - 'hemne' => - array ( - ), - 'hemnes' => - array ( - ), - 'hemsedal' => - array ( - ), - 'more-og-romsdal' => - array ( - 'heroy' => - array ( - ), - 'sande' => - array ( - ), - ), - 'xn--mre-og-romsdal-qqb' => - array ( - 'xn--hery-ira' => - array ( - ), - 'sande' => - array ( - ), - ), - 'hitra' => - array ( - ), - 'hjartdal' => - array ( - ), - 'hjelmeland' => - array ( - ), - 'hobol' => - array ( - ), - 'xn--hobl-ira' => - array ( - ), - 'hof' => - array ( - ), - 'hol' => - array ( - ), - 'hole' => - array ( - ), - 'holmestrand' => - array ( - ), - 'holtalen' => - array ( - ), - 'xn--holtlen-hxa' => - array ( - ), - 'hornindal' => - array ( - ), - 'horten' => - array ( - ), - 'hurdal' => - array ( - ), - 'hurum' => - array ( - ), - 'hvaler' => - array ( - ), - 'hyllestad' => - array ( - ), - 'hagebostad' => - array ( - ), - 'xn--hgebostad-g3a' => - array ( - ), - 'hoyanger' => - array ( - ), - 'xn--hyanger-q1a' => - array ( - ), - 'hoylandet' => - array ( - ), - 'xn--hylandet-54a' => - array ( - ), - 'ha' => - array ( - ), - 'xn--h-2fa' => - array ( - ), - 'ibestad' => - array ( - ), - 'inderoy' => - array ( - ), - 'xn--indery-fya' => - array ( - ), - 'iveland' => - array ( - ), - 'jevnaker' => - array ( - ), - 'jondal' => - array ( - ), - 'jolster' => - array ( - ), - 'xn--jlster-bya' => - array ( - ), - 'karasjok' => - array ( - ), - 'karasjohka' => - array ( - ), - 'xn--krjohka-hwab49j' => - array ( - ), - 'karlsoy' => - array ( - ), - 'galsa' => - array ( - ), - 'xn--gls-elac' => - array ( - ), - 'karmoy' => - array ( - ), - 'xn--karmy-yua' => - array ( - ), - 'kautokeino' => - array ( - ), - 'guovdageaidnu' => - array ( - ), - 'klepp' => - array ( - ), - 'klabu' => - array ( - ), - 'xn--klbu-woa' => - array ( - ), - 'kongsberg' => - array ( - ), - 'kongsvinger' => - array ( - ), - 'kragero' => - array ( - ), - 'xn--krager-gya' => - array ( - ), - 'kristiansand' => - array ( - ), - 'kristiansund' => - array ( - ), - 'krodsherad' => - array ( - ), - 'xn--krdsherad-m8a' => - array ( - ), - 'kvalsund' => - array ( - ), - 'rahkkeravju' => - array ( - ), - 'xn--rhkkervju-01af' => - array ( - ), - 'kvam' => - array ( - ), - 'kvinesdal' => - array ( - ), - 'kvinnherad' => - array ( - ), - 'kviteseid' => - array ( - ), - 'kvitsoy' => - array ( - ), - 'xn--kvitsy-fya' => - array ( - ), - 'kvafjord' => - array ( - ), - 'xn--kvfjord-nxa' => - array ( - ), - 'giehtavuoatna' => - array ( - ), - 'kvanangen' => - array ( - ), - 'xn--kvnangen-k0a' => - array ( - ), - 'navuotna' => - array ( - ), - 'xn--nvuotna-hwa' => - array ( - ), - 'kafjord' => - array ( - ), - 'xn--kfjord-iua' => - array ( - ), - 'gaivuotna' => - array ( - ), - 'xn--givuotna-8ya' => - array ( - ), - 'larvik' => - array ( - ), - 'lavangen' => - array ( - ), - 'lavagis' => - array ( - ), - 'loabat' => - array ( - ), - 'xn--loabt-0qa' => - array ( - ), - 'lebesby' => - array ( - ), - 'davvesiida' => - array ( - ), - 'leikanger' => - array ( - ), - 'leirfjord' => - array ( - ), - 'leka' => - array ( - ), - 'leksvik' => - array ( - ), - 'lenvik' => - array ( - ), - 'leangaviika' => - array ( - ), - 'xn--leagaviika-52b' => - array ( - ), - 'lesja' => - array ( - ), - 'levanger' => - array ( - ), - 'lier' => - array ( - ), - 'lierne' => - array ( - ), - 'lillehammer' => - array ( - ), - 'lillesand' => - array ( - ), - 'lindesnes' => - array ( - ), - 'lindas' => - array ( - ), - 'xn--linds-pra' => - array ( - ), - 'lom' => - array ( - ), - 'loppa' => - array ( - ), - 'lahppi' => - array ( - ), - 'xn--lhppi-xqa' => - array ( - ), - 'lund' => - array ( - ), - 'lunner' => - array ( - ), - 'luroy' => - array ( - ), - 'xn--lury-ira' => - array ( - ), - 'luster' => - array ( - ), - 'lyngdal' => - array ( - ), - 'lyngen' => - array ( - ), - 'ivgu' => - array ( - ), - 'lardal' => - array ( - ), - 'lerdal' => - array ( - ), - 'xn--lrdal-sra' => - array ( - ), - 'lodingen' => - array ( - ), - 'xn--ldingen-q1a' => - array ( - ), - 'lorenskog' => - array ( - ), - 'xn--lrenskog-54a' => - array ( - ), - 'loten' => - array ( - ), - 'xn--lten-gra' => - array ( - ), - 'malvik' => - array ( - ), - 'masoy' => - array ( - ), - 'xn--msy-ula0h' => - array ( - ), - 'muosat' => - array ( - ), - 'xn--muost-0qa' => - array ( - ), - 'mandal' => - array ( - ), - 'marker' => - array ( - ), - 'marnardal' => - array ( - ), - 'masfjorden' => - array ( - ), - 'meland' => - array ( - ), - 'meldal' => - array ( - ), - 'melhus' => - array ( - ), - 'meloy' => - array ( - ), - 'xn--mely-ira' => - array ( - ), - 'meraker' => - array ( - ), - 'xn--merker-kua' => - array ( - ), - 'moareke' => - array ( - ), - 'xn--moreke-jua' => - array ( - ), - 'midsund' => - array ( - ), - 'midtre-gauldal' => - array ( - ), - 'modalen' => - array ( - ), - 'modum' => - array ( - ), - 'molde' => - array ( - ), - 'moskenes' => - array ( - ), - 'moss' => - array ( - ), - 'mosvik' => - array ( - ), - 'malselv' => - array ( - ), - 'xn--mlselv-iua' => - array ( - ), - 'malatvuopmi' => - array ( - ), - 'xn--mlatvuopmi-s4a' => - array ( - ), - 'namdalseid' => - array ( - ), - 'aejrie' => - array ( - ), - 'namsos' => - array ( - ), - 'namsskogan' => - array ( - ), - 'naamesjevuemie' => - array ( - ), - 'xn--nmesjevuemie-tcba' => - array ( - ), - 'laakesvuemie' => - array ( - ), - 'nannestad' => - array ( - ), - 'narvik' => - array ( - ), - 'narviika' => - array ( - ), - 'naustdal' => - array ( - ), - 'nedre-eiker' => - array ( - ), - 'akershus' => - array ( - 'nes' => - array ( - ), - ), - 'buskerud' => - array ( - 'nes' => - array ( - ), - ), - 'nesna' => - array ( - ), - 'nesodden' => - array ( - ), - 'nesseby' => - array ( - ), - 'unjarga' => - array ( - ), - 'xn--unjrga-rta' => - array ( - ), - 'nesset' => - array ( - ), - 'nissedal' => - array ( - ), - 'nittedal' => - array ( - ), - 'nord-aurdal' => - array ( - ), - 'nord-fron' => - array ( - ), - 'nord-odal' => - array ( - ), - 'norddal' => - array ( - ), - 'nordkapp' => - array ( - ), - 'davvenjarga' => - array ( - ), - 'xn--davvenjrga-y4a' => - array ( - ), - 'nordre-land' => - array ( - ), - 'nordreisa' => - array ( - ), - 'raisa' => - array ( - ), - 'xn--risa-5na' => - array ( - ), - 'nore-og-uvdal' => - array ( - ), - 'notodden' => - array ( - ), - 'naroy' => - array ( - ), - 'xn--nry-yla5g' => - array ( - ), - 'notteroy' => - array ( - ), - 'xn--nttery-byae' => - array ( - ), - 'odda' => - array ( - ), - 'oksnes' => - array ( - ), - 'xn--ksnes-uua' => - array ( - ), - 'oppdal' => - array ( - ), - 'oppegard' => - array ( - ), - 'xn--oppegrd-ixa' => - array ( - ), - 'orkdal' => - array ( - ), - 'orland' => - array ( - ), - 'xn--rland-uua' => - array ( - ), - 'orskog' => - array ( - ), - 'xn--rskog-uua' => - array ( - ), - 'orsta' => - array ( - ), - 'xn--rsta-fra' => - array ( - ), - 'hedmark' => - array ( - 'os' => - array ( - ), - 'valer' => - array ( - ), - 'xn--vler-qoa' => - array ( - ), - ), - 'hordaland' => - array ( - 'os' => - array ( - ), - ), - 'osen' => - array ( - ), - 'osteroy' => - array ( - ), - 'xn--ostery-fya' => - array ( - ), - 'ostre-toten' => - array ( - ), - 'xn--stre-toten-zcb' => - array ( - ), - 'overhalla' => - array ( - ), - 'ovre-eiker' => - array ( - ), - 'xn--vre-eiker-k8a' => - array ( - ), - 'oyer' => - array ( - ), - 'xn--yer-zna' => - array ( - ), - 'oygarden' => - array ( - ), - 'xn--ygarden-p1a' => - array ( - ), - 'oystre-slidre' => - array ( - ), - 'xn--ystre-slidre-ujb' => - array ( - ), - 'porsanger' => - array ( - ), - 'porsangu' => - array ( - ), - 'xn--porsgu-sta26f' => - array ( - ), - 'porsgrunn' => - array ( - ), - 'radoy' => - array ( - ), - 'xn--rady-ira' => - array ( - ), - 'rakkestad' => - array ( - ), - 'rana' => - array ( - ), - 'ruovat' => - array ( - ), - 'randaberg' => - array ( - ), - 'rauma' => - array ( - ), - 'rendalen' => - array ( - ), - 'rennebu' => - array ( - ), - 'rennesoy' => - array ( - ), - 'xn--rennesy-v1a' => - array ( - ), - 'rindal' => - array ( - ), - 'ringebu' => - array ( - ), - 'ringerike' => - array ( - ), - 'ringsaker' => - array ( - ), - 'rissa' => - array ( - ), - 'risor' => - array ( - ), - 'xn--risr-ira' => - array ( - ), - 'roan' => - array ( - ), - 'rollag' => - array ( - ), - 'rygge' => - array ( - ), - 'ralingen' => - array ( - ), - 'xn--rlingen-mxa' => - array ( - ), - 'rodoy' => - array ( - ), - 'xn--rdy-0nab' => - array ( - ), - 'romskog' => - array ( - ), - 'xn--rmskog-bya' => - array ( - ), - 'roros' => - array ( - ), - 'xn--rros-gra' => - array ( - ), - 'rost' => - array ( - ), - 'xn--rst-0na' => - array ( - ), - 'royken' => - array ( - ), - 'xn--ryken-vua' => - array ( - ), - 'royrvik' => - array ( - ), - 'xn--ryrvik-bya' => - array ( - ), - 'rade' => - array ( - ), - 'xn--rde-ula' => - array ( - ), - 'salangen' => - array ( - ), - 'siellak' => - array ( - ), - 'saltdal' => - array ( - ), - 'salat' => - array ( - ), - 'xn--slt-elab' => - array ( - ), - 'xn--slat-5na' => - array ( - ), - 'samnanger' => - array ( - ), - 'vestfold' => - array ( - 'sande' => - array ( - ), - ), - 'sandefjord' => - array ( - ), - 'sandnes' => - array ( - ), - 'sandoy' => - array ( - ), - 'xn--sandy-yua' => - array ( - ), - 'sarpsborg' => - array ( - ), - 'sauda' => - array ( - ), - 'sauherad' => - array ( - ), - 'sel' => - array ( - ), - 'selbu' => - array ( - ), - 'selje' => - array ( - ), - 'seljord' => - array ( - ), - 'sigdal' => - array ( - ), - 'siljan' => - array ( - ), - 'sirdal' => - array ( - ), - 'skaun' => - array ( - ), - 'skedsmo' => - array ( - ), - 'ski' => - array ( - ), - 'skien' => - array ( - ), - 'skiptvet' => - array ( - ), - 'skjervoy' => - array ( - ), - 'xn--skjervy-v1a' => - array ( - ), - 'skierva' => - array ( - ), - 'xn--skierv-uta' => - array ( - ), - 'skjak' => - array ( - ), - 'xn--skjk-soa' => - array ( - ), - 'skodje' => - array ( - ), - 'skanland' => - array ( - ), - 'xn--sknland-fxa' => - array ( - ), - 'skanit' => - array ( - ), - 'xn--sknit-yqa' => - array ( - ), - 'smola' => - array ( - ), - 'xn--smla-hra' => - array ( - ), - 'snillfjord' => - array ( - ), - 'snasa' => - array ( - ), - 'xn--snsa-roa' => - array ( - ), - 'snoasa' => - array ( - ), - 'snaase' => - array ( - ), - 'xn--snase-nra' => - array ( - ), - 'sogndal' => - array ( - ), - 'sokndal' => - array ( - ), - 'sola' => - array ( - ), - 'solund' => - array ( - ), - 'songdalen' => - array ( - ), - 'sortland' => - array ( - ), - 'spydeberg' => - array ( - ), - 'stange' => - array ( - ), - 'stavanger' => - array ( - ), - 'steigen' => - array ( - ), - 'steinkjer' => - array ( - ), - 'stjordal' => - array ( - ), - 'xn--stjrdal-s1a' => - array ( - ), - 'stokke' => - array ( - ), - 'stor-elvdal' => - array ( - ), - 'stord' => - array ( - ), - 'stordal' => - array ( - ), - 'storfjord' => - array ( - ), - 'omasvuotna' => - array ( - ), - 'strand' => - array ( - ), - 'stranda' => - array ( - ), - 'stryn' => - array ( - ), - 'sula' => - array ( - ), - 'suldal' => - array ( - ), - 'sund' => - array ( - ), - 'sunndal' => - array ( - ), - 'surnadal' => - array ( - ), - 'sveio' => - array ( - ), - 'svelvik' => - array ( - ), - 'sykkylven' => - array ( - ), - 'sogne' => - array ( - ), - 'xn--sgne-gra' => - array ( - ), - 'somna' => - array ( - ), - 'xn--smna-gra' => - array ( - ), - 'sondre-land' => - array ( - ), - 'xn--sndre-land-0cb' => - array ( - ), - 'sor-aurdal' => - array ( - ), - 'xn--sr-aurdal-l8a' => - array ( - ), - 'sor-fron' => - array ( - ), - 'xn--sr-fron-q1a' => - array ( - ), - 'sor-odal' => - array ( - ), - 'xn--sr-odal-q1a' => - array ( - ), - 'sor-varanger' => - array ( - ), - 'xn--sr-varanger-ggb' => - array ( - ), - 'matta-varjjat' => - array ( - ), - 'xn--mtta-vrjjat-k7af' => - array ( - ), - 'sorfold' => - array ( - ), - 'xn--srfold-bya' => - array ( - ), - 'sorreisa' => - array ( - ), - 'xn--srreisa-q1a' => - array ( - ), - 'sorum' => - array ( - ), - 'xn--srum-gra' => - array ( - ), - 'tana' => - array ( - ), - 'deatnu' => - array ( - ), - 'time' => - array ( - ), - 'tingvoll' => - array ( - ), - 'tinn' => - array ( - ), - 'tjeldsund' => - array ( - ), - 'dielddanuorri' => - array ( - ), - 'tjome' => - array ( - ), - 'xn--tjme-hra' => - array ( - ), - 'tokke' => - array ( - ), - 'tolga' => - array ( - ), - 'torsken' => - array ( - ), - 'tranoy' => - array ( - ), - 'xn--trany-yua' => - array ( - ), - 'tromso' => - array ( - ), - 'xn--troms-zua' => - array ( - ), - 'tromsa' => - array ( - ), - 'romsa' => - array ( - ), - 'trondheim' => - array ( - ), - 'troandin' => - array ( - ), - 'trysil' => - array ( - ), - 'trana' => - array ( - ), - 'xn--trna-woa' => - array ( - ), - 'trogstad' => - array ( - ), - 'xn--trgstad-r1a' => - array ( - ), - 'tvedestrand' => - array ( - ), - 'tydal' => - array ( - ), - 'tynset' => - array ( - ), - 'tysfjord' => - array ( - ), - 'divtasvuodna' => - array ( - ), - 'divttasvuotna' => - array ( - ), - 'tysnes' => - array ( - ), - 'tysvar' => - array ( - ), - 'xn--tysvr-vra' => - array ( - ), - 'tonsberg' => - array ( - ), - 'xn--tnsberg-q1a' => - array ( - ), - 'ullensaker' => - array ( - ), - 'ullensvang' => - array ( - ), - 'ulvik' => - array ( - ), - 'utsira' => - array ( - ), - 'vadso' => - array ( - ), - 'xn--vads-jra' => - array ( - ), - 'cahcesuolo' => - array ( - ), - 'xn--hcesuolo-7ya35b' => - array ( - ), - 'vaksdal' => - array ( - ), - 'valle' => - array ( - ), - 'vang' => - array ( - ), - 'vanylven' => - array ( - ), - 'vardo' => - array ( - ), - 'xn--vard-jra' => - array ( - ), - 'varggat' => - array ( - ), - 'xn--vrggt-xqad' => - array ( - ), - 'vefsn' => - array ( - ), - 'vaapste' => - array ( - ), - 'vega' => - array ( - ), - 'vegarshei' => - array ( - ), - 'xn--vegrshei-c0a' => - array ( - ), - 'vennesla' => - array ( - ), - 'verdal' => - array ( - ), - 'verran' => - array ( - ), - 'vestby' => - array ( - ), - 'vestnes' => - array ( - ), - 'vestre-slidre' => - array ( - ), - 'vestre-toten' => - array ( - ), - 'vestvagoy' => - array ( - ), - 'xn--vestvgy-ixa6o' => - array ( - ), - 'vevelstad' => - array ( - ), - 'vik' => - array ( - ), - 'vikna' => - array ( - ), - 'vindafjord' => - array ( - ), - 'volda' => - array ( - ), - 'voss' => - array ( - ), - 'varoy' => - array ( - ), - 'xn--vry-yla5g' => - array ( - ), - 'vagan' => - array ( - ), - 'xn--vgan-qoa' => - array ( - ), - 'voagat' => - array ( - ), - 'vagsoy' => - array ( - ), - 'xn--vgsy-qoa0j' => - array ( - ), - 'vaga' => - array ( - ), - 'xn--vg-yiab' => - array ( - ), - 'ostfold' => - array ( - 'valer' => - array ( - ), - ), - 'xn--stfold-9xa' => - array ( - 'xn--vler-qoa' => - array ( - ), - ), - 'co' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'np' => - array ( - '*' => - array ( - ), - ), - 'nr' => - array ( - 'biz' => - array ( - ), - 'info' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'com' => - array ( - ), - ), - 'nu' => - array ( - 'merseine' => - array ( - ), - 'mine' => - array ( - ), - 'shacknet' => - array ( - ), - ), - 'nz' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'cri' => - array ( - ), - 'geek' => - array ( - ), - 'gen' => - array ( - ), - 'govt' => - array ( - ), - 'health' => - array ( - ), - 'iwi' => - array ( - ), - 'kiwi' => - array ( - ), - 'maori' => - array ( - ), - 'mil' => - array ( - ), - 'xn--mori-qsa' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'parliament' => - array ( - ), - 'school' => - array ( - ), - ), - 'om' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'med' => - array ( - ), - 'museum' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'pro' => - array ( - ), - ), - 'org' => - array ( - 'ae' => - array ( - ), - 'us' => - array ( - ), - 'cdn77' => - array ( - 'c' => - array ( - ), - 'rsc' => - array ( - ), - ), - 'cdn77-secure' => - array ( - 'origin' => - array ( - 'ssl' => - array ( - ), - ), - ), - 'duckdns' => - array ( - ), - 'dyndns' => - array ( - 'go' => - array ( - ), - 'home' => - array ( - ), - ), - 'blogdns' => - array ( - ), - 'blogsite' => - array ( - ), - 'boldlygoingnowhere' => - array ( - ), - 'dnsalias' => - array ( - ), - 'dnsdojo' => - array ( - ), - 'doesntexist' => - array ( - ), - 'dontexist' => - array ( - ), - 'doomdns' => - array ( - ), - 'dvrdns' => - array ( - ), - 'dynalias' => - array ( - ), - 'endofinternet' => - array ( - ), - 'endoftheinternet' => - array ( - ), - 'from-me' => - array ( - ), - 'game-host' => - array ( - ), - 'gotdns' => - array ( - ), - 'hobby-site' => - array ( - ), - 'homedns' => - array ( - ), - 'homeftp' => - array ( - ), - 'homelinux' => - array ( - ), - 'homeunix' => - array ( - ), - 'is-a-bruinsfan' => - array ( - ), - 'is-a-candidate' => - array ( - ), - 'is-a-celticsfan' => - array ( - ), - 'is-a-chef' => - array ( - ), - 'is-a-geek' => - array ( - ), - 'is-a-knight' => - array ( - ), - 'is-a-linux-user' => - array ( - ), - 'is-a-patsfan' => - array ( - ), - 'is-a-soxfan' => - array ( - ), - 'is-found' => - array ( - ), - 'is-lost' => - array ( - ), - 'is-saved' => - array ( - ), - 'is-very-bad' => - array ( - ), - 'is-very-evil' => - array ( - ), - 'is-very-good' => - array ( - ), - 'is-very-nice' => - array ( - ), - 'is-very-sweet' => - array ( - ), - 'isa-geek' => - array ( - ), - 'kicks-ass' => - array ( - ), - 'misconfused' => - array ( - ), - 'podzone' => - array ( - ), - 'readmyblog' => - array ( - ), - 'selfip' => - array ( - ), - 'sellsyourhome' => - array ( - ), - 'servebbs' => - array ( - ), - 'serveftp' => - array ( - ), - 'servegame' => - array ( - ), - 'stuff-4-sale' => - array ( - ), - 'webhop' => - array ( - ), - 'eu' => - array ( - 'al' => - array ( - ), - 'asso' => - array ( - ), - 'at' => - array ( - ), - 'au' => - array ( - ), - 'be' => - array ( - ), - 'bg' => - array ( - ), - 'ca' => - array ( - ), - 'cd' => - array ( - ), - 'ch' => - array ( - ), - 'cn' => - array ( - ), - 'cy' => - array ( - ), - 'cz' => - array ( - ), - 'de' => - array ( - ), - 'dk' => - array ( - ), - 'edu' => - array ( - ), - 'ee' => - array ( - ), - 'es' => - array ( - ), - 'fi' => - array ( - ), - 'fr' => - array ( - ), - 'gr' => - array ( - ), - 'hr' => - array ( - ), - 'hu' => - array ( - ), - 'ie' => - array ( - ), - 'il' => - array ( - ), - 'in' => - array ( - ), - 'int' => - array ( - ), - 'is' => - array ( - ), - 'it' => - array ( - ), - 'jp' => - array ( - ), - 'kr' => - array ( - ), - 'lt' => - array ( - ), - 'lu' => - array ( - ), - 'lv' => - array ( - ), - 'mc' => - array ( - ), - 'me' => - array ( - ), - 'mk' => - array ( - ), - 'mt' => - array ( - ), - 'my' => - array ( - ), - 'net' => - array ( - ), - 'ng' => - array ( - ), - 'nl' => - array ( - ), - 'no' => - array ( - ), - 'nz' => - array ( - ), - 'paris' => - array ( - ), - 'pl' => - array ( - ), - 'pt' => - array ( - ), - 'q-a' => - array ( - ), - 'ro' => - array ( - ), - 'ru' => - array ( - ), - 'se' => - array ( - ), - 'si' => - array ( - ), - 'sk' => - array ( - ), - 'tr' => - array ( - ), - 'uk' => - array ( - ), - 'us' => - array ( - ), - ), - 'bmoattachments' => - array ( - ), - 'dsmynas' => - array ( - ), - 'familyds' => - array ( - ), - 'hk' => - array ( - ), - 'za' => - array ( - ), - ), - 'pa' => - array ( - 'ac' => - array ( - ), - 'gob' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'sld' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'ing' => - array ( - ), - 'abo' => - array ( - ), - 'med' => - array ( - ), - 'nom' => - array ( - ), - ), - 'pe' => - array ( - 'edu' => - array ( - ), - 'gob' => - array ( - ), - 'nom' => - array ( - ), - 'mil' => - array ( - ), - 'org' => - array ( - ), - 'com' => - array ( - ), - 'net' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'pf' => - array ( - 'com' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - ), - 'pg' => - array ( - '*' => - array ( - ), - ), - 'ph' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'ngo' => - array ( - ), - 'mil' => - array ( - ), - 'i' => - array ( - ), - ), - 'pk' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'org' => - array ( - ), - 'fam' => - array ( - ), - 'biz' => - array ( - ), - 'web' => - array ( - ), - 'gov' => - array ( - ), - 'gob' => - array ( - ), - 'gok' => - array ( - ), - 'gon' => - array ( - ), - 'gop' => - array ( - ), - 'gos' => - array ( - ), - 'info' => - array ( - ), - ), - 'pl' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'aid' => - array ( - ), - 'agro' => - array ( - ), - 'atm' => - array ( - ), - 'auto' => - array ( - ), - 'biz' => - array ( - ), - 'edu' => - array ( - ), - 'gmina' => - array ( - ), - 'gsm' => - array ( - ), - 'info' => - array ( - ), - 'mail' => - array ( - ), - 'miasta' => - array ( - ), - 'media' => - array ( - ), - 'mil' => - array ( - ), - 'nieruchomosci' => - array ( - ), - 'nom' => - array ( - ), - 'pc' => - array ( - ), - 'powiat' => - array ( - ), - 'priv' => - array ( - ), - 'realestate' => - array ( - ), - 'rel' => - array ( - ), - 'sex' => - array ( - ), - 'shop' => - array ( - ), - 'sklep' => - array ( - ), - 'sos' => - array ( - ), - 'szkola' => - array ( - ), - 'targi' => - array ( - ), - 'tm' => - array ( - ), - 'tourism' => - array ( - ), - 'travel' => - array ( - ), - 'turystyka' => - array ( - ), - 'gov' => - array ( - 'ap' => - array ( - ), - 'ic' => - array ( - ), - 'is' => - array ( - ), - 'us' => - array ( - ), - 'kmpsp' => - array ( - ), - 'kppsp' => - array ( - ), - 'kwpsp' => - array ( - ), - 'psp' => - array ( - ), - 'wskr' => - array ( - ), - 'kwp' => - array ( - ), - 'mw' => - array ( - ), - 'ug' => - array ( - ), - 'um' => - array ( - ), - 'umig' => - array ( - ), - 'ugim' => - array ( - ), - 'upow' => - array ( - ), - 'uw' => - array ( - ), - 'starostwo' => - array ( - ), - 'pa' => - array ( - ), - 'po' => - array ( - ), - 'psse' => - array ( - ), - 'pup' => - array ( - ), - 'rzgw' => - array ( - ), - 'sa' => - array ( - ), - 'so' => - array ( - ), - 'sr' => - array ( - ), - 'wsa' => - array ( - ), - 'sko' => - array ( - ), - 'uzs' => - array ( - ), - 'wiih' => - array ( - ), - 'winb' => - array ( - ), - 'pinb' => - array ( - ), - 'wios' => - array ( - ), - 'witd' => - array ( - ), - 'wzmiuw' => - array ( - ), - 'piw' => - array ( - ), - 'wiw' => - array ( - ), - 'griw' => - array ( - ), - 'wif' => - array ( - ), - 'oum' => - array ( - ), - 'sdn' => - array ( - ), - 'zp' => - array ( - ), - 'uppo' => - array ( - ), - 'mup' => - array ( - ), - 'wuoz' => - array ( - ), - 'konsulat' => - array ( - ), - 'oirm' => - array ( - ), - ), - 'augustow' => - array ( - ), - 'babia-gora' => - array ( - ), - 'bedzin' => - array ( - ), - 'beskidy' => - array ( - ), - 'bialowieza' => - array ( - ), - 'bialystok' => - array ( - ), - 'bielawa' => - array ( - ), - 'bieszczady' => - array ( - ), - 'boleslawiec' => - array ( - ), - 'bydgoszcz' => - array ( - ), - 'bytom' => - array ( - ), - 'cieszyn' => - array ( - ), - 'czeladz' => - array ( - ), - 'czest' => - array ( - ), - 'dlugoleka' => - array ( - ), - 'elblag' => - array ( - ), - 'elk' => - array ( - ), - 'glogow' => - array ( - ), - 'gniezno' => - array ( - ), - 'gorlice' => - array ( - ), - 'grajewo' => - array ( - ), - 'ilawa' => - array ( - ), - 'jaworzno' => - array ( - ), - 'jelenia-gora' => - array ( - ), - 'jgora' => - array ( - ), - 'kalisz' => - array ( - ), - 'kazimierz-dolny' => - array ( - ), - 'karpacz' => - array ( - ), - 'kartuzy' => - array ( - ), - 'kaszuby' => - array ( - ), - 'katowice' => - array ( - ), - 'kepno' => - array ( - ), - 'ketrzyn' => - array ( - ), - 'klodzko' => - array ( - ), - 'kobierzyce' => - array ( - ), - 'kolobrzeg' => - array ( - ), - 'konin' => - array ( - ), - 'konskowola' => - array ( - ), - 'kutno' => - array ( - ), - 'lapy' => - array ( - ), - 'lebork' => - array ( - ), - 'legnica' => - array ( - ), - 'lezajsk' => - array ( - ), - 'limanowa' => - array ( - ), - 'lomza' => - array ( - ), - 'lowicz' => - array ( - ), - 'lubin' => - array ( - ), - 'lukow' => - array ( - ), - 'malbork' => - array ( - ), - 'malopolska' => - array ( - ), - 'mazowsze' => - array ( - ), - 'mazury' => - array ( - ), - 'mielec' => - array ( - ), - 'mielno' => - array ( - ), - 'mragowo' => - array ( - ), - 'naklo' => - array ( - ), - 'nowaruda' => - array ( - ), - 'nysa' => - array ( - ), - 'olawa' => - array ( - ), - 'olecko' => - array ( - ), - 'olkusz' => - array ( - ), - 'olsztyn' => - array ( - ), - 'opoczno' => - array ( - ), - 'opole' => - array ( - ), - 'ostroda' => - array ( - ), - 'ostroleka' => - array ( - ), - 'ostrowiec' => - array ( - ), - 'ostrowwlkp' => - array ( - ), - 'pila' => - array ( - ), - 'pisz' => - array ( - ), - 'podhale' => - array ( - ), - 'podlasie' => - array ( - ), - 'polkowice' => - array ( - ), - 'pomorze' => - array ( - ), - 'pomorskie' => - array ( - ), - 'prochowice' => - array ( - ), - 'pruszkow' => - array ( - ), - 'przeworsk' => - array ( - ), - 'pulawy' => - array ( - ), - 'radom' => - array ( - ), - 'rawa-maz' => - array ( - ), - 'rybnik' => - array ( - ), - 'rzeszow' => - array ( - ), - 'sanok' => - array ( - ), - 'sejny' => - array ( - ), - 'slask' => - array ( - ), - 'slupsk' => - array ( - ), - 'sosnowiec' => - array ( - ), - 'stalowa-wola' => - array ( - ), - 'skoczow' => - array ( - ), - 'starachowice' => - array ( - ), - 'stargard' => - array ( - ), - 'suwalki' => - array ( - ), - 'swidnica' => - array ( - ), - 'swiebodzin' => - array ( - ), - 'swinoujscie' => - array ( - ), - 'szczecin' => - array ( - ), - 'szczytno' => - array ( - ), - 'tarnobrzeg' => - array ( - ), - 'tgory' => - array ( - ), - 'turek' => - array ( - ), - 'tychy' => - array ( - ), - 'ustka' => - array ( - ), - 'walbrzych' => - array ( - ), - 'warmia' => - array ( - ), - 'warszawa' => - array ( - ), - 'waw' => - array ( - ), - 'wegrow' => - array ( - ), - 'wielun' => - array ( - ), - 'wlocl' => - array ( - ), - 'wloclawek' => - array ( - ), - 'wodzislaw' => - array ( - ), - 'wolomin' => - array ( - ), - 'wroclaw' => - array ( - ), - 'zachpomor' => - array ( - ), - 'zagan' => - array ( - ), - 'zarow' => - array ( - ), - 'zgora' => - array ( - ), - 'zgorzelec' => - array ( - ), - 'co' => - array ( - ), - 'art' => - array ( - ), - 'gliwice' => - array ( - ), - 'krakow' => - array ( - ), - 'poznan' => - array ( - ), - 'wroc' => - array ( - ), - 'zakopane' => - array ( - ), - 'gda' => - array ( - ), - 'gdansk' => - array ( - ), - 'gdynia' => - array ( - ), - 'med' => - array ( - ), - 'sopot' => - array ( - ), - ), - 'pm' => - array ( - ), - 'pn' => - array ( - 'gov' => - array ( - ), - 'co' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - ), - 'post' => - array ( - ), - 'pr' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'isla' => - array ( - ), - 'pro' => - array ( - ), - 'biz' => - array ( - ), - 'info' => - array ( - ), - 'name' => - array ( - ), - 'est' => - array ( - ), - 'prof' => - array ( - ), - 'ac' => - array ( - ), - ), - 'pro' => - array ( - 'aca' => - array ( - ), - 'bar' => - array ( - ), - 'cpa' => - array ( - ), - 'jur' => - array ( - ), - 'law' => - array ( - ), - 'med' => - array ( - ), - 'eng' => - array ( - ), - ), - 'ps' => - array ( - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'sec' => - array ( - ), - 'plo' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - ), - 'pt' => - array ( - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'int' => - array ( - ), - 'publ' => - array ( - ), - 'com' => - array ( - ), - 'nome' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'pw' => - array ( - 'co' => - array ( - ), - 'ne' => - array ( - ), - 'or' => - array ( - ), - 'ed' => - array ( - ), - 'go' => - array ( - ), - 'belau' => - array ( - ), - ), - 'py' => - array ( - 'com' => - array ( - ), - 'coop' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'qa' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'sch' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 're' => - array ( - 'asso' => - array ( - ), - 'com' => - array ( - ), - 'nom' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ro' => - array ( - 'arts' => - array ( - ), - 'com' => - array ( - ), - 'firm' => - array ( - ), - 'info' => - array ( - ), - 'nom' => - array ( - ), - 'nt' => - array ( - ), - 'org' => - array ( - ), - 'rec' => - array ( - ), - 'store' => - array ( - ), - 'tm' => - array ( - ), - 'www' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'rs' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'in' => - array ( - ), - 'org' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'ru' => - array ( - 'ac' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'int' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'pp' => - array ( - ), - 'adygeya' => - array ( - ), - 'altai' => - array ( - ), - 'amur' => - array ( - ), - 'arkhangelsk' => - array ( - ), - 'astrakhan' => - array ( - ), - 'bashkiria' => - array ( - ), - 'belgorod' => - array ( - ), - 'bir' => - array ( - ), - 'bryansk' => - array ( - ), - 'buryatia' => - array ( - ), - 'cbg' => - array ( - ), - 'chel' => - array ( - ), - 'chelyabinsk' => - array ( - ), - 'chita' => - array ( - ), - 'chukotka' => - array ( - ), - 'chuvashia' => - array ( - ), - 'dagestan' => - array ( - ), - 'dudinka' => - array ( - ), - 'e-burg' => - array ( - ), - 'grozny' => - array ( - ), - 'irkutsk' => - array ( - ), - 'ivanovo' => - array ( - ), - 'izhevsk' => - array ( - ), - 'jar' => - array ( - ), - 'joshkar-ola' => - array ( - ), - 'kalmykia' => - array ( - ), - 'kaluga' => - array ( - ), - 'kamchatka' => - array ( - ), - 'karelia' => - array ( - ), - 'kazan' => - array ( - ), - 'kchr' => - array ( - ), - 'kemerovo' => - array ( - ), - 'khabarovsk' => - array ( - ), - 'khakassia' => - array ( - ), - 'khv' => - array ( - ), - 'kirov' => - array ( - ), - 'koenig' => - array ( - ), - 'komi' => - array ( - ), - 'kostroma' => - array ( - ), - 'krasnoyarsk' => - array ( - ), - 'kuban' => - array ( - ), - 'kurgan' => - array ( - ), - 'kursk' => - array ( - ), - 'lipetsk' => - array ( - ), - 'magadan' => - array ( - ), - 'mari' => - array ( - ), - 'mari-el' => - array ( - ), - 'marine' => - array ( - ), - 'mordovia' => - array ( - ), - 'msk' => - array ( - ), - 'murmansk' => - array ( - ), - 'nalchik' => - array ( - ), - 'nnov' => - array ( - ), - 'nov' => - array ( - ), - 'novosibirsk' => - array ( - ), - 'nsk' => - array ( - ), - 'omsk' => - array ( - ), - 'orenburg' => - array ( - ), - 'oryol' => - array ( - ), - 'palana' => - array ( - ), - 'penza' => - array ( - ), - 'perm' => - array ( - ), - 'ptz' => - array ( - ), - 'rnd' => - array ( - ), - 'ryazan' => - array ( - ), - 'sakhalin' => - array ( - ), - 'samara' => - array ( - ), - 'saratov' => - array ( - ), - 'simbirsk' => - array ( - ), - 'smolensk' => - array ( - ), - 'spb' => - array ( - ), - 'stavropol' => - array ( - ), - 'stv' => - array ( - ), - 'surgut' => - array ( - ), - 'tambov' => - array ( - ), - 'tatarstan' => - array ( - ), - 'tom' => - array ( - ), - 'tomsk' => - array ( - ), - 'tsaritsyn' => - array ( - ), - 'tsk' => - array ( - ), - 'tula' => - array ( - ), - 'tuva' => - array ( - ), - 'tver' => - array ( - ), - 'tyumen' => - array ( - ), - 'udm' => - array ( - ), - 'udmurtia' => - array ( - ), - 'ulan-ude' => - array ( - ), - 'vladikavkaz' => - array ( - ), - 'vladimir' => - array ( - ), - 'vladivostok' => - array ( - ), - 'volgograd' => - array ( - ), - 'vologda' => - array ( - ), - 'voronezh' => - array ( - ), - 'vrn' => - array ( - ), - 'vyatka' => - array ( - ), - 'yakutia' => - array ( - ), - 'yamal' => - array ( - ), - 'yaroslavl' => - array ( - ), - 'yekaterinburg' => - array ( - ), - 'yuzhno-sakhalinsk' => - array ( - ), - 'amursk' => - array ( - ), - 'baikal' => - array ( - ), - 'cmw' => - array ( - ), - 'fareast' => - array ( - ), - 'jamal' => - array ( - ), - 'kms' => - array ( - ), - 'k-uralsk' => - array ( - ), - 'kustanai' => - array ( - ), - 'kuzbass' => - array ( - ), - 'mytis' => - array ( - ), - 'nakhodka' => - array ( - ), - 'nkz' => - array ( - ), - 'norilsk' => - array ( - ), - 'oskol' => - array ( - ), - 'pyatigorsk' => - array ( - ), - 'rubtsovsk' => - array ( - ), - 'snz' => - array ( - ), - 'syzran' => - array ( - ), - 'vdonsk' => - array ( - ), - 'zgrad' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'test' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'rw' => - array ( - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'ac' => - array ( - ), - 'com' => - array ( - ), - 'co' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'gouv' => - array ( - ), - ), - 'sa' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'med' => - array ( - ), - 'pub' => - array ( - ), - 'edu' => - array ( - ), - 'sch' => - array ( - ), - ), - 'sb' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'sc' => - array ( - 'com' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - ), - 'sd' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'med' => - array ( - ), - 'tv' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - ), - 'se' => - array ( - 'a' => - array ( - ), - 'ac' => - array ( - ), - 'b' => - array ( - ), - 'bd' => - array ( - ), - 'brand' => - array ( - ), - 'c' => - array ( - ), - 'd' => - array ( - ), - 'e' => - array ( - ), - 'f' => - array ( - ), - 'fh' => - array ( - ), - 'fhsk' => - array ( - ), - 'fhv' => - array ( - ), - 'g' => - array ( - ), - 'h' => - array ( - ), - 'i' => - array ( - ), - 'k' => - array ( - ), - 'komforb' => - array ( - ), - 'kommunalforbund' => - array ( - ), - 'komvux' => - array ( - ), - 'l' => - array ( - ), - 'lanbib' => - array ( - ), - 'm' => - array ( - ), - 'n' => - array ( - ), - 'naturbruksgymn' => - array ( - ), - 'o' => - array ( - ), - 'org' => - array ( - ), - 'p' => - array ( - ), - 'parti' => - array ( - ), - 'pp' => - array ( - ), - 'press' => - array ( - ), - 'r' => - array ( - ), - 's' => - array ( - ), - 't' => - array ( - ), - 'tm' => - array ( - ), - 'u' => - array ( - ), - 'w' => - array ( - ), - 'x' => - array ( - ), - 'y' => - array ( - ), - 'z' => - array ( - ), - 'com' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'sg' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'per' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'sh' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - 'mil' => - array ( - ), - 'platform' => - array ( - '*' => - array ( - ), - ), - 'hashbang' => - array ( - ), - ), - 'si' => - array ( - 'blogspot' => - array ( - ), - ), - 'sj' => - array ( - ), - 'sk' => - array ( - 'blogspot' => - array ( - ), - ), - 'sl' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'org' => - array ( - ), - ), - 'sm' => - array ( - ), - 'sn' => - array ( - 'art' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gouv' => - array ( - ), - 'org' => - array ( - ), - 'perso' => - array ( - ), - 'univ' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'so' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'sr' => - array ( - ), - 'st' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'consulado' => - array ( - ), - 'edu' => - array ( - ), - 'embaixada' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'principe' => - array ( - ), - 'saotome' => - array ( - ), - 'store' => - array ( - ), - ), - 'su' => - array ( - 'adygeya' => - array ( - ), - 'arkhangelsk' => - array ( - ), - 'balashov' => - array ( - ), - 'bashkiria' => - array ( - ), - 'bryansk' => - array ( - ), - 'dagestan' => - array ( - ), - 'grozny' => - array ( - ), - 'ivanovo' => - array ( - ), - 'kalmykia' => - array ( - ), - 'kaluga' => - array ( - ), - 'karelia' => - array ( - ), - 'khakassia' => - array ( - ), - 'krasnodar' => - array ( - ), - 'kurgan' => - array ( - ), - 'lenug' => - array ( - ), - 'mordovia' => - array ( - ), - 'msk' => - array ( - ), - 'murmansk' => - array ( - ), - 'nalchik' => - array ( - ), - 'nov' => - array ( - ), - 'obninsk' => - array ( - ), - 'penza' => - array ( - ), - 'pokrovsk' => - array ( - ), - 'sochi' => - array ( - ), - 'spb' => - array ( - ), - 'togliatti' => - array ( - ), - 'troitsk' => - array ( - ), - 'tula' => - array ( - ), - 'tuva' => - array ( - ), - 'vladikavkaz' => - array ( - ), - 'vladimir' => - array ( - ), - 'vologda' => - array ( - ), - ), - 'sv' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gob' => - array ( - ), - 'org' => - array ( - ), - 'red' => - array ( - ), - ), - 'sx' => - array ( - 'gov' => - array ( - ), - ), - 'sy' => - array ( - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - ), - 'sz' => - array ( - 'co' => - array ( - ), - 'ac' => - array ( - ), - 'org' => - array ( - ), - ), - 'tc' => - array ( - ), - 'td' => - array ( - 'blogspot' => - array ( - ), - ), - 'tel' => - array ( - ), - 'tf' => - array ( - ), - 'tg' => - array ( - ), - 'th' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'go' => - array ( - ), - 'in' => - array ( - ), - 'mi' => - array ( - ), - 'net' => - array ( - ), - 'or' => - array ( - ), - ), - 'tj' => - array ( - 'ac' => - array ( - ), - 'biz' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'go' => - array ( - ), - 'gov' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'name' => - array ( - ), - 'net' => - array ( - ), - 'nic' => - array ( - ), - 'org' => - array ( - ), - 'test' => - array ( - ), - 'web' => - array ( - ), - ), - 'tk' => - array ( - ), - 'tl' => - array ( - 'gov' => - array ( - ), - ), - 'tm' => - array ( - 'com' => - array ( - ), - 'co' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'nom' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'edu' => - array ( - ), - ), - 'tn' => - array ( - 'com' => - array ( - ), - 'ens' => - array ( - ), - 'fin' => - array ( - ), - 'gov' => - array ( - ), - 'ind' => - array ( - ), - 'intl' => - array ( - ), - 'nat' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'info' => - array ( - ), - 'perso' => - array ( - ), - 'tourism' => - array ( - ), - 'edunet' => - array ( - ), - 'rnrt' => - array ( - ), - 'rns' => - array ( - ), - 'rnu' => - array ( - ), - 'mincom' => - array ( - ), - 'agrinet' => - array ( - ), - 'defense' => - array ( - ), - 'turen' => - array ( - ), - ), - 'to' => - array ( - 'com' => - array ( - ), - 'gov' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'mil' => - array ( - ), - ), - 'tr' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'info' => - array ( - ), - 'biz' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'web' => - array ( - ), - 'gen' => - array ( - ), - 'tv' => - array ( - ), - 'av' => - array ( - ), - 'dr' => - array ( - ), - 'bbs' => - array ( - ), - 'name' => - array ( - ), - 'tel' => - array ( - ), - 'gov' => - array ( - ), - 'bel' => - array ( - ), - 'pol' => - array ( - ), - 'mil' => - array ( - ), - 'k12' => - array ( - ), - 'edu' => - array ( - ), - 'kep' => - array ( - ), - 'nc' => - array ( - 'gov' => - array ( - ), - ), - ), - 'travel' => - array ( - ), - 'tt' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'net' => - array ( - ), - 'biz' => - array ( - ), - 'info' => - array ( - ), - 'pro' => - array ( - ), - 'int' => - array ( - ), - 'coop' => - array ( - ), - 'jobs' => - array ( - ), - 'mobi' => - array ( - ), - 'travel' => - array ( - ), - 'museum' => - array ( - ), - 'aero' => - array ( - ), - 'name' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - ), - 'tv' => - array ( - 'dyndns' => - array ( - ), - 'better-than' => - array ( - ), - 'on-the-web' => - array ( - ), - 'worse-than' => - array ( - ), - ), - 'tw' => - array ( - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'idv' => - array ( - ), - 'game' => - array ( - ), - 'ebiz' => - array ( - ), - 'club' => - array ( - ), - 'xn--zf0ao64a' => - array ( - ), - 'xn--uc0atv' => - array ( - ), - 'xn--czrw28b' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'tz' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - ), - 'go' => - array ( - ), - 'hotel' => - array ( - ), - 'info' => - array ( - ), - 'me' => - array ( - ), - 'mil' => - array ( - ), - 'mobi' => - array ( - ), - 'ne' => - array ( - ), - 'or' => - array ( - ), - 'sc' => - array ( - ), - 'tv' => - array ( - ), - ), - 'ua' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'in' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'cherkassy' => - array ( - ), - 'cherkasy' => - array ( - ), - 'chernigov' => - array ( - ), - 'chernihiv' => - array ( - ), - 'chernivtsi' => - array ( - ), - 'chernovtsy' => - array ( - ), - 'ck' => - array ( - ), - 'cn' => - array ( - ), - 'cr' => - array ( - ), - 'crimea' => - array ( - ), - 'cv' => - array ( - ), - 'dn' => - array ( - ), - 'dnepropetrovsk' => - array ( - ), - 'dnipropetrovsk' => - array ( - ), - 'dominic' => - array ( - ), - 'donetsk' => - array ( - ), - 'dp' => - array ( - ), - 'if' => - array ( - ), - 'ivano-frankivsk' => - array ( - ), - 'kh' => - array ( - ), - 'kharkiv' => - array ( - ), - 'kharkov' => - array ( - ), - 'kherson' => - array ( - ), - 'khmelnitskiy' => - array ( - ), - 'khmelnytskyi' => - array ( - ), - 'kiev' => - array ( - ), - 'kirovograd' => - array ( - ), - 'km' => - array ( - ), - 'kr' => - array ( - ), - 'krym' => - array ( - ), - 'ks' => - array ( - ), - 'kv' => - array ( - ), - 'kyiv' => - array ( - ), - 'lg' => - array ( - ), - 'lt' => - array ( - ), - 'lugansk' => - array ( - ), - 'lutsk' => - array ( - ), - 'lv' => - array ( - ), - 'lviv' => - array ( - ), - 'mk' => - array ( - ), - 'mykolaiv' => - array ( - ), - 'nikolaev' => - array ( - ), - 'od' => - array ( - ), - 'odesa' => - array ( - ), - 'odessa' => - array ( - ), - 'pl' => - array ( - ), - 'poltava' => - array ( - ), - 'rivne' => - array ( - ), - 'rovno' => - array ( - ), - 'rv' => - array ( - ), - 'sb' => - array ( - ), - 'sebastopol' => - array ( - ), - 'sevastopol' => - array ( - ), - 'sm' => - array ( - ), - 'sumy' => - array ( - ), - 'te' => - array ( - ), - 'ternopil' => - array ( - ), - 'uz' => - array ( - ), - 'uzhgorod' => - array ( - ), - 'vinnica' => - array ( - ), - 'vinnytsia' => - array ( - ), - 'vn' => - array ( - ), - 'volyn' => - array ( - ), - 'yalta' => - array ( - ), - 'zaporizhzhe' => - array ( - ), - 'zaporizhzhia' => - array ( - ), - 'zhitomir' => - array ( - ), - 'zhytomyr' => - array ( - ), - 'zp' => - array ( - ), - 'zt' => - array ( - ), - 'biz' => - array ( - ), - 'co' => - array ( - ), - 'pp' => - array ( - ), - ), - 'ug' => - array ( - 'co' => - array ( - ), - 'or' => - array ( - ), - 'ac' => - array ( - ), - 'sc' => - array ( - ), - 'go' => - array ( - ), - 'ne' => - array ( - ), - 'com' => - array ( - ), - 'org' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'uk' => - array ( - 'ac' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'gov' => - array ( - 'service' => - array ( - ), - ), - 'ltd' => - array ( - ), - 'me' => - array ( - ), - 'net' => - array ( - ), - 'nhs' => - array ( - ), - 'org' => - array ( - ), - 'plc' => - array ( - ), - 'police' => - array ( - ), - 'sch' => - array ( - '*' => - array ( - ), - ), - ), - 'us' => - array ( - 'dni' => - array ( - ), - 'fed' => - array ( - ), - 'isa' => - array ( - ), - 'kids' => - array ( - ), - 'nsn' => - array ( - ), - 'ak' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'al' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ar' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'as' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'az' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ca' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'co' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ct' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'dc' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'de' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'fl' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ga' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'gu' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'hi' => - array ( - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ia' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'id' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'il' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'in' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ks' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ky' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'la' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ma' => - array ( - 'k12' => - array ( - 'pvt' => - array ( - ), - 'chtr' => - array ( - ), - 'paroch' => - array ( - ), - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'md' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'me' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'mi' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'mn' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'mo' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ms' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'mt' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nc' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nd' => - array ( - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ne' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nh' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nj' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nm' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'nv' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ny' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'oh' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ok' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'or' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'pa' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'pr' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ri' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'sc' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'sd' => - array ( - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'tn' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'tx' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'ut' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'vi' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'vt' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'va' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'wa' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'wi' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'wv' => - array ( - 'cc' => - array ( - ), - ), - 'wy' => - array ( - 'k12' => - array ( - ), - 'cc' => - array ( - ), - 'lib' => - array ( - ), - ), - 'is-by' => - array ( - ), - 'land-4-sale' => - array ( - ), - 'stuff-4-sale' => - array ( - ), - ), - 'uy' => - array ( - 'com' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'gub' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'uz' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'va' => - array ( - ), - 'vc' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'mil' => - array ( - ), - 'edu' => - array ( - ), - ), - 've' => - array ( - 'arts' => - array ( - ), - 'co' => - array ( - ), - 'com' => - array ( - ), - 'e12' => - array ( - ), - 'edu' => - array ( - ), - 'firm' => - array ( - ), - 'gob' => - array ( - ), - 'gov' => - array ( - ), - 'info' => - array ( - ), - 'int' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'rec' => - array ( - ), - 'store' => - array ( - ), - 'tec' => - array ( - ), - 'web' => - array ( - ), - ), - 'vg' => - array ( - ), - 'vi' => - array ( - 'co' => - array ( - ), - 'com' => - array ( - ), - 'k12' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'vn' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'int' => - array ( - ), - 'ac' => - array ( - ), - 'biz' => - array ( - ), - 'info' => - array ( - ), - 'name' => - array ( - ), - 'pro' => - array ( - ), - 'health' => - array ( - ), - 'blogspot' => - array ( - ), - ), - 'vu' => - array ( - 'com' => - array ( - ), - 'edu' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - ), - 'wf' => - array ( - ), - 'ws' => - array ( - 'com' => - array ( - ), - 'net' => - array ( - ), - 'org' => - array ( - ), - 'gov' => - array ( - ), - 'edu' => - array ( - ), - 'dyndns' => - array ( - ), - 'mypets' => - array ( - ), - ), - 'yt' => - array ( - ), - 'xn--mgbaam7a8h' => - array ( - ), - 'xn--y9a3aq' => - array ( - ), - 'xn--54b7fta0cc' => - array ( - ), - 'xn--90ais' => - array ( - ), - 'xn--fiqs8s' => - array ( - ), - 'xn--fiqz9s' => - array ( - ), - 'xn--lgbbat1ad8j' => - array ( - ), - 'xn--wgbh1c' => - array ( - ), - 'xn--node' => - array ( - ), - 'xn--qxam' => - array ( - ), - 'xn--j6w193g' => - array ( - ), - 'xn--h2brj9c' => - array ( - ), - 'xn--mgbbh1a71e' => - array ( - ), - 'xn--fpcrj9c3d' => - array ( - ), - 'xn--gecrj9c' => - array ( - ), - 'xn--s9brj9c' => - array ( - ), - 'xn--45brj9c' => - array ( - ), - 'xn--xkc2dl3a5ee0h' => - array ( - ), - 'xn--mgba3a4f16a' => - array ( - ), - 'xn--mgba3a4fra' => - array ( - ), - 'xn--mgbtx2b' => - array ( - ), - 'xn--mgbayh7gpa' => - array ( - ), - 'xn--3e0b707e' => - array ( - ), - 'xn--80ao21a' => - array ( - ), - 'xn--fzc2c9e2c' => - array ( - ), - 'xn--xkc2al3hye2a' => - array ( - ), - 'xn--mgbc0a9azcg' => - array ( - ), - 'xn--d1alf' => - array ( - ), - 'xn--l1acc' => - array ( - ), - 'xn--mix891f' => - array ( - ), - 'xn--mix082f' => - array ( - ), - 'xn--mgbx4cd0ab' => - array ( - ), - 'xn--mgb9awbf' => - array ( - ), - 'xn--mgbai9azgqp6j' => - array ( - ), - 'xn--mgbai9a5eva00b' => - array ( - ), - 'xn--ygbi2ammx' => - array ( - ), - 'xn--90a3ac' => - array ( - 'xn--o1ac' => - array ( - ), - 'xn--c1avg' => - array ( - ), - 'xn--90azh' => - array ( - ), - 'xn--d1at' => - array ( - ), - 'xn--o1ach' => - array ( - ), - 'xn--80au' => - array ( - ), - ), - 'xn--p1ai' => - array ( - ), - 'xn--wgbl6a' => - array ( - ), - 'xn--mgberp4a5d4ar' => - array ( - ), - 'xn--mgberp4a5d4a87g' => - array ( - ), - 'xn--mgbqly7c0a67fbc' => - array ( - ), - 'xn--mgbqly7cvafr' => - array ( - ), - 'xn--mgbpl2fh' => - array ( - ), - 'xn--yfro4i67o' => - array ( - ), - 'xn--clchc0ea0b2g2a9gcd' => - array ( - ), - 'xn--ogbpf8fl' => - array ( - ), - 'xn--mgbtf8fl' => - array ( - ), - 'xn--o3cw4h' => - array ( - ), - 'xn--pgbs0dh' => - array ( - ), - 'xn--kpry57d' => - array ( - ), - 'xn--kprw13d' => - array ( - ), - 'xn--nnx388a' => - array ( - ), - 'xn--j1amh' => - array ( - ), - 'xn--mgb2ddes' => - array ( - ), - 'xxx' => - array ( - ), - 'ye' => - array ( - '*' => - array ( - ), - ), - 'za' => - array ( - 'ac' => - array ( - ), - 'agric' => - array ( - ), - 'alt' => - array ( - ), - 'co' => - array ( - 'blogspot' => - array ( - ), - ), - 'edu' => - array ( - ), - 'gov' => - array ( - ), - 'grondar' => - array ( - ), - 'law' => - array ( - ), - 'mil' => - array ( - ), - 'net' => - array ( - ), - 'ngo' => - array ( - ), - 'nis' => - array ( - ), - 'nom' => - array ( - ), - 'org' => - array ( - ), - 'school' => - array ( - ), - 'tm' => - array ( - ), - 'web' => - array ( - ), - ), - 'zm' => - array ( - '*' => - array ( - ), - ), - 'zw' => - array ( - '*' => - array ( - ), - ), - 'aaa' => - array ( - ), - 'aarp' => - array ( - ), - 'abarth' => - array ( - ), - 'abb' => - array ( - ), - 'abbott' => - array ( - ), - 'abbvie' => - array ( - ), - 'abc' => - array ( - ), - 'able' => - array ( - ), - 'abogado' => - array ( - ), - 'abudhabi' => - array ( - ), - 'academy' => - array ( - ), - 'accenture' => - array ( - ), - 'accountant' => - array ( - ), - 'accountants' => - array ( - ), - 'aco' => - array ( - ), - 'active' => - array ( - ), - 'actor' => - array ( - ), - 'adac' => - array ( - ), - 'ads' => - array ( - ), - 'adult' => - array ( - ), - 'aeg' => - array ( - ), - 'aetna' => - array ( - ), - 'afamilycompany' => - array ( - ), - 'afl' => - array ( - ), - 'africa' => - array ( - ), - 'africamagic' => - array ( - ), - 'agakhan' => - array ( - ), - 'agency' => - array ( - ), - 'aig' => - array ( - ), - 'aigo' => - array ( - ), - 'airbus' => - array ( - ), - 'airforce' => - array ( - ), - 'airtel' => - array ( - ), - 'akdn' => - array ( - ), - 'alfaromeo' => - array ( - ), - 'alibaba' => - array ( - ), - 'alipay' => - array ( - ), - 'allfinanz' => - array ( - ), - 'allstate' => - array ( - ), - 'ally' => - array ( - ), - 'alsace' => - array ( - ), - 'alstom' => - array ( - ), - 'americanexpress' => - array ( - ), - 'americanfamily' => - array ( - ), - 'amex' => - array ( - ), - 'amfam' => - array ( - ), - 'amica' => - array ( - ), - 'amsterdam' => - array ( - ), - 'analytics' => - array ( - ), - 'android' => - array ( - ), - 'anquan' => - array ( - ), - 'anz' => - array ( - ), - 'aol' => - array ( - ), - 'apartments' => - array ( - ), - 'app' => - array ( - ), - 'apple' => - array ( - ), - 'aquarelle' => - array ( - ), - 'arab' => - array ( - ), - 'aramco' => - array ( - ), - 'archi' => - array ( - ), - 'army' => - array ( - ), - 'arte' => - array ( - ), - 'asda' => - array ( - ), - 'associates' => - array ( - ), - 'athleta' => - array ( - ), - 'attorney' => - array ( - ), - 'auction' => - array ( - ), - 'audi' => - array ( - ), - 'audible' => - array ( - ), - 'audio' => - array ( - ), - 'auspost' => - array ( - ), - 'author' => - array ( - ), - 'auto' => - array ( - ), - 'autos' => - array ( - ), - 'avianca' => - array ( - ), - 'aws' => - array ( - ), - 'axa' => - array ( - ), - 'azure' => - array ( - ), - 'baby' => - array ( - ), - 'baidu' => - array ( - ), - 'banamex' => - array ( - ), - 'bananarepublic' => - array ( - ), - 'band' => - array ( - ), - 'bank' => - array ( - ), - 'bar' => - array ( - ), - 'barcelona' => - array ( - ), - 'barclaycard' => - array ( - ), - 'barclays' => - array ( - ), - 'barefoot' => - array ( - ), - 'bargains' => - array ( - ), - 'baseball' => - array ( - ), - 'basketball' => - array ( - ), - 'bauhaus' => - array ( - ), - 'bayern' => - array ( - ), - 'bbc' => - array ( - ), - 'bbt' => - array ( - ), - 'bbva' => - array ( - ), - 'bcg' => - array ( - ), - 'bcn' => - array ( - ), - 'beats' => - array ( - ), - 'beauty' => - array ( - ), - 'beer' => - array ( - ), - 'bentley' => - array ( - ), - 'berlin' => - array ( - ), - 'best' => - array ( - ), - 'bestbuy' => - array ( - ), - 'bet' => - array ( - ), - 'bharti' => - array ( - ), - 'bible' => - array ( - ), - 'bid' => - array ( - ), - 'bike' => - array ( - ), - 'bing' => - array ( - ), - 'bingo' => - array ( - ), - 'bio' => - array ( - ), - 'black' => - array ( - ), - 'blackfriday' => - array ( - ), - 'blanco' => - array ( - ), - 'blockbuster' => - array ( - ), - 'blog' => - array ( - ), - 'bloomberg' => - array ( - ), - 'blue' => - array ( - ), - 'bms' => - array ( - ), - 'bmw' => - array ( - ), - 'bnl' => - array ( - ), - 'bnpparibas' => - array ( - ), - 'boats' => - array ( - ), - 'boehringer' => - array ( - ), - 'bofa' => - array ( - ), - 'bom' => - array ( - ), - 'bond' => - array ( - ), - 'boo' => - array ( - ), - 'book' => - array ( - ), - 'booking' => - array ( - ), - 'boots' => - array ( - ), - 'bosch' => - array ( - ), - 'bostik' => - array ( - ), - 'boston' => - array ( - ), - 'bot' => - array ( - ), - 'boutique' => - array ( - ), - 'box' => - array ( - ), - 'bradesco' => - array ( - ), - 'bridgestone' => - array ( - ), - 'broadway' => - array ( - ), - 'broker' => - array ( - ), - 'brother' => - array ( - ), - 'brussels' => - array ( - ), - 'budapest' => - array ( - ), - 'bugatti' => - array ( - ), - 'build' => - array ( - ), - 'builders' => - array ( - ), - 'business' => - array ( - ), - 'buy' => - array ( - ), - 'buzz' => - array ( - ), - 'bzh' => - array ( - ), - 'cab' => - array ( - ), - 'cafe' => - array ( - ), - 'cal' => - array ( - ), - 'call' => - array ( - ), - 'calvinklein' => - array ( - ), - 'camera' => - array ( - ), - 'camp' => - array ( - ), - 'cancerresearch' => - array ( - ), - 'canon' => - array ( - ), - 'capetown' => - array ( - ), - 'capital' => - array ( - ), - 'capitalone' => - array ( - ), - 'car' => - array ( - ), - 'caravan' => - array ( - ), - 'cards' => - array ( - ), - 'care' => - array ( - ), - 'career' => - array ( - ), - 'careers' => - array ( - ), - 'cars' => - array ( - ), - 'cartier' => - array ( - ), - 'casa' => - array ( - ), - 'case' => - array ( - ), - 'caseih' => - array ( - ), - 'cash' => - array ( - ), - 'casino' => - array ( - ), - 'catering' => - array ( - ), - 'catholic' => - array ( - ), - 'cba' => - array ( - ), - 'cbn' => - array ( - ), - 'cbre' => - array ( - ), - 'cbs' => - array ( - ), - 'ceb' => - array ( - ), - 'center' => - array ( - ), - 'ceo' => - array ( - ), - 'cern' => - array ( - ), - 'cfa' => - array ( - ), - 'cfd' => - array ( - ), - 'chanel' => - array ( - ), - 'channel' => - array ( - ), - 'chase' => - array ( - ), - 'chat' => - array ( - ), - 'cheap' => - array ( - ), - 'chintai' => - array ( - ), - 'chloe' => - array ( - ), - 'christmas' => - array ( - ), - 'chrome' => - array ( - ), - 'chrysler' => - array ( - ), - 'church' => - array ( - ), - 'cipriani' => - array ( - ), - 'circle' => - array ( - ), - 'cisco' => - array ( - ), - 'citadel' => - array ( - ), - 'citi' => - array ( - ), - 'citic' => - array ( - ), - 'city' => - array ( - ), - 'cityeats' => - array ( - ), - 'claims' => - array ( - ), - 'cleaning' => - array ( - ), - 'click' => - array ( - ), - 'clinic' => - array ( - ), - 'clinique' => - array ( - ), - 'clothing' => - array ( - ), - 'cloud' => - array ( - ), - 'club' => - array ( - ), - 'clubmed' => - array ( - ), - 'coach' => - array ( - ), - 'codes' => - array ( - ), - 'coffee' => - array ( - ), - 'college' => - array ( - ), - 'cologne' => - array ( - ), - 'comcast' => - array ( - ), - 'commbank' => - array ( - ), - 'community' => - array ( - ), - 'company' => - array ( - ), - 'compare' => - array ( - ), - 'computer' => - array ( - ), - 'comsec' => - array ( - ), - 'condos' => - array ( - ), - 'construction' => - array ( - ), - 'consulting' => - array ( - ), - 'contact' => - array ( - ), - 'contractors' => - array ( - ), - 'cooking' => - array ( - ), - 'cookingchannel' => - array ( - ), - 'cool' => - array ( - ), - 'corsica' => - array ( - ), - 'country' => - array ( - ), - 'coupon' => - array ( - ), - 'coupons' => - array ( - ), - 'courses' => - array ( - ), - 'credit' => - array ( - ), - 'creditcard' => - array ( - ), - 'creditunion' => - array ( - ), - 'cricket' => - array ( - ), - 'crown' => - array ( - ), - 'crs' => - array ( - ), - 'cruise' => - array ( - ), - 'cruises' => - array ( - ), - 'csc' => - array ( - ), - 'cuisinella' => - array ( - ), - 'cymru' => - array ( - ), - 'cyou' => - array ( - ), - 'dabur' => - array ( - ), - 'dad' => - array ( - ), - 'dance' => - array ( - ), - 'date' => - array ( - ), - 'dating' => - array ( - ), - 'datsun' => - array ( - ), - 'day' => - array ( - ), - 'dclk' => - array ( - ), - 'dds' => - array ( - ), - 'deal' => - array ( - ), - 'dealer' => - array ( - ), - 'deals' => - array ( - ), - 'degree' => - array ( - ), - 'delivery' => - array ( - ), - 'dell' => - array ( - ), - 'deloitte' => - array ( - ), - 'delta' => - array ( - ), - 'democrat' => - array ( - ), - 'dental' => - array ( - ), - 'dentist' => - array ( - ), - 'desi' => - array ( - ), - 'design' => - array ( - ), - 'dev' => - array ( - ), - 'dhl' => - array ( - ), - 'diamonds' => - array ( - ), - 'diet' => - array ( - ), - 'digital' => - array ( - ), - 'direct' => - array ( - ), - 'directory' => - array ( - ), - 'discount' => - array ( - ), - 'discover' => - array ( - ), - 'dish' => - array ( - ), - 'diy' => - array ( - ), - 'dnp' => - array ( - ), - 'docs' => - array ( - ), - 'dodge' => - array ( - ), - 'dog' => - array ( - ), - 'doha' => - array ( - ), - 'domains' => - array ( - ), - 'doosan' => - array ( - ), - 'dot' => - array ( - ), - 'download' => - array ( - ), - 'drive' => - array ( - ), - 'dstv' => - array ( - ), - 'dtv' => - array ( - ), - 'dubai' => - array ( - ), - 'duck' => - array ( - ), - 'dunlop' => - array ( - ), - 'duns' => - array ( - ), - 'dupont' => - array ( - ), - 'durban' => - array ( - ), - 'dvag' => - array ( - ), - 'dwg' => - array ( - ), - 'earth' => - array ( - ), - 'eat' => - array ( - ), - 'edeka' => - array ( - ), - 'education' => - array ( - ), - 'email' => - array ( - ), - 'emerck' => - array ( - ), - 'emerson' => - array ( - ), - 'energy' => - array ( - ), - 'engineer' => - array ( - ), - 'engineering' => - array ( - ), - 'enterprises' => - array ( - ), - 'epost' => - array ( - ), - 'epson' => - array ( - ), - 'equipment' => - array ( - ), - 'ericsson' => - array ( - ), - 'erni' => - array ( - ), - 'esq' => - array ( - ), - 'estate' => - array ( - ), - 'esurance' => - array ( - ), - 'etisalat' => - array ( - ), - 'eurovision' => - array ( - ), - 'eus' => - array ( - ), - 'events' => - array ( - ), - 'everbank' => - array ( - ), - 'exchange' => - array ( - ), - 'expert' => - array ( - ), - 'exposed' => - array ( - ), - 'express' => - array ( - ), - 'extraspace' => - array ( - ), - 'fage' => - array ( - ), - 'fail' => - array ( - ), - 'fairwinds' => - array ( - ), - 'faith' => - array ( - ), - 'family' => - array ( - ), - 'fan' => - array ( - ), - 'fans' => - array ( - ), - 'farm' => - array ( - ), - 'farmers' => - array ( - ), - 'fashion' => - array ( - ), - 'fast' => - array ( - ), - 'fedex' => - array ( - ), - 'feedback' => - array ( - ), - 'ferrari' => - array ( - ), - 'ferrero' => - array ( - ), - 'fiat' => - array ( - ), - 'fidelity' => - array ( - ), - 'fido' => - array ( - ), - 'film' => - array ( - ), - 'final' => - array ( - ), - 'finance' => - array ( - ), - 'financial' => - array ( - ), - 'fire' => - array ( - ), - 'firestone' => - array ( - ), - 'firmdale' => - array ( - ), - 'fish' => - array ( - ), - 'fishing' => - array ( - ), - 'fit' => - array ( - ), - 'fitness' => - array ( - ), - 'flickr' => - array ( - ), - 'flights' => - array ( - ), - 'flir' => - array ( - ), - 'florist' => - array ( - ), - 'flowers' => - array ( - ), - 'flsmidth' => - array ( - ), - 'fly' => - array ( - ), - 'foo' => - array ( - ), - 'foodnetwork' => - array ( - ), - 'football' => - array ( - ), - 'ford' => - array ( - ), - 'forex' => - array ( - ), - 'forsale' => - array ( - ), - 'forum' => - array ( - ), - 'foundation' => - array ( - ), - 'fox' => - array ( - ), - 'free' => - array ( - ), - 'fresenius' => - array ( - ), - 'frl' => - array ( - ), - 'frogans' => - array ( - ), - 'frontdoor' => - array ( - ), - 'frontier' => - array ( - ), - 'ftr' => - array ( - ), - 'fujitsu' => - array ( - ), - 'fujixerox' => - array ( - ), - 'fund' => - array ( - ), - 'furniture' => - array ( - ), - 'futbol' => - array ( - ), - 'fyi' => - array ( - ), - 'gal' => - array ( - ), - 'gallery' => - array ( - ), - 'gallo' => - array ( - ), - 'gallup' => - array ( - ), - 'game' => - array ( - ), - 'games' => - array ( - ), - 'gap' => - array ( - ), - 'garden' => - array ( - ), - 'gbiz' => - array ( - ), - 'gdn' => - array ( - ), - 'gea' => - array ( - ), - 'gent' => - array ( - ), - 'genting' => - array ( - ), - 'george' => - array ( - ), - 'ggee' => - array ( - ), - 'gift' => - array ( - ), - 'gifts' => - array ( - ), - 'gives' => - array ( - ), - 'giving' => - array ( - ), - 'glade' => - array ( - ), - 'glass' => - array ( - ), - 'gle' => - array ( - ), - 'global' => - array ( - ), - 'globo' => - array ( - ), - 'gmail' => - array ( - ), - 'gmo' => - array ( - ), - 'gmx' => - array ( - ), - 'godaddy' => - array ( - ), - 'gold' => - array ( - ), - 'goldpoint' => - array ( - ), - 'golf' => - array ( - ), - 'goo' => - array ( - ), - 'goodhands' => - array ( - ), - 'goodyear' => - array ( - ), - 'goog' => - array ( - ), - 'google' => - array ( - ), - 'gop' => - array ( - ), - 'got' => - array ( - ), - 'gotv' => - array ( - ), - 'grainger' => - array ( - ), - 'graphics' => - array ( - ), - 'gratis' => - array ( - ), - 'green' => - array ( - ), - 'gripe' => - array ( - ), - 'group' => - array ( - ), - 'guardian' => - array ( - ), - 'gucci' => - array ( - ), - 'guge' => - array ( - ), - 'guide' => - array ( - ), - 'guitars' => - array ( - ), - 'guru' => - array ( - ), - 'hair' => - array ( - ), - 'hamburg' => - array ( - ), - 'hangout' => - array ( - ), - 'haus' => - array ( - ), - 'hbo' => - array ( - ), - 'hdfc' => - array ( - ), - 'hdfcbank' => - array ( - ), - 'health' => - array ( - ), - 'healthcare' => - array ( - ), - 'help' => - array ( - ), - 'helsinki' => - array ( - ), - 'here' => - array ( - ), - 'hermes' => - array ( - ), - 'hgtv' => - array ( - ), - 'hiphop' => - array ( - ), - 'hisamitsu' => - array ( - ), - 'hitachi' => - array ( - ), - 'hiv' => - array ( - ), - 'hkt' => - array ( - ), - 'hockey' => - array ( - ), - 'holdings' => - array ( - ), - 'holiday' => - array ( - ), - 'homedepot' => - array ( - ), - 'homegoods' => - array ( - ), - 'homes' => - array ( - ), - 'homesense' => - array ( - ), - 'honda' => - array ( - ), - 'honeywell' => - array ( - ), - 'horse' => - array ( - ), - 'host' => - array ( - ), - 'hosting' => - array ( - ), - 'hot' => - array ( - ), - 'hoteles' => - array ( - ), - 'hotmail' => - array ( - ), - 'house' => - array ( - ), - 'how' => - array ( - ), - 'hsbc' => - array ( - ), - 'htc' => - array ( - ), - 'hughes' => - array ( - ), - 'hyatt' => - array ( - ), - 'hyundai' => - array ( - ), - 'ibm' => - array ( - ), - 'icbc' => - array ( - ), - 'ice' => - array ( - ), - 'icu' => - array ( - ), - 'ieee' => - array ( - ), - 'ifm' => - array ( - ), - 'iinet' => - array ( - ), - 'ikano' => - array ( - ), - 'imamat' => - array ( - ), - 'imdb' => - array ( - ), - 'immo' => - array ( - ), - 'immobilien' => - array ( - ), - 'industries' => - array ( - ), - 'infiniti' => - array ( - ), - 'ing' => - array ( - ), - 'ink' => - array ( - ), - 'institute' => - array ( - ), - 'insurance' => - array ( - ), - 'insure' => - array ( - ), - 'intel' => - array ( - ), - 'international' => - array ( - ), - 'intuit' => - array ( - ), - 'investments' => - array ( - ), - 'ipiranga' => - array ( - ), - 'irish' => - array ( - ), - 'iselect' => - array ( - ), - 'ismaili' => - array ( - ), - 'ist' => - array ( - ), - 'istanbul' => - array ( - ), - 'itau' => - array ( - ), - 'itv' => - array ( - ), - 'iveco' => - array ( - ), - 'iwc' => - array ( - ), - 'jaguar' => - array ( - ), - 'java' => - array ( - ), - 'jcb' => - array ( - ), - 'jcp' => - array ( - ), - 'jeep' => - array ( - ), - 'jetzt' => - array ( - ), - 'jewelry' => - array ( - ), - 'jio' => - array ( - ), - 'jlc' => - array ( - ), - 'jll' => - array ( - ), - 'jmp' => - array ( - ), - 'jnj' => - array ( - ), - 'joburg' => - array ( - ), - 'jot' => - array ( - ), - 'joy' => - array ( - ), - 'jpmorgan' => - array ( - ), - 'jprs' => - array ( - ), - 'juegos' => - array ( - ), - 'juniper' => - array ( - ), - 'kaufen' => - array ( - ), - 'kddi' => - array ( - ), - 'kerryhotels' => - array ( - ), - 'kerrylogistics' => - array ( - ), - 'kerryproperties' => - array ( - ), - 'kfh' => - array ( - ), - 'kia' => - array ( - ), - 'kim' => - array ( - ), - 'kinder' => - array ( - ), - 'kindle' => - array ( - ), - 'kitchen' => - array ( - ), - 'kiwi' => - array ( - ), - 'koeln' => - array ( - ), - 'komatsu' => - array ( - ), - 'kosher' => - array ( - ), - 'kpmg' => - array ( - ), - 'kpn' => - array ( - ), - 'krd' => - array ( - ), - 'kred' => - array ( - ), - 'kuokgroup' => - array ( - ), - 'kyknet' => - array ( - ), - 'kyoto' => - array ( - ), - 'lacaixa' => - array ( - ), - 'ladbrokes' => - array ( - ), - 'lamborghini' => - array ( - ), - 'lamer' => - array ( - ), - 'lancaster' => - array ( - ), - 'lancia' => - array ( - ), - 'lancome' => - array ( - ), - 'land' => - array ( - ), - 'landrover' => - array ( - ), - 'lanxess' => - array ( - ), - 'lasalle' => - array ( - ), - 'lat' => - array ( - ), - 'latino' => - array ( - ), - 'latrobe' => - array ( - ), - 'law' => - array ( - ), - 'lawyer' => - array ( - ), - 'lds' => - array ( - ), - 'lease' => - array ( - ), - 'leclerc' => - array ( - ), - 'lefrak' => - array ( - ), - 'legal' => - array ( - ), - 'lego' => - array ( - ), - 'lexus' => - array ( - ), - 'lgbt' => - array ( - ), - 'liaison' => - array ( - ), - 'lidl' => - array ( - ), - 'life' => - array ( - ), - 'lifeinsurance' => - array ( - ), - 'lifestyle' => - array ( - ), - 'lighting' => - array ( - ), - 'like' => - array ( - ), - 'lilly' => - array ( - ), - 'limited' => - array ( - ), - 'limo' => - array ( - ), - 'lincoln' => - array ( - ), - 'linde' => - array ( - ), - 'link' => - array ( - ), - 'lipsy' => - array ( - ), - 'live' => - array ( - ), - 'living' => - array ( - ), - 'lixil' => - array ( - ), - 'loan' => - array ( - ), - 'loans' => - array ( - ), - 'locker' => - array ( - ), - 'locus' => - array ( - ), - 'loft' => - array ( - ), - 'lol' => - array ( - ), - 'london' => - array ( - ), - 'lotte' => - array ( - ), - 'lotto' => - array ( - ), - 'love' => - array ( - ), - 'lpl' => - array ( - ), - 'lplfinancial' => - array ( - ), - 'ltd' => - array ( - ), - 'ltda' => - array ( - ), - 'lundbeck' => - array ( - ), - 'lupin' => - array ( - ), - 'luxe' => - array ( - ), - 'luxury' => - array ( - ), - 'macys' => - array ( - ), - 'madrid' => - array ( - ), - 'maif' => - array ( - ), - 'maison' => - array ( - ), - 'makeup' => - array ( - ), - 'man' => - array ( - ), - 'management' => - array ( - ), - 'mango' => - array ( - ), - 'market' => - array ( - ), - 'marketing' => - array ( - ), - 'markets' => - array ( - ), - 'marriott' => - array ( - ), - 'marshalls' => - array ( - ), - 'maserati' => - array ( - ), - 'mattel' => - array ( - ), - 'mba' => - array ( - ), - 'mcd' => - array ( - ), - 'mcdonalds' => - array ( - ), - 'mckinsey' => - array ( - ), - 'med' => - array ( - ), - 'media' => - array ( - ), - 'meet' => - array ( - ), - 'melbourne' => - array ( - ), - 'meme' => - array ( - ), - 'memorial' => - array ( - ), - 'men' => - array ( - ), - 'menu' => - array ( - ), - 'meo' => - array ( - ), - 'metlife' => - array ( - ), - 'miami' => - array ( - ), - 'microsoft' => - array ( - ), - 'mini' => - array ( - ), - 'mint' => - array ( - ), - 'mit' => - array ( - ), - 'mitsubishi' => - array ( - ), - 'mlb' => - array ( - ), - 'mls' => - array ( - ), - 'mma' => - array ( - ), - 'mnet' => - array ( - ), - 'mobily' => - array ( - ), - 'moda' => - array ( - ), - 'moe' => - array ( - ), - 'moi' => - array ( - ), - 'mom' => - array ( - ), - 'monash' => - array ( - ), - 'money' => - array ( - ), - 'monster' => - array ( - ), - 'montblanc' => - array ( - ), - 'mopar' => - array ( - ), - 'mormon' => - array ( - ), - 'mortgage' => - array ( - ), - 'moscow' => - array ( - ), - 'moto' => - array ( - ), - 'motorcycles' => - array ( - ), - 'mov' => - array ( - ), - 'movie' => - array ( - ), - 'movistar' => - array ( - ), - 'msd' => - array ( - ), - 'mtn' => - array ( - ), - 'mtpc' => - array ( - ), - 'mtr' => - array ( - ), - 'multichoice' => - array ( - ), - 'mutual' => - array ( - ), - 'mutuelle' => - array ( - ), - 'mzansimagic' => - array ( - ), - 'nab' => - array ( - ), - 'nadex' => - array ( - ), - 'nagoya' => - array ( - ), - 'naspers' => - array ( - ), - 'nationwide' => - array ( - ), - 'natura' => - array ( - ), - 'navy' => - array ( - ), - 'nba' => - array ( - ), - 'nec' => - array ( - ), - 'netbank' => - array ( - ), - 'netflix' => - array ( - ), - 'network' => - array ( - ), - 'neustar' => - array ( - ), - 'new' => - array ( - ), - 'newholland' => - array ( - ), - 'news' => - array ( - ), - 'next' => - array ( - ), - 'nextdirect' => - array ( - ), - 'nexus' => - array ( - ), - 'nfl' => - array ( - ), - 'ngo' => - array ( - ), - 'nhk' => - array ( - ), - 'nico' => - array ( - ), - 'nike' => - array ( - ), - 'nikon' => - array ( - ), - 'ninja' => - array ( - ), - 'nissan' => - array ( - ), - 'nissay' => - array ( - ), - 'nokia' => - array ( - ), - 'northwesternmutual' => - array ( - ), - 'norton' => - array ( - ), - 'now' => - array ( - ), - 'nowruz' => - array ( - ), - 'nowtv' => - array ( - ), - 'nra' => - array ( - ), - 'nrw' => - array ( - ), - 'ntt' => - array ( - ), - 'nyc' => - array ( - ), - 'obi' => - array ( - ), - 'observer' => - array ( - ), - 'off' => - array ( - ), - 'office' => - array ( - ), - 'okinawa' => - array ( - ), - 'olayan' => - array ( - ), - 'olayangroup' => - array ( - ), - 'oldnavy' => - array ( - ), - 'ollo' => - array ( - ), - 'omega' => - array ( - ), - 'one' => - array ( - ), - 'ong' => - array ( - ), - 'onl' => - array ( - ), - 'online' => - array ( - ), - 'onyourside' => - array ( - ), - 'ooo' => - array ( - ), - 'open' => - array ( - ), - 'oracle' => - array ( - ), - 'orange' => - array ( - ), - 'organic' => - array ( - ), - 'orientexpress' => - array ( - ), - 'origins' => - array ( - ), - 'osaka' => - array ( - ), - 'otsuka' => - array ( - ), - 'ott' => - array ( - ), - 'ovh' => - array ( - ), - 'page' => - array ( - ), - 'pamperedchef' => - array ( - ), - 'panasonic' => - array ( - ), - 'panerai' => - array ( - ), - 'paris' => - array ( - ), - 'pars' => - array ( - ), - 'partners' => - array ( - ), - 'parts' => - array ( - ), - 'party' => - array ( - ), - 'passagens' => - array ( - ), - 'pay' => - array ( - ), - 'payu' => - array ( - ), - 'pccw' => - array ( - ), - 'pet' => - array ( - ), - 'pfizer' => - array ( - ), - 'pharmacy' => - array ( - ), - 'philips' => - array ( - ), - 'photo' => - array ( - ), - 'photography' => - array ( - ), - 'photos' => - array ( - ), - 'physio' => - array ( - ), - 'piaget' => - array ( - ), - 'pics' => - array ( - ), - 'pictet' => - array ( - ), - 'pictures' => - array ( - ), - 'pid' => - array ( - ), - 'pin' => - array ( - ), - 'ping' => - array ( - ), - 'pink' => - array ( - ), - 'pioneer' => - array ( - ), - 'pizza' => - array ( - ), - 'place' => - array ( - ), - 'play' => - array ( - ), - 'playstation' => - array ( - ), - 'plumbing' => - array ( - ), - 'plus' => - array ( - ), - 'pnc' => - array ( - ), - 'pohl' => - array ( - ), - 'poker' => - array ( - ), - 'politie' => - array ( - ), - 'porn' => - array ( - ), - 'pramerica' => - array ( - ), - 'praxi' => - array ( - ), - 'press' => - array ( - ), - 'prime' => - array ( - ), - 'prod' => - array ( - ), - 'productions' => - array ( - ), - 'prof' => - array ( - ), - 'progressive' => - array ( - ), - 'promo' => - array ( - ), - 'properties' => - array ( - ), - 'property' => - array ( - ), - 'protection' => - array ( - ), - 'pru' => - array ( - ), - 'prudential' => - array ( - ), - 'pub' => - array ( - ), - 'pwc' => - array ( - ), - 'qpon' => - array ( - ), - 'quebec' => - array ( - ), - 'quest' => - array ( - ), - 'qvc' => - array ( - ), - 'racing' => - array ( - ), - 'raid' => - array ( - ), - 'read' => - array ( - ), - 'realestate' => - array ( - ), - 'realtor' => - array ( - ), - 'realty' => - array ( - ), - 'recipes' => - array ( - ), - 'red' => - array ( - ), - 'redstone' => - array ( - ), - 'redumbrella' => - array ( - ), - 'rehab' => - array ( - ), - 'reise' => - array ( - ), - 'reisen' => - array ( - ), - 'reit' => - array ( - ), - 'reliance' => - array ( - ), - 'ren' => - array ( - ), - 'rent' => - array ( - ), - 'rentals' => - array ( - ), - 'repair' => - array ( - ), - 'report' => - array ( - ), - 'republican' => - array ( - ), - 'rest' => - array ( - ), - 'restaurant' => - array ( - ), - 'review' => - array ( - ), - 'reviews' => - array ( - ), - 'rexroth' => - array ( - ), - 'rich' => - array ( - ), - 'richardli' => - array ( - ), - 'ricoh' => - array ( - ), - 'rightathome' => - array ( - ), - 'ril' => - array ( - ), - 'rio' => - array ( - ), - 'rip' => - array ( - ), - 'rmit' => - array ( - ), - 'rocher' => - array ( - ), - 'rocks' => - array ( - ), - 'rodeo' => - array ( - ), - 'rogers' => - array ( - ), - 'room' => - array ( - ), - 'rsvp' => - array ( - ), - 'ruhr' => - array ( - ), - 'run' => - array ( - ), - 'rwe' => - array ( - ), - 'ryukyu' => - array ( - ), - 'saarland' => - array ( - ), - 'safe' => - array ( - ), - 'safety' => - array ( - ), - 'sakura' => - array ( - ), - 'sale' => - array ( - ), - 'salon' => - array ( - ), - 'samsclub' => - array ( - ), - 'samsung' => - array ( - ), - 'sandvik' => - array ( - ), - 'sandvikcoromant' => - array ( - ), - 'sanofi' => - array ( - ), - 'sap' => - array ( - ), - 'sapo' => - array ( - ), - 'sarl' => - array ( - ), - 'sas' => - array ( - ), - 'save' => - array ( - ), - 'saxo' => - array ( - ), - 'sbi' => - array ( - ), - 'sbs' => - array ( - ), - 'sca' => - array ( - ), - 'scb' => - array ( - ), - 'schaeffler' => - array ( - ), - 'schmidt' => - array ( - ), - 'scholarships' => - array ( - ), - 'school' => - array ( - ), - 'schule' => - array ( - ), - 'schwarz' => - array ( - ), - 'science' => - array ( - ), - 'scjohnson' => - array ( - ), - 'scor' => - array ( - ), - 'scot' => - array ( - ), - 'seat' => - array ( - ), - 'secure' => - array ( - ), - 'security' => - array ( - ), - 'seek' => - array ( - ), - 'select' => - array ( - ), - 'sener' => - array ( - ), - 'services' => - array ( - ), - 'ses' => - array ( - ), - 'seven' => - array ( - ), - 'sew' => - array ( - ), - 'sex' => - array ( - ), - 'sexy' => - array ( - ), - 'sfr' => - array ( - ), - 'shangrila' => - array ( - ), - 'sharp' => - array ( - ), - 'shaw' => - array ( - ), - 'shell' => - array ( - ), - 'shia' => - array ( - ), - 'shiksha' => - array ( - ), - 'shoes' => - array ( - ), - 'shouji' => - array ( - ), - 'show' => - array ( - ), - 'showtime' => - array ( - ), - 'shriram' => - array ( - ), - 'silk' => - array ( - ), - 'sina' => - array ( - ), - 'singles' => - array ( - ), - 'site' => - array ( - ), - 'ski' => - array ( - ), - 'skin' => - array ( - ), - 'sky' => - array ( - ), - 'skype' => - array ( - ), - 'sling' => - array ( - ), - 'smart' => - array ( - ), - 'smile' => - array ( - ), - 'sncf' => - array ( - ), - 'soccer' => - array ( - ), - 'social' => - array ( - ), - 'softbank' => - array ( - ), - 'software' => - array ( - ), - 'sohu' => - array ( - ), - 'solar' => - array ( - ), - 'solutions' => - array ( - ), - 'song' => - array ( - ), - 'sony' => - array ( - ), - 'soy' => - array ( - ), - 'space' => - array ( - ), - 'spiegel' => - array ( - ), - 'spot' => - array ( - ), - 'spreadbetting' => - array ( - ), - 'srl' => - array ( - ), - 'srt' => - array ( - ), - 'stada' => - array ( - ), - 'staples' => - array ( - ), - 'star' => - array ( - ), - 'starhub' => - array ( - ), - 'statebank' => - array ( - ), - 'statefarm' => - array ( - ), - 'statoil' => - array ( - ), - 'stc' => - array ( - ), - 'stcgroup' => - array ( - ), - 'stockholm' => - array ( - ), - 'storage' => - array ( - ), - 'store' => - array ( - ), - 'studio' => - array ( - ), - 'study' => - array ( - ), - 'style' => - array ( - ), - 'sucks' => - array ( - ), - 'supersport' => - array ( - ), - 'supplies' => - array ( - ), - 'supply' => - array ( - ), - 'support' => - array ( - ), - 'surf' => - array ( - ), - 'surgery' => - array ( - ), - 'suzuki' => - array ( - ), - 'swatch' => - array ( - ), - 'swiftcover' => - array ( - ), - 'swiss' => - array ( - ), - 'sydney' => - array ( - ), - 'symantec' => - array ( - ), - 'systems' => - array ( - ), - 'tab' => - array ( - ), - 'taipei' => - array ( - ), - 'talk' => - array ( - ), - 'taobao' => - array ( - ), - 'target' => - array ( - ), - 'tatamotors' => - array ( - ), - 'tatar' => - array ( - ), - 'tattoo' => - array ( - ), - 'tax' => - array ( - ), - 'taxi' => - array ( - ), - 'tci' => - array ( - ), - 'tdk' => - array ( - ), - 'team' => - array ( - ), - 'tech' => - array ( - ), - 'technology' => - array ( - ), - 'telecity' => - array ( - ), - 'telefonica' => - array ( - ), - 'temasek' => - array ( - ), - 'tennis' => - array ( - ), - 'teva' => - array ( - ), - 'thd' => - array ( - ), - 'theater' => - array ( - ), - 'theatre' => - array ( - ), - 'theguardian' => - array ( - ), - 'tiaa' => - array ( - ), - 'tickets' => - array ( - ), - 'tienda' => - array ( - ), - 'tiffany' => - array ( - ), - 'tips' => - array ( - ), - 'tires' => - array ( - ), - 'tirol' => - array ( - ), - 'tjmaxx' => - array ( - ), - 'tjx' => - array ( - ), - 'tkmaxx' => - array ( - ), - 'tmall' => - array ( - ), - 'today' => - array ( - ), - 'tokyo' => - array ( - ), - 'tools' => - array ( - ), - 'top' => - array ( - ), - 'toray' => - array ( - ), - 'toshiba' => - array ( - ), - 'total' => - array ( - ), - 'tours' => - array ( - ), - 'town' => - array ( - ), - 'toyota' => - array ( - ), - 'toys' => - array ( - ), - 'trade' => - array ( - ), - 'trading' => - array ( - ), - 'training' => - array ( - ), - 'travelchannel' => - array ( - ), - 'travelers' => - array ( - ), - 'travelersinsurance' => - array ( - ), - 'trust' => - array ( - ), - 'trv' => - array ( - ), - 'tube' => - array ( - ), - 'tui' => - array ( - ), - 'tunes' => - array ( - ), - 'tushu' => - array ( - ), - 'tvs' => - array ( - ), - 'ubank' => - array ( - ), - 'ubs' => - array ( - ), - 'uconnect' => - array ( - ), - 'unicom' => - array ( - ), - 'university' => - array ( - ), - 'uno' => - array ( - ), - 'uol' => - array ( - ), - 'ups' => - array ( - ), - 'vacations' => - array ( - ), - 'vana' => - array ( - ), - 'vanguard' => - array ( - ), - 'vegas' => - array ( - ), - 'ventures' => - array ( - ), - 'verisign' => - array ( - ), - 'versicherung' => - array ( - ), - 'vet' => - array ( - ), - 'viajes' => - array ( - ), - 'video' => - array ( - ), - 'vig' => - array ( - ), - 'viking' => - array ( - ), - 'villas' => - array ( - ), - 'vin' => - array ( - ), - 'vip' => - array ( - ), - 'virgin' => - array ( - ), - 'visa' => - array ( - ), - 'vision' => - array ( - ), - 'vista' => - array ( - ), - 'vistaprint' => - array ( - ), - 'viva' => - array ( - ), - 'vivo' => - array ( - ), - 'vlaanderen' => - array ( - ), - 'vodka' => - array ( - ), - 'volkswagen' => - array ( - ), - 'volvo' => - array ( - ), - 'vote' => - array ( - ), - 'voting' => - array ( - ), - 'voto' => - array ( - ), - 'voyage' => - array ( - ), - 'vuelos' => - array ( - ), - 'wales' => - array ( - ), - 'walmart' => - array ( - ), - 'walter' => - array ( - ), - 'wang' => - array ( - ), - 'wanggou' => - array ( - ), - 'warman' => - array ( - ), - 'watch' => - array ( - ), - 'watches' => - array ( - ), - 'weather' => - array ( - ), - 'weatherchannel' => - array ( - ), - 'webcam' => - array ( - ), - 'weber' => - array ( - ), - 'website' => - array ( - ), - 'wed' => - array ( - ), - 'wedding' => - array ( - ), - 'weibo' => - array ( - ), - 'weir' => - array ( - ), - 'whoswho' => - array ( - ), - 'wien' => - array ( - ), - 'wiki' => - array ( - ), - 'williamhill' => - array ( - ), - 'win' => - array ( - ), - 'windows' => - array ( - ), - 'wine' => - array ( - ), - 'winners' => - array ( - ), - 'wme' => - array ( - ), - 'wolterskluwer' => - array ( - ), - 'woodside' => - array ( - ), - 'work' => - array ( - ), - 'works' => - array ( - ), - 'world' => - array ( - ), - 'wow' => - array ( - ), - 'wtc' => - array ( - ), - 'wtf' => - array ( - ), - 'xbox' => - array ( - ), - 'xerox' => - array ( - ), - 'xfinity' => - array ( - ), - 'xihuan' => - array ( - ), - 'xin' => - array ( - ), - 'xn--11b4c3d' => - array ( - ), - 'xn--1ck2e1b' => - array ( - ), - 'xn--1qqw23a' => - array ( - ), - 'xn--30rr7y' => - array ( - ), - 'xn--3bst00m' => - array ( - ), - 'xn--3ds443g' => - array ( - ), - 'xn--3oq18vl8pn36a' => - array ( - ), - 'xn--3pxu8k' => - array ( - ), - 'xn--42c2d9a' => - array ( - ), - 'xn--45q11c' => - array ( - ), - 'xn--4gbrim' => - array ( - ), - 'xn--4gq48lf9j' => - array ( - ), - 'xn--55qw42g' => - array ( - ), - 'xn--55qx5d' => - array ( - ), - 'xn--5su34j936bgsg' => - array ( - ), - 'xn--5tzm5g' => - array ( - ), - 'xn--6frz82g' => - array ( - ), - 'xn--6qq986b3xl' => - array ( - ), - 'xn--80adxhks' => - array ( - ), - 'xn--80aqecdr1a' => - array ( - ), - 'xn--80asehdb' => - array ( - ), - 'xn--80aswg' => - array ( - ), - 'xn--8y0a063a' => - array ( - ), - 'xn--9dbq2a' => - array ( - ), - 'xn--9et52u' => - array ( - ), - 'xn--9krt00a' => - array ( - ), - 'xn--b4w605ferd' => - array ( - ), - 'xn--bck1b9a5dre4c' => - array ( - ), - 'xn--c1avg' => - array ( - ), - 'xn--c2br7g' => - array ( - ), - 'xn--cck2b3b' => - array ( - ), - 'xn--cg4bki' => - array ( - ), - 'xn--czr694b' => - array ( - ), - 'xn--czrs0t' => - array ( - ), - 'xn--czru2d' => - array ( - ), - 'xn--d1acj3b' => - array ( - ), - 'xn--eckvdtc9d' => - array ( - ), - 'xn--efvy88h' => - array ( - ), - 'xn--estv75g' => - array ( - ), - 'xn--fct429k' => - array ( - ), - 'xn--fhbei' => - array ( - ), - 'xn--fiq228c5hs' => - array ( - ), - 'xn--fiq64b' => - array ( - ), - 'xn--fjq720a' => - array ( - ), - 'xn--flw351e' => - array ( - ), - 'xn--fzys8d69uvgm' => - array ( - ), - 'xn--g2xx48c' => - array ( - ), - 'xn--gckr3f0f' => - array ( - ), - 'xn--gk3at1e' => - array ( - ), - 'xn--hxt814e' => - array ( - ), - 'xn--i1b6b1a6a2e' => - array ( - ), - 'xn--imr513n' => - array ( - ), - 'xn--io0a7i' => - array ( - ), - 'xn--j1aef' => - array ( - ), - 'xn--jlq61u9w7b' => - array ( - ), - 'xn--jvr189m' => - array ( - ), - 'xn--kcrx77d1x4a' => - array ( - ), - 'xn--kpu716f' => - array ( - ), - 'xn--kput3i' => - array ( - ), - 'xn--mgba3a3ejt' => - array ( - ), - 'xn--mgba7c0bbn0a' => - array ( - ), - 'xn--mgbaakc7dvf' => - array ( - ), - 'xn--mgbab2bd' => - array ( - ), - 'xn--mgbb9fbpob' => - array ( - ), - 'xn--mgbca7dzdo' => - array ( - ), - 'xn--mgbi4ecexp' => - array ( - ), - 'xn--mgbt3dhd' => - array ( - ), - 'xn--mk1bu44c' => - array ( - ), - 'xn--mxtq1m' => - array ( - ), - 'xn--ngbc5azd' => - array ( - ), - 'xn--ngbe9e0a' => - array ( - ), - 'xn--ngbrx' => - array ( - ), - 'xn--nqv7f' => - array ( - ), - 'xn--nqv7fs00ema' => - array ( - ), - 'xn--nyqy26a' => - array ( - ), - 'xn--p1acf' => - array ( - ), - 'xn--pbt977c' => - array ( - ), - 'xn--pssy2u' => - array ( - ), - 'xn--q9jyb4c' => - array ( - ), - 'xn--qcka1pmc' => - array ( - ), - 'xn--rhqv96g' => - array ( - ), - 'xn--rovu88b' => - array ( - ), - 'xn--ses554g' => - array ( - ), - 'xn--t60b56a' => - array ( - ), - 'xn--tckwe' => - array ( - ), - 'xn--tiq49xqyj' => - array ( - ), - 'xn--unup4y' => - array ( - ), - 'xn--vermgensberater-ctb' => - array ( - ), - 'xn--vermgensberatung-pwb' => - array ( - ), - 'xn--vhquv' => - array ( - ), - 'xn--vuq861b' => - array ( - ), - 'xn--w4r85el8fhu5dnra' => - array ( - ), - 'xn--w4rs40l' => - array ( - ), - 'xn--xhq521b' => - array ( - ), - 'xn--zfr164b' => - array ( - ), - 'xperia' => - array ( - ), - 'xyz' => - array ( - ), - 'yachts' => - array ( - ), - 'yahoo' => - array ( - ), - 'yamaxun' => - array ( - ), - 'yandex' => - array ( - ), - 'yodobashi' => - array ( - ), - 'yoga' => - array ( - ), - 'yokohama' => - array ( - ), - 'you' => - array ( - ), - 'youtube' => - array ( - ), - 'yun' => - array ( - ), - 'zappos' => - array ( - ), - 'zara' => - array ( - ), - 'zero' => - array ( - ), - 'zip' => - array ( - ), - 'zippo' => - array ( - ), - 'zone' => - array ( - ), - 'zuerich' => - array ( - ), -); \ No newline at end of file diff --git a/example.php b/example.php deleted file mode 100644 index d8fdce00..00000000 --- a/example.php +++ /dev/null @@ -1,45 +0,0 @@ -getList()); - -// Parse a URL -$url = $parser->parseUrl('http://user:pass@www.pref.okinawa.jp:8080/path/to/page.html?query=string#fragment'); - -// Accessing elements of the URL -var_dump($url); -var_dump($url->__toString()); -var_dump($url->getPath()); -var_dump($url->getFragment()); - -// Getting the Host object from the URL -$host = $url->getHost(); - -// Accessing elements of the Host -var_dump($host); -var_dump($host->__toString()); -var_dump($host->getSubdomain()); -var_dump($host->getRegistrableDomain()); -var_dump($host->getPublicSuffix()); - -// It's possible to parse a host only, if you prefer -$host = $parser->parseHost('a.b.c.cy'); - -// Accessing elements of the Host -var_dump($host); -var_dump($host->__toString()); -var_dump($host->getSubdomain()); -var_dump($host->getRegistrableDomain()); -var_dump($host->getPublicSuffix()); - -// If you just need to know subdomain/registrable domain/public suffix info -// about a host, there are public methods available for that in the Parser -var_dump($parser->getSubdomain('www.scottwills.co.uk')); -var_dump($parser->getRegistrableDomain('www.scottwills.co.uk')); -var_dump($parser->getPublicSuffix('www.scottwills.co.uk')); diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..19ea5e3e --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,19 @@ +includes: + - vendor/phpstan/phpstan-strict-rules/rules.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon +parameters: + level: max + paths: + - src + ignoreErrors: + - message: '#has no value type specified in iterable type array.#' + path: src/Rules.php + - message: '#has parameter \$(properties|rules|list|tmpList) with no value type specified in iterable type array.#' + path: src/Rules.php + - message: "#Cannot access offset '!' on mixed.#" + path: src/Rules.php + - message: '#Variable \$line on left side of \?\? always exists and is not nullable.#' + path: src/Rules.php + - '#^Parameter \#1 \$callback of function set_error_handler expects#' + reportUnmatchedIgnoredErrors: true diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6f91249b..2403d4e9 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,29 +1,26 @@ - - - - tests/src + + + + + + + + + + + src - - - - ./src - - - - - - - - + + + + + + + src + + + src + + diff --git a/src/CannotProcessHost.php b/src/CannotProcessHost.php new file mode 100644 index 00000000..27e4146f --- /dev/null +++ b/src/CannotProcessHost.php @@ -0,0 +1,11 @@ +registeredName->value(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + throw SyntaxError::dueToUnsupportedType($this->registeredName->toString()); + } + } + + /** + * @param array{registeredName: RegisteredName} $properties + */ + public static function __set_state(array $properties): self + { + return new self($properties['registeredName']); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIDNA2003(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + return new self(RegisteredName::fromIDNA2003($domain)); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIDNA2008(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + return new self(RegisteredName::fromIDNA2008($domain)); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + yield from $this->registeredName; + } + + public function isAscii(): bool + { + return $this->registeredName->isAscii(); + } + + public function jsonSerialize(): ?string + { + return $this->registeredName->jsonSerialize(); + } + + public function count(): int + { + return count($this->registeredName); + } + + public function value(): ?string + { + return $this->registeredName->value(); + } + + public function toString(): string + { + return $this->registeredName->toString(); + } + + public function label(int $key): ?string + { + return $this->registeredName->label($key); + } + + /** + * @return list + */ + public function keys(?string $label = null): array + { + return $this->registeredName->keys($label); + } + + /** + * @return list + */ + public function labels(): array + { + return $this->registeredName->labels(); + } + + private function newInstance(RegisteredName $registeredName): self + { + if ($registeredName->value() === $this->registeredName->value()) { + return $this; + } + + return new self($registeredName); + } + + public function toAscii(): self + { + return $this->newInstance($this->registeredName->toAscii()); + } + + public function toUnicode(): self + { + return $this->newInstance($this->registeredName->toUnicode()); + } + + /** + * @throws CannotProcessHost + */ + public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self + { + return $this->newInstance($this->registeredName->prepend($label)); + } + + /** + * @throws CannotProcessHost + */ + public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self + { + return $this->newInstance($this->registeredName->append($label)); + } + + public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self + { + return $this->newInstance($this->registeredName->withLabel($key, $label)); + } + + public function withoutLabel(int ...$keys): self + { + return $this->newInstance($this->registeredName->withoutLabel(...$keys)); + } + + /** + * @throws CannotProcessHost + */ + public function clear(): self + { + return $this->newInstance($this->registeredName->clear()); + } + + /** + * @throws CannotProcessHost + */ + public function slice(int $offset, ?int $length = null): self + { + return $this->newInstance($this->registeredName->slice($offset, $length)); + } + + public function withRootLabel(): self + { + if ('' === $this->label(0)) { + return $this; + } + + return $this->append(''); + } + + public function withoutRootLabel(): self + { + if ('' === $this->label(0)) { + return $this->slice(1); + } + + return $this; + } + + public function isAbsolute(): bool + { + return '' === $this->label(0); + } + + /** + * Apply the callback if the given "condition" is (or resolves to) true. + * + * @param (callable($this): bool)|bool $condition + * @param callable($this): (self|null) $onSuccess + * @param ?callable($this): (self|null) $onFail + * + */ + public function when(callable|bool $condition, callable $onSuccess, ?callable $onFail = null): self + { + if (!is_bool($condition)) { + $condition = $condition($this); + } + + return match (true) { + $condition => $onSuccess($this), + null !== $onFail => $onFail($this), + default => $this, + } ?? $this; + } +} diff --git a/src/DomainName.php b/src/DomainName.php new file mode 100644 index 00000000..fd6e3b91 --- /dev/null +++ b/src/DomainName.php @@ -0,0 +1,123 @@ + + */ +interface DomainName extends Host, IteratorAggregate +{ + /** + * Tells whether the current domain is in its ascii form. + */ + public function isAscii(): bool; + + /** + * Retrieves a single domain label. + * + * If $key is non-negative, the returned value will be the label at $key position from the start. + * If $key is negative, the returned value will be the label at $key position from the end. + * + * If no label is found the submitted $key the returned value will be null. + * + * @param int $key the label offset + */ + public function label(int $key): ?string; + + /** + * Returns the object labels. + * + * @return list + */ + public function labels(): array; + + /** + * Returns the associated key for each label. + * + * If a value is specified only the keys associated with + * the given value will be returned + * + * @return list + */ + public function keys(?string $label = null): array; + + /** + * The external iterator iterates over the DomainInterface labels + * from the right-most label to the left-most label. + * + * @return Iterator + */ + public function getIterator(): Iterator; + + /** + * Prepends a label to the domain. + * + * @see ::withLabel + */ + public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self; + + /** + * Appends a label to the domain. + * + * @see ::withLabel + */ + public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self; + + /** + * Returns an instance with the specified label added at the specified key. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the new label + * + * If $key is non-negative, the added label will be the label at $key position from the start. + * If $key is negative, the added label will be the label at $key position from the end. + * + * @param DomainNameProvider|Host|Stringable|string|int|null $label a domain label + * + * @throws CannotProcessHost If the key is out of bounds + * @throws CannotProcessHost If the label is converted to the NULL value + */ + public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self; + + /** + * Returns an instance with the label at the specified key removed. + * + * This method MUST retain the state of the current instance, and return + * an instance without the specified label + * + * If $key is non-negative, the removed label will be the label at $key position from the start. + * If $key is negative, the removed label will be the label at $key position from the end. + * + * + * @throws CannotProcessHost If the key is out of bounds + */ + public function withoutLabel(int ...$keys): self; + + /** + * Returns an instance with all labels removed. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains no label + */ + public function clear(): self; + + /** + * Extracts a slice of $length elements starting at position $offset from the Collection. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the selected slice. + * + * If $length is null it returns all elements from $offset to the end of the Domain. + */ + public function slice(int $offset, ?int $length = null): self; +} diff --git a/src/DomainNameProvider.php b/src/DomainNameProvider.php new file mode 100644 index 00000000..efc7cb91 --- /dev/null +++ b/src/DomainNameProvider.php @@ -0,0 +1,10 @@ +expectException(SyntaxError::class); + + Domain::fromIDNA2008($domain); + } + + /** + * @return iterable + */ + public static function invalidDomainProvider(): iterable + { + return [ + 'invalid IDN domain' => ['a⒈com'], + 'invalid IDN domain full size' => ['%00.com'], + 'invalid IDN domain full size rawurlencode ' => ['%ef%bc%85%ef%bc%94%ef%bc%91.com'], + ]; + } + + public function testToUnicodeNeverThrowsException(): void + { + self::assertSame( + 'xn--a-ecp.ru', + Domain::fromIDNA2008('xN--a-eCp.rU')->toUnicode()->toString() + ); + } + + public function testDomainInternalPhpMethod(): void + { + $domain = Domain::fromIDNA2008('www.ulb.ac.be'); + /** @var Domain $generateDomain */ + $generateDomain = eval('return '.var_export($domain, true).';'); + self::assertEquals($domain, $generateDomain); + self::assertSame(['be', 'ac', 'ulb', 'www'], [...$domain]); + self::assertEquals('"www.ulb.ac.be"', json_encode($domain)); + self::assertSame('www.ulb.ac.be', $domain->toString()); + } + + /** + * @param array $labels + */ + #[DataProvider('countableProvider')] + public function testCountable(?string $domain, int $nbLabels, array $labels): void + { + $domain = Domain::fromIDNA2008($domain); + self::assertCount($nbLabels, $domain); + self::assertSame($labels, [...$domain]); + } + + /** + * @return iterable}> + */ + public static function countableProvider(): iterable + { + return [ + 'null' => [null, 0, []], + 'empty string' => ['', 1, ['']], + 'simple' => ['foo.bar.baz', 3, ['baz', 'bar', 'foo']], + 'unicode' => ['www.食狮.公司.cn', 4, ['cn', '公司', '食狮', 'www']], + ]; + } + + public function testGetLabel(): void + { + $domain = Domain::fromIDNA2008('master.example.com'); + + self::assertSame('com', $domain->label(0)); + self::assertSame('example', $domain->label(1)); + self::assertSame('master', $domain->label(-1)); + self::assertNull($domain->label(23)); + self::assertNull($domain->label(-23)); + } + + public function testOffsets(): void + { + $domain = Domain::fromIDNA2008('master.com.example.com'); + + self::assertSame([0, 2], $domain->keys('com')); + self::assertSame([], $domain->keys('toto')); + self::assertSame([0, 1, 2, 3], $domain->keys()); + } + + public function testLabels(): void + { + self::assertSame([ + 'com', + 'example', + 'com', + 'master', + ], Domain::fromIDNA2008('master.com.example.com')->labels()); + + self::assertSame([], Domain::fromIDNA2008(null)->labels()); + } + + #[DataProvider('toUnicodeProvider')] + public function testToIDN( + ?string $domain, + ?string $expectedDomain, + ?string $expectedIDNDomain + ): void { + $domain = Domain::fromIDNA2008($domain); + self::assertSame($expectedDomain, $domain->value()); + + /** @var Domain $domainIDN */ + $domainIDN = $domain->toUnicode(); + self::assertSame($expectedIDNDomain, $domainIDN->value()); + } + + /** + * @return iterable + */ + public static function toUnicodeProvider(): iterable + { + return [ + 'simple domain' => [ + 'domain' => 'www.ulb.ac.be', + 'expectedDomain' => 'www.ulb.ac.be', + 'expectedIDNDomain' => 'www.ulb.ac.be', + ], + 'ASCII to IDN domain' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNDomain' => 'www.食狮.公司.cn', + ], + 'IDN to IDN domain' => [ + 'domain' => 'www.食狮.公司.cn', + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedIDNDomain' => 'www.食狮.公司.cn', + ], + 'empty string domain and null suffix' => [ + 'domain' => '', + 'expectedDomain' => '', + 'expectedIDNDomain' => '', + ], + 'null domain and suffix' => [ + 'domain' => null, + 'expectedDomain' => null, + 'expectedIDNDomain' => null, + ], + 'domain with null suffix' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNDomain' => 'www.食狮.公司.cn', + ], + 'domain with URLencoded data' => [ + 'domain' => 'b%C3%A9b%C3%A9.be', + 'expectedDomain' => 'bébé.be', + 'expectedIDNDomain' => 'bébé.be', + ], + ]; + } + + #[DataProvider('toAsciiProvider')] + public function testToAscii( + ?string $domain, + ?string $expectedDomain, + ?string $expectedIDNDomain + ): void { + $domain = Domain::fromIDNA2008($domain); + self::assertSame($expectedDomain, $domain->value()); + + /** @var Domain $domainIDN */ + $domainIDN = $domain->toAscii(); + self::assertSame($expectedIDNDomain, $domainIDN->value()); + } + + /** + * @return iterable + */ + public static function toAsciiProvider(): iterable + { + return [ + 'simple domain' => [ + 'domain' => 'www.ulb.ac.be', + 'expectedDomain' => 'www.ulb.ac.be', + 'expectedIDNDomain' => 'www.ulb.ac.be', + ], + 'ASCII to ASCII domain' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + ], + 'ASCII to IDN domain' => [ + 'domain' => 'www.食狮.公司.cn', + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + ], + 'null domain and suffix' => [ + 'domain' => null, + 'expectedDomain' => null, + 'expectedIDNDomain' => null, + ], + 'domain with null suffix' => [ + 'domain' => 'www.食狮.公司.cn', + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + ], + ]; + } + + #[DataProvider('withLabelWorksProvider')] + public function testWithLabelWorks(DomainName $domain, int $key, string $label, ?string $expected): void + { + $result = $domain->withLabel($key, $label); + self::assertSame($expected, $result->value()); + } + + /** + * @return iterable + */ + public static function withLabelWorksProvider(): iterable + { + $base_domain = Domain::fromIDNA2008('www.example.com'); + + return [ + 'null domain' => [ + 'domain' => Domain::fromIDNA2008(null), + 'key' => 0, + 'label' => 'localhost', + 'expected' => 'localhost', + ], + 'simple replace positive offset' => [ + 'domain' => $base_domain, + 'key' => 2, + 'label' => 'shop', + 'expected' => 'shop.example.com', + ], + 'simple replace negative offset' => [ + 'domain' => $base_domain, + 'key' => -1, + 'label' => 'shop', + 'expected' => 'shop.example.com', + ], + 'simple addition positive offset' => [ + 'domain' => $base_domain, + 'key' => 3, + 'label' => 'shop', + 'expected' => 'shop.www.example.com', + ], + 'simple addition negative offset' => [ + 'domain' => $base_domain, + 'key' => -4, + 'label' => 'shop', + 'expected' => 'www.example.com.shop', + ], + 'simple replace remove PSL info' => [ + 'domain' => $base_domain, + 'key' => 0, + 'label' => 'fr', + 'expected' => 'www.example.fr', + ], + 'replace without any change' => [ + 'domain' => $base_domain, + 'key' => 2, + 'label' => 'www', + 'expected' => 'www.example.com', + ], + 'simple update IDN (1)' => [ + 'domain' => $base_domain, + 'key' => 2, + 'label' => 'рф', + 'expected' => 'xn--p1ai.example.com', + ], + 'simple update IDN (2)' => [ + 'domain' => Domain::fromIDNA2008('www.bébé.be'), + 'key' => 2, + 'label' => 'xn--p1ai', + 'expected' => 'рф.bébé.be', + ], + 'replace a domain with multiple label' => [ + 'domain' => $base_domain, + 'key' => -1, + 'label' => 'www.shop', + 'expected' => 'www.shop.example.com', + ], + ]; + } + + public function testWithLabelFailsWithInvalidKey(): void + { + $this->expectException(SyntaxError::class); + Domain::fromIDNA2008('example.com')->withLabel(-4, 'www'); + } + + public function testWithLabelFailsWithInvalidLabel2(): void + { + $this->expectException(SyntaxError::class); + + Domain::fromIDNA2008('example.com')->withLabel(-1, ''); + } + + #[DataProvider('validAppend')] + public function testAppend(string $raw, string $append, string $expected): void + { + self::assertSame($expected, Domain::fromIDNA2008($raw)->append($append)->toString()); + } + + /** + * @return iterable + */ + public static function validAppend(): iterable + { + return [ + ['secure.example.com', '8.8.8.8', 'secure.example.com.8.8.8.8'], + ['secure.example.com', 'master', 'secure.example.com.master'], + ['secure.example.com', 'master.', 'secure.example.com.master.'], + ['example.com', '', 'example.com.'], + ]; + } + + #[DataProvider('validPrepend')] + public function testPrepend(string $raw, string $prepend, string $expected): void + { + self::assertSame($expected, Domain::fromIDNA2008($raw)->prepend($prepend)->toString()); + } + + /** + * @return iterable + */ + public static function validPrepend(): iterable + { + return [ + ['secure.example.com', 'master', 'master.secure.example.com'], + ['secure.example.com', '127.0.0.1', '127.0.0.1.secure.example.com'], + ['secure.example.com.', 'master', 'master.secure.example.com.'], + ]; + } + + #[DataProvider('withoutLabelWorksProvider')] + public function testwithoutLabelWorks(DomainName $domain, int $key, ?string $expected): void + { + $result = $domain->withoutLabel($key); + self::assertSame($expected, $result->value()); + } + + /** + * @return iterable + */ + public static function withoutLabelWorksProvider(): iterable + { + $base_domain = Domain::fromIDNA2008('www.example.com'); + + return [ + 'simple removal positive offset' => [ + 'domain' => $base_domain, + 'key' => 2, + 'expected' => 'example.com', + ], + 'simple removal negative offset' => [ + 'domain' => $base_domain, + 'key' => -1, + 'expected' => 'example.com', + ], + 'simple removal strip PSL info positive offset' => [ + 'domain' => $base_domain, + 'key' => 0, + 'expected' => 'www.example', + ], + 'simple removal strip PSL info negative offset' => [ + 'domain' => $base_domain, + 'key' => -3, + 'expected' => 'www.example', + ], + ]; + } + + public function testwithoutLabelFailsWithInvalidKey(): void + { + $this->expectException(SyntaxError::class); + Domain::fromIDNA2008('example.com')->withoutLabel(-3); + } + + public function testwithoutLabelWorksWithMultipleKeys(): void + { + self::assertNull(Domain::fromIDNA2008('www.example.com')->withoutLabel(0, 1, 2)->value()); + } + + public function testWithoutLabelWorksWithoutArgument(): void + { + $domain = Domain::fromIDNA2008('www.example.com'); + + self::assertSame($domain, $domain->withoutLabel()); + } + + #[DataProvider('resolveCustomIDNAOptionsProvider')] + public function testResolveWorksWithCustomIDNAOptions( + string $domainName, + string $withLabel, + ?string $expectedContent, + ?string $expectedAscii, + ?string $expectedUnicode, + ?string $expectedWithLabel + ): void { + $domain = Domain::fromIDNA2008($domainName); + self::assertSame($expectedContent, $domain->value()); + self::assertSame($expectedAscii, $domain->toAscii()->value()); + self::assertSame($expectedUnicode, $domain->toUnicode()->value()); + self::assertSame($expectedWithLabel, $domain->withLabel(-1, $withLabel)->value()); + } + + /** + * @return iterable> + */ + public static function resolveCustomIDNAOptionsProvider(): iterable + { + return [ + 'without deviation characters' => [ + 'example.com', + 'größe', + 'example.com', + 'example.com', + 'example.com', + 'xn--gre-6ka8i.com', + ], + 'without deviation characters with label' => [ + 'www.example.com', + 'größe', + 'www.example.com', + 'www.example.com', + 'www.example.com', + 'xn--gre-6ka8i.example.com', + ], + 'with deviation in domain' => [ + 'www.faß.de', + 'größe', + 'www.faß.de', + 'www.xn--fa-hia.de', + 'www.faß.de', + 'größe.faß.de', + ], + 'with deviation in label' => [ + 'faß.test.de', + 'größe', + 'faß.test.de', + 'xn--fa-hia.test.de', + 'faß.test.de', + 'größe.test.de', + ], + ]; + } + + public function testWithIDNAOptions(): void + { + self::assertNotEquals(Domain::fromIDNA2003('example.com'), Domain::fromIDNA2008('example.com')); + } + + public function testSlice(): void + { + $domain = Domain::fromIDNA2008('ulb.ac.be'); + + self::assertSame($domain->toString(), $domain->slice(-3)->toString()); + self::assertSame($domain->toString(), $domain->slice(0)->toString()); + + self::assertSame('ulb.ac', $domain->slice(1)->toString()); + self::assertSame('ulb', $domain->slice(-1)->toString()); + self::assertSame('be', $domain->slice(-3, 1)->toString()); + } + + public function testSliceThrowsOnOverFlow(): void + { + $this->expectException(SyntaxError::class); + + Domain::fromIDNA2008('ulb.ac.be')->slice(5); + } +} diff --git a/src/EffectiveTopLevelDomain.php b/src/EffectiveTopLevelDomain.php new file mode 100644 index 00000000..29636cdb --- /dev/null +++ b/src/EffectiveTopLevelDomain.php @@ -0,0 +1,41 @@ + strtolower($domain), 'isTransitionalDifferent' => false, 'errors' => 0]); + } + + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + + /** @var array{result:string, isTransitionalDifferent:bool, errors:int} $idnaInfo */ + $info = IdnaInfo::fromIntl($idnaInfo); + if (0 !== $info->errors()) { + throw SyntaxError::dueToIDNAError($domain, $info); + } + + return $info; + } + + /** + * Converts the input to its IDNA UNICODE form. + * + * This method returns the string converted to IDN UNICODE form + */ + public static function toUnicode(string $domain, int $options): IdnaInfo + { + if (!str_contains($domain, 'xn--')) { + return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => 0]); + } + + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_utf8($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + + /** @var array{result:string, isTransitionalDifferent:bool, errors:int} $idnaInfo */ + $info = IdnaInfo::fromIntl($idnaInfo); + if (0 !== $info->errors()) { + return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => 0]); + } + + return $info; + } +} diff --git a/src/IdnaInfo.php b/src/IdnaInfo.php new file mode 100644 index 00000000..7afd6b24 --- /dev/null +++ b/src/IdnaInfo.php @@ -0,0 +1,93 @@ + 'a non-final domain name label (or the whole domain name) is empty', + Idna::ERROR_LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', + Idna::ERROR_DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', + Idna::ERROR_LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', + Idna::ERROR_TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', + Idna::ERROR_HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', + Idna::ERROR_LEADING_COMBINING_MARK => 'a label starts with a combining mark', + Idna::ERROR_DISALLOWED => 'a label or domain name contains disallowed characters', + Idna::ERROR_PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', + Idna::ERROR_LABEL_HAS_DOT => 'a label contains a dot=full stop', + Idna::ERROR_INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', + Idna::ERROR_BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', + Idna::ERROR_CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', + Idna::ERROR_CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', + Idna::ERROR_CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts', + ]; + + /** @var array */ + public readonly array $errorList; + + private function __construct( + public readonly string $result, + public readonly bool $isTransitionalDifferent, + public readonly int $errors + ) { + $this->errorList = array_filter( + self::ERRORS, + fn (int $error): bool => 0 !== ($error & $this->errors), + ARRAY_FILTER_USE_KEY + ); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $infos + */ + public static function fromIntl(array $infos): self + { + return new self($infos['result'], $infos['isTransitionalDifferent'], $infos['errors']); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $properties + */ + public static function __set_state(array $properties): self + { + return self::fromIntl($properties); + } + + public function result(): string + { + return $this->result; + } + + public function isTransitionalDifferent(): bool + { + return $this->isTransitionalDifferent; + } + + public function errors(): int + { + return $this->errors; + } + + public function error(int $error): ?string + { + return $this->errorList[$error] ?? null; + } + + /** + * @return array + */ + public function errorList(): array + { + return $this->errorList; + } +} diff --git a/src/IdnaInfoTest.php b/src/IdnaInfoTest.php new file mode 100644 index 00000000..1ecd93b0 --- /dev/null +++ b/src/IdnaInfoTest.php @@ -0,0 +1,47 @@ + 'foo.bar', 'isTransitionalDifferent' => false, 'errors' => 0]; + $result = IdnaInfo::fromIntl($infos); + /** @var IdnaInfo $generateResult */ + $generateResult = eval('return '.var_export($result, true).';'); + + self::assertEquals($result, $generateResult); + } + + public function testItCanBeInstantiatedFromArray(): void + { + $infos = ['result' => '', 'isTransitionalDifferent' => false, 'errors' => 0]; + $result = IdnaInfo::fromIntl($infos); + + self::assertSame('', $result->result); + self::assertFalse($result->isTransitionalDifferent); + self::assertSame(0, $result->errors); + self::assertNull($result->error(Idna::ERROR_BIDI)); + self::assertCount(0, $result->errorList); + } + + public function testInvalidSyntaxAfterIDNConversion(): void + { + try { + Idna::toAscii('%00.com', Idna::IDNA2008_ASCII); + } catch (SyntaxError $exception) { + $result = $exception->idnaInfo(); + self::assertInstanceOf(IdnaInfo::class, $result); + self::assertSame(Idna::ERROR_DISALLOWED, $result->errors); + self::assertIsString($result->error(Idna::ERROR_DISALLOWED)); + self::assertCount(1, $result->errorList); + } + } +} diff --git a/src/Pdp/Exception/PdpException.php b/src/Pdp/Exception/PdpException.php deleted file mode 100644 index f6d95eb3..00000000 --- a/src/Pdp/Exception/PdpException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @author Jeremy Kendall - */ -class CurlHttpAdapter implements HttpAdapterInterface -{ - /** - * {@inheritdoc} - */ - public function getContent($url) - { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_URL, $url); - $content = curl_exec($ch); - curl_close($ch); - - return $content; - } -} diff --git a/src/Pdp/HttpAdapter/HttpAdapterInterface.php b/src/Pdp/HttpAdapter/HttpAdapterInterface.php deleted file mode 100644 index e4eb5c0b..00000000 --- a/src/Pdp/HttpAdapter/HttpAdapterInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @author Jeremy Kendall - */ -interface HttpAdapterInterface -{ - /** - * Returns the content fetched from a given URL. - * - * @param string $url - * - * @return string Retrieved content - */ - public function getContent($url); -} diff --git a/src/Pdp/Parser.php b/src/Pdp/Parser.php deleted file mode 100644 index 71bf8a22..00000000 --- a/src/Pdp/Parser.php +++ /dev/null @@ -1,358 +0,0 @@ -publicSuffixList = $publicSuffixList; - } - - /** - * Parses url. - * - * @param string $url Url to parse - * - * @return Url Object representation of url - */ - public function parseUrl($url) - { - $rawUrl = $url; - $elem = array( - 'scheme' => null, - 'user' => null, - 'pass' => null, - 'host' => null, - 'port' => null, - 'path' => null, - 'query' => null, - 'fragment' => null, - ); - - if (preg_match(self::SCHEME_PATTERN, $url) === 0) { - // Wacky scheme required to overcome parse_url behavior in PHP lt 5.4.7 - // See https://github.com/jeremykendall/php-domain-parser/issues/49 - $url = 'php-lt-5.4.7-hack://' . preg_replace('#^//#', '', $url, 1); - } - - $parts = pdp_parse_url($url); - - if ($parts === false) { - throw new SeriouslyMalformedUrlException($rawUrl); - } - - if ($parts['scheme'] === 'php-lt-5.4.7-hack') { - // Remove wacky scheme required to overcome parse_url behavior in PHP lt 5.4.7 - // See https://github.com/jeremykendall/php-domain-parser/issues/49 - $parts['scheme'] = null; - } - - $elem = (array) $parts + $elem; - - $host = $this->parseHost($parts['host']); - - return new Url( - $elem['scheme'], - $elem['user'], - $elem['pass'], - $host, - $elem['port'], - $elem['path'], - $elem['query'], - $elem['fragment'] - ); - } - - /** - * Parses host part of url. - * - * @param string $host Host part of url - * - * @return Host Object representation of host portion of url - */ - public function parseHost($host) - { - $host = mb_strtolower($host, 'UTF-8'); - - return new Host( - $this->getSubdomain($host), - $this->getRegistrableDomain($host), - $this->getPublicSuffix($host), - $host - ); - } - - /** - * Get the raw public suffix based on the cached public suffix list file. - * Return false if the provided suffix is not included in the PSL. - * - * @param string $host The host to process - * - * @return string|false The suffix or false if suffix not included in the PSL - */ - protected function getRawPublicSuffix($host) - { - $host = $this->normalize($host); - - $parts = array_reverse(explode('.', $host)); - $publicSuffix = array(); - $publicSuffixList = $this->publicSuffixList; - - foreach ($parts as $part) { - if (array_key_exists($part, $publicSuffixList) - && array_key_exists('!', $publicSuffixList[$part])) { - break; - } - - if (array_key_exists($part, $publicSuffixList)) { - array_unshift($publicSuffix, $part); - $publicSuffixList = $publicSuffixList[$part]; - continue; - } - - if (array_key_exists('*', $publicSuffixList)) { - array_unshift($publicSuffix, $part); - $publicSuffixList = $publicSuffixList['*']; - continue; - } - - // Avoids improper parsing when $host's subdomain + public suffix === - // a valid public suffix (e.g. host 'us.example.com' and public suffix 'us.com') - // - // Added by @goodhabit in https://github.com/jeremykendall/php-domain-parser/pull/15 - // Resolves https://github.com/jeremykendall/php-domain-parser/issues/16 - break; - } - - // If empty, then the suffix is not included in the PSL and is - // considered "invalid". This also triggers algorithm rule #2: If no - // rules match, the prevailing rule is "*". - if (empty($publicSuffix)) { - return false; - } - - $suffix = implode('.', array_filter($publicSuffix, 'strlen')); - - return $this->denormalize($suffix); - } - - /** - * Returns the public suffix portion of provided host. - * - * @param string $host host - * - * @return string|null public suffix or null if host does not contain a public suffix - */ - public function getPublicSuffix($host) - { - if (strpos($host, '.') === 0) { - return; - } - - // Fixes #22: If a single label domain makes it this far (e.g., - // localhost, foo, etc.), this stops it from incorrectly being set as - // the public suffix. - if (!$this->isMultiLabelDomain($host)) { - return; - } - - // Fixes #43 - if ($this->isIpv4Address($host)) { - return; - } - - $suffix = $this->getRawPublicSuffix($host); - - // Apply algorithm rule #2: If no rules match, the prevailing rule is "*". - if (false === $suffix) { - $parts = array_reverse(explode('.', $host)); - $suffix = array_shift($parts); - } - - return $suffix; - } - - /** - * Is suffix valid? - * - * Validity determined by whether or not the suffix is included in the PSL. - * - * @param string $host Host part - * - * @return bool True is suffix is valid, false otherwise - */ - public function isSuffixValid($host) - { - return $this->getRawPublicSuffix($host) !== false; - } - - /** - * Returns registrable domain portion of provided host. - * - * Per the test cases provided by Mozilla - * (http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1), - * this method should return null if the domain provided is a public suffix. - * - * @param string $host host - * - * @return string|null registrable domain - */ - public function getRegistrableDomain($host) - { - if (!$this->isMultiLabelDomain($host)) { - return; - } - - $publicSuffix = $this->getPublicSuffix($host); - - if ($publicSuffix === null || $host == $publicSuffix) { - return; - } - - $publicSuffixParts = array_reverse(explode('.', $publicSuffix)); - $hostParts = array_reverse(explode('.', $host)); - $registrableDomainParts = $publicSuffixParts + array_slice($hostParts, 0, count($publicSuffixParts) + 1); - - return implode('.', array_reverse($registrableDomainParts)); - } - - /** - * Returns the subdomain portion of provided host. - * - * @param string $host host - * - * @return string|null subdomain - */ - public function getSubdomain($host) - { - $registrableDomain = $this->getRegistrableDomain($host); - - if ($registrableDomain === null || $host === $registrableDomain) { - return; - } - - $registrableDomainParts = array_reverse(explode('.', $registrableDomain)); - - $host = $this->normalize($host); - - $hostParts = array_reverse(explode('.', $host)); - $subdomainParts = array_slice($hostParts, count($registrableDomainParts)); - - $subdomain = implode('.', array_reverse($subdomainParts)); - - return $this->denormalize($subdomain); - } - - /** - * If a URL is not punycoded, then it may be an IDNA URL, so it must be - * converted to ASCII. Performs conversion and sets flag. - * - * @param string $part Host part - * - * @return string Host part, transformed if not punycoded - */ - protected function normalize($part) - { - $punycoded = (strpos($part, 'xn--') !== false); - - if ($punycoded === false) { - $part = idn_to_ascii($part); - $this->isNormalized = true; - } - - return strtolower($part); - } - - /** - * Converts any normalized part back to IDNA. Performs conversion and - * resets flag. - * - * @param string $part Host part - * - * @return string Denormalized host part - */ - protected function denormalize($part) - { - if ($this->isNormalized === true) { - $part = idn_to_utf8($part); - $this->isNormalized = false; - } - - return $part; - } - - /** - * Tests host for presence of '.'. - * - * Related to #22 - * - * @param string $host Host part of url - * - * @return bool True if multi-label domain, false otherwise - */ - protected function isMultiLabelDomain($host) - { - return strpos($host, '.') !== false; - } - - /** - * Tests host to determine if it is an IP address. - * - * Related to #43 - * - * @param string $host Host part of url - * - * @return bool True if host is an ip address, false otherwise - */ - protected function isIpv4Address($host) - { - return preg_match(self::IP_ADDRESS_PATTERN, $host) === 1; - } -} diff --git a/src/Pdp/PublicSuffixList.php b/src/Pdp/PublicSuffixList.php deleted file mode 100644 index d05687e4..00000000 --- a/src/Pdp/PublicSuffixList.php +++ /dev/null @@ -1,31 +0,0 @@ -cacheDir = $cacheDir; - } - - /** - * Downloads Public Suffix List and writes text cache and PHP cache. If these files - * already exist, they will be overwritten. - */ - public function refreshPublicSuffixList() - { - $this->fetchListFromSource(); - $publicSuffixListArray = $this->parseListToArray( - $this->cacheDir . '/' . self::PDP_PSL_TEXT_FILE - ); - $this->writePhpCache($publicSuffixListArray); - } - - /** - * Obtain Public Suffix List from its online source and write to cache dir. - * - * @return int Number of bytes that were written to the file - */ - public function fetchListFromSource() - { - $publicSuffixList = $this->getHttpAdapter() - ->getContent($this->publicSuffixListUrl); - - return $this->write(self::PDP_PSL_TEXT_FILE, $publicSuffixList); - } - - /** - * Parses text representation of list to associative, multidimensional array. - * - * This method is based heavily on the code found in generateEffectiveTLDs.php - * - * @link https://github.com/usrflo/registered-domain-libs/blob/master/generateEffectiveTLDs.php - * A copy of the Apache License, Version 2.0, is provided with this - * distribution - * - * @param string $textFile Public Suffix List text filename - * - * @return array Associative, multidimensional array representation of the - * public suffx list - */ - public function parseListToArray($textFile) - { - $data = file( - $textFile, - FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES - ); - - $data = array_filter($data, function ($line) { - return strstr($line, '//') === false; - }); - - $publicSuffixListArray = array(); - - foreach ($data as $line) { - $ruleParts = explode('.', $line); - $this->buildArray($publicSuffixListArray, $ruleParts); - } - - return $publicSuffixListArray; - } - - /** - * Recursive method to build the array representation of the Public Suffix List. - * - * This method is based heavily on the code found in generateEffectiveTLDs.php - * - * @link https://github.com/usrflo/registered-domain-libs/blob/master/generateEffectiveTLDs.php - * A copy of the Apache License, Version 2.0, is provided with this - * distribution - * - * @param array $publicSuffixListArray Initially an empty array, this eventually - * becomes the array representation of the Public Suffix List - * @param array $ruleParts One line (rule) from the Public Suffix List - * exploded on '.', or the remaining portion of that array during recursion - */ - public function buildArray(array &$publicSuffixListArray, array $ruleParts) - { - $isDomain = true; - - $part = array_pop($ruleParts); - - // Adheres to canonicalization rule from the "Formal Algorithm" section - // of https://publicsuffix.org/list/ - // "The domain and all rules must be canonicalized in the normal way - // for hostnames - lower-case, Punycode (RFC 3492)." - $part = idn_to_ascii($part); - - if (strpos($part, '!') === 0) { - $part = substr($part, 1); - $isDomain = false; - } - - if (!array_key_exists($part, $publicSuffixListArray)) { - if ($isDomain) { - $publicSuffixListArray[$part] = array(); - } else { - $publicSuffixListArray[$part] = array('!' => ''); - } - } - - if ($isDomain && count($ruleParts) > 0) { - $this->buildArray($publicSuffixListArray[$part], $ruleParts); - } - } - - /** - * Writes php array representation of the Public Suffix List to disk. - * - * @param array $publicSuffixList Array representation of the Public Suffix List - * - * @return int Number of bytes that were written to the file - */ - public function writePhpCache(array $publicSuffixList) - { - $data = 'write(self::PDP_PSL_PHP_FILE, $data); - } - - /** - * Gets Public Suffix List. - * - * @return PublicSuffixList Instance of Public Suffix List - */ - public function getList() - { - if (!file_exists($this->cacheDir . '/' . self::PDP_PSL_PHP_FILE)) { - $this->refreshPublicSuffixList(); - } - - $this->list = new PublicSuffixList( - include $this->cacheDir . '/' . self::PDP_PSL_PHP_FILE - ); - - return $this->list; - } - - /** - * Writes to file. - * - * @param string $filename Filename in cache dir where data will be written - * @param mixed $data Data to write - * - * @return int Number of bytes that were written to the file - * - * @throws \Exception Throws \Exception if unable to write file - */ - protected function write($filename, $data) - { - $result = @file_put_contents($this->cacheDir . '/' . $filename, $data); - - if ($result === false) { - throw new \Exception("Cannot write '" . $this->cacheDir . '/' . "$filename'"); - } - - return $result; - } - - /** - * Returns http adapter. Returns default http adapter if one is not set. - * - * @return \Pdp\HttpAdapter\HttpAdapterInterface Http adapter - */ - public function getHttpAdapter() - { - if ($this->httpAdapter === null) { - $this->httpAdapter = new HttpAdapter\CurlHttpAdapter(); - } - - return $this->httpAdapter; - } - - /** - * Sets http adapter. - * - * @param \Pdp\HttpAdapter\HttpAdapterInterface $httpAdapter - */ - public function setHttpAdapter(HttpAdapter\HttpAdapterInterface $httpAdapter) - { - $this->httpAdapter = $httpAdapter; - } -} diff --git a/src/Pdp/Uri/Url.php b/src/Pdp/Uri/Url.php deleted file mode 100644 index 78d5a94a..00000000 --- a/src/Pdp/Uri/Url.php +++ /dev/null @@ -1,252 +0,0 @@ -scheme = mb_strtolower($scheme, 'UTF-8') ?: null; - $this->user = $user; - $this->pass = $pass; - $this->host = $host; - $this->port = $port; - $this->path = $path; - $this->query = $query; - $this->fragment = $fragment; - } - - /** - * Gets schemeless url. - * - * @return string Url without scheme - */ - public function getSchemeless() - { - return preg_replace(Parser::SCHEME_PATTERN, '//', $this->__toString(), 1); - } - - /** - * Converts the URI object to a string and returns it. - * - * @return string The full URI this object represents. - */ - public function __toString() - { - $url = null; - - if ($this->scheme) { - $url .= $this->scheme . '://'; - } - - if ($this->user) { - $url .= urlencode($this->user); - if ($this->pass) { - $url .= ':' . urlencode($this->pass); - } - $url .= '@'; - } - - $host = $this->host->__toString(); - - if ($host) { - $url .= $host; - } - - if ($this->port) { - $url .= ':' . (int) $this->port; - } - - if ($this->path) { - $url .= $this->path; - } - - if ($this->query) { - $url .= '?' . $this->query; - } - - if ($this->fragment) { - $url .= '#' . urlencode($this->fragment); - } - - return $url; - } - - /** - * Converts the URI object to an array and returns it. - * - * @return array Array of URI component parts - */ - public function toArray() - { - return array( - 'scheme' => $this->getScheme(), - 'user' => $this->getUser(), - 'pass' => $this->getPass(), - 'host' => $this->getHost()->__toString(), - 'subdomain' => $this->getHost()->getSubdomain(), - 'registrableDomain' => $this->getHost()->getRegistrableDomain(), - 'publicSuffix' => $this->getHost()->getPublicSuffix(), - 'port' => $this->getPort(), - 'path' => $this->getPath(), - 'query' => $this->getQuery(), - 'fragment' => $this->getFragment(), - ); - } - - /** - * Get Scheme. - * - * @return string - */ - public function getScheme() - { - return $this->scheme; - } - - /** - * Get User. - * - * @return string - */ - public function getUser() - { - return $this->user; - } - - /** - * Get Pass. - * - * @return string - */ - public function getPass() - { - return $this->pass; - } - - /** - * Get Host object. - * - * @return Host - */ - public function getHost() - { - return $this->host; - } - - /** - * Get Port. - * - * @return int - */ - public function getPort() - { - return $this->port; - } - - /** - * Get Path. - * - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * Get Query. - * - * @return string - */ - public function getQuery() - { - return $this->query; - } - - /** - * Get Fragment. - * - * @return string - */ - public function getFragment() - { - return $this->fragment; - } -} diff --git a/src/Pdp/Uri/Url/Host.php b/src/Pdp/Uri/Url/Host.php deleted file mode 100644 index ec611998..00000000 --- a/src/Pdp/Uri/Url/Host.php +++ /dev/null @@ -1,126 +0,0 @@ -subdomain = $subdomain; - $this->registrableDomain = $registrableDomain; - $this->publicSuffix = $publicSuffix; - $this->host = $host; - } - - /** - * Get Subdomain. - * - * @return string|null - */ - public function getSubdomain() - { - return $this->subdomain; - } - - /** - * @return string - */ - public function getRegistrableDomain() - { - return $this->registrableDomain; - } - - /** - * Get Public suffix. - * - * @return string|null - */ - public function getPublicSuffix() - { - return $this->publicSuffix; - } - - /** - * Get Entire host part. - * - * @return string|null - */ - public function getHost() - { - return $this->host; - } - - /** - * Get string representation of host. - * - * @return string String representation of host - */ - public function __toString() - { - if ($this->host !== null) { - return $this->host; - } - - // retain only the elements that are not empty - $str = array_filter( - array($this->subdomain, $this->registrableDomain), - 'strlen' - ); - - return implode('.', $str); - } - - /** - * Get array representation of host. - * - * @return array Array representation of host - */ - public function toArray() - { - return array( - 'subdomain' => $this->getSubdomain(), - 'registrableDomain' => $this->getRegistrableDomain(), - 'publicSuffix' => $this->getPublicSuffix(), - 'host' => $this->getHost(), - ); - } -} diff --git a/src/PublicSuffixList.php b/src/PublicSuffixList.php new file mode 100644 index 00000000..ecbd75a2 --- /dev/null +++ b/src/PublicSuffixList.php @@ -0,0 +1,32 @@ +[a-z0-9_~\-]) + (?[!$&\'()*+,;=]) + (?%[A-F0-9]{2}) + (?(?:(?&unreserved)|(?&sub_delims)|(?&encoded)){1,63}) + ) + ^(?:(?®_name)\.){0,126}(?®_name)\.?$/ix'; + private const REGEXP_URI_DELIMITERS = '/[:\/?#\[\]@ ]/'; + + /** @var list */ + private readonly array $labels; + private readonly ?string $domain; + + /** + * @throws CannotProcessHost + */ + private function __construct(private readonly string $type, DomainNameProvider|Host|Stringable|string|int|null $domain) + { + $this->domain = $this->parseDomain($domain); + $this->labels = null === $this->domain ? [] : array_reverse(explode('.', $this->domain)); + } + + /** + * @param array{domain:string|null, type:string} $properties + * + * @throws CannotProcessHost + */ + public static function __set_state(array $properties): self + { + return new self($properties['type'], $properties['domain']); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIDNA2003(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + return new self(self::IDNA_2003, $domain); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIDNA2008(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + return new self(self::IDNA_2008, $domain); + } + + /** + * @throws CannotProcessHost + */ + private function parseDomain(DomainNameProvider|Host|Stringable|string|int|null $domain): ?string + { + return $this->parseValue(match (true) { + $domain instanceof DomainNameProvider => $domain->domain()->value(), + $domain instanceof Host => $domain->toUnicode()->value(), + default => $domain, + }); + } + + /** + * Parse and format the domain to ensure it is valid. + * Returns an array containing the formatted domain name labels + * and the domain transitional information. + * + * For example: parse('wWw.uLb.Ac.be') should return ['www.ulb.ac.be', ['be', 'ac', 'ulb', 'www']];. + * + * @throws SyntaxError If the host is not a domain + * @throws SyntaxError If the domain is not a host + */ + private function parseValue(Stringable|string|int|null $domain): ?string + { + if (null === $domain) { + return null; + } + + if ($domain instanceof Stringable) { + $domain = (string) $domain; + } + + $domain = (string) $domain; + if ('' === $domain) { + return ''; + } + + $res = filter_var($domain, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + if (false !== $res) { + return $res; + } + + $formattedDomain = rawurldecode($domain); + return match (true) { + 1 === preg_match(self::REGEXP_REGISTERED_NAME, $formattedDomain) => strtolower($formattedDomain), + // a domain name can not contain URI delimiters or space + 1 === preg_match(self::REGEXP_URI_DELIMITERS, $formattedDomain) => throw SyntaxError::dueToInvalidCharacters($domain), + // if the domain name does not contain UTF-8 chars then it is malformed + 1 !== preg_match(self::REGEXP_IDN_PATTERN, $formattedDomain) => throw SyntaxError::dueToMalformedValue($domain), + default => $this->domainToUnicode($this->domainToAscii($formattedDomain)), + }; + } + + private function domainToAscii(string $domain): string + { + return Idna::toAscii( + $domain, + self::IDNA_2003 === $this->type ? Idna::IDNA2003_ASCII : Idna::IDNA2008_ASCII + )->result(); + } + + private function domainToUnicode(string $domain): string + { + return Idna::toUnicode( + $domain, + self::IDNA_2003 === $this->type ? Idna::IDNA2003_UNICODE : Idna::IDNA2008_UNICODE + )->result(); + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + yield from $this->labels; + } + + public function isAscii(): bool + { + return null === $this->domain || 1 !== preg_match(self::REGEXP_IDN_PATTERN, $this->domain); + } + + public function jsonSerialize(): ?string + { + return $this->domain; + } + + public function count(): int + { + return count($this->labels); + } + + public function value(): ?string + { + return $this->domain; + } + + public function toString(): string + { + return (string) $this->domain; + } + + public function label(int $key): ?string + { + if ($key < 0) { + $key += count($this->labels); + } + + return $this->labels[$key] ?? null; + } + + /** + * @return list + */ + public function keys(?string $label = null): array + { + if (null === $label) { + return array_keys($this->labels); + } + + return array_keys($this->labels, $label, true); + } + + /** + * @return list + */ + public function labels(): array + { + return $this->labels; + } + + public function toAscii(): self + { + if (null === $this->domain) { + return $this; + } + + $domain = $this->domainToAscii($this->domain); + if ($domain === $this->domain) { + return $this; + } + + return new self($this->type, $domain); + } + + public function toUnicode(): self + { + if (null === $this->domain) { + return $this; + } + + $domain = $this->domainToUnicode($this->domain); + if ($domain === $this->domain) { + return $this; + } + + return new self($this->type, $domain); + } + + /** + * Filter a subdomain to update the domain part. + */ + private function normalize(DomainNameProvider|Host|Stringable|string|int|null $domain): ?string + { + if ($domain instanceof DomainNameProvider) { + $domain = $domain->domain(); + } + + if ($domain instanceof Host) { + $domain = $domain->value(); + } + + if (null === $domain) { + return null; + } + + $domain = (string) $domain; + + return match (true) { + null === $this->domain => $domain, + $this->isAscii() => $this->domainToAscii($domain), + default => $this->domainToUnicode($domain), + }; + } + + /** + * @throws CannotProcessHost + */ + public function prepend(DomainNameProvider|Host|Stringable|string|int|null $label): self + { + return $this->withLabel(count($this->labels), $label); + } + + /** + * @throws CannotProcessHost + */ + public function append(DomainNameProvider|Host|Stringable|string|int|null $label): self + { + return $this->withLabel(- count($this->labels) - 1, $label); + } + + public function withLabel(int $key, DomainNameProvider|Host|Stringable|string|int|null $label): self + { + $nbLabels = count($this->labels); + if ($key < - $nbLabels - 1 || $key > $nbLabels) { + throw SyntaxError::dueToInvalidLabelKey($this, $key); + } + + if (0 > $key) { + $key = $nbLabels + $key; + } + + $label = $this->normalize($label); + + if (($this->labels[$key] ?? null) === $label) { + return $this; + } + + $labels = $this->labels; + $labels[$key] = $label; + ksort($labels); + + return new self($this->type, implode('.', array_reverse($labels))); + } + + public function withoutLabel(int ...$keys): self + { + $nbLabels = count($this->labels); + foreach ($keys as &$offset) { + if (- $nbLabels > $offset || $nbLabels - 1 < $offset) { + throw SyntaxError::dueToInvalidLabelKey($this, $offset); + } + + if (0 > $offset) { + $offset += $nbLabels; + } + } + unset($offset); + + $deletedKeys = array_keys(array_count_values($keys)); + $labels = []; + foreach ($this->labels as $offset => $label) { + if (!in_array($offset, $deletedKeys, true)) { + $labels[] = $label; + } + } + + if ($labels === $this->labels) { + return $this; + } + + return new self($this->type, [] === $labels ? null : implode('.', array_reverse($labels))); + } + + /** + * @throws CannotProcessHost + */ + public function clear(): self + { + if (null === $this->domain) { + return $this; + } + + return new self($this->type, null); + } + + /** + * @throws CannotProcessHost + */ + public function slice(int $offset, ?int $length = null): self + { + $nbLabels = count($this->labels); + if ($offset < - $nbLabels || $offset > $nbLabels) { + throw SyntaxError::dueToInvalidLabelKey($this, $offset); + } + + $labels = array_slice($this->labels, $offset, $length, true); + if ($labels === $this->labels) { + return $this; + } + + return new self($this->type, [] === $labels ? null : implode('.', array_reverse($labels))); + } + + public function withRootLabel(): self + { + if ('' === $this->label(0)) { + return $this; + } + + return $this->append(''); + } + + public function withoutRootLabel(): self + { + if ('' === $this->label(0)) { + return $this->slice(1); + } + + return $this; + } + + public function isAbsolute(): bool + { + return '' === $this->label(0); + } + + /** + * Apply the callback if the given "condition" is (or resolves to) true. + * + * @param (callable($this): bool)|bool $condition + * @param callable($this): (self|null) $onSuccess + * @param ?callable($this): (self|null) $onFail + * + */ + public function when(callable|bool $condition, callable $onSuccess, ?callable $onFail = null): self + { + if (!is_bool($condition)) { + $condition = $condition($this); + } + + return match (true) { + $condition => $onSuccess($this), + null !== $onFail => $onFail($this), + default => $this, + } ?? $this; + } +} diff --git a/src/ResolvedDomain.php b/src/ResolvedDomain.php new file mode 100644 index 00000000..d687146a --- /dev/null +++ b/src/ResolvedDomain.php @@ -0,0 +1,301 @@ +domain = $domain; + $this->suffix = $suffix; + [ + 'registrableDomain' => $this->registrableDomain, + 'secondLevelDomain' => $this->secondLevelDomain, + 'subDomain' => $this->subDomain, + ] = $this->parse(); + } + + /** + * @throws CannotProcessHost + */ + public static function fromICANN(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength): self + { + $domain = self::setDomainName($domain); + + return new self($domain, Suffix::fromICANN($domain->withoutRootLabel()->slice(0, $suffixLength))); + } + + /** + * @throws CannotProcessHost + */ + public static function fromPrivate(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength): self + { + $domain = self::setDomainName($domain); + + return new self($domain, Suffix::fromPrivate($domain->withoutRootLabel()->slice(0, $suffixLength))); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIANA(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + $domain = self::setDomainName($domain); + + return new self($domain, Suffix::fromIANA($domain->withoutRootLabel()->label(0))); + } + + /** + * @throws CannotProcessHost + */ + public static function fromUnknown(DomainNameProvider|Host|Stringable|string|int|null $domain, int $suffixLength = 0): self + { + $domain = self::setDomainName($domain); + + return new self($domain, Suffix::fromUnknown($domain->slice(0, $suffixLength))); + } + + /** + * @param array{domain:DomainName, suffix:EffectiveTopLevelDomain} $properties + * + * @throws CannotProcessHost + */ + public static function __set_state(array $properties): self + { + return new self($properties['domain'], $properties['suffix']); + } + + /** + * @throws CannotProcessHost + */ + private static function setDomainName(DomainNameProvider|Host|Stringable|string|int|null $domain): DomainName + { + return match (true) { + $domain instanceof DomainNameProvider => $domain->domain(), + $domain instanceof DomainName => $domain, + default => RegisteredName::fromIDNA2008($domain), + }; + } + + /** + * Make sure the Value Object is always in a valid state. + * + * @throws UnableToResolveDomain|CannotProcessHost If the suffix can not be attached to the domain + * + * @return array{registrableDomain: DomainName, secondLevelDomain: DomainName, subDomain: DomainName} + */ + private function parse(): array + { + $suffixValue = $this->suffix->value(); + if (null === $suffixValue) { + $nullDomain = $this->domain->clear(); + + return [ + 'registrableDomain' => $nullDomain, + 'secondLevelDomain' => $nullDomain, + 'subDomain' => $nullDomain, + ]; + } + + if (2 > count($this->domain)) { + throw UnableToResolveDomain::dueToUnresolvableDomain($this->domain); + } + + if ($this->domain->value() === $suffixValue) { + throw UnableToResolveDomain::dueToIdenticalValue($this->domain); + } + + $length = count($this->suffix); + $offset = 0; + if ($this->domain->isAbsolute()) { + $offset = 1; + } + + return [ + 'registrableDomain' => $this->domain->slice($offset, $length + 1), + 'secondLevelDomain' => $this->domain->slice($length + $offset, 1), + 'subDomain' => RegisteredName::fromIDNA2008($this->domain->value())->slice($length + 1 + $offset), + ]; + } + + public function count(): int + { + return count($this->domain); + } + + public function domain(): DomainName + { + return $this->domain; + } + + public function registrableDomain(): DomainName + { + return $this->registrableDomain; + } + + public function secondLevelDomain(): DomainName + { + return $this->secondLevelDomain; + } + + public function subDomain(): DomainName + { + return $this->subDomain; + } + + public function suffix(): EffectiveTopLevelDomain + { + return $this->suffix; + } + + public function jsonSerialize(): ?string + { + return $this->domain->jsonSerialize(); + } + + public function value(): ?string + { + return $this->domain->value(); + } + + public function toString(): string + { + return $this->domain->toString(); + } + + public function toAscii(): self + { + return new self($this->domain->toAscii(), $this->suffix->toAscii()); + } + + public function toUnicode(): self + { + return new self($this->domain->toUnicode(), $this->suffix->toUnicode()); + } + + public function isAbsolute(): bool + { + return $this->domain->isAbsolute(); + } + + public function withoutRootLabel(): self + { + return new self($this->domain->withoutRootLabel(), $this->suffix); + } + + public function withRootLabel(): self + { + return new self($this->domain->withRootLabel(), $this->suffix); + } + + /** + * @throws CannotProcessHost + */ + public function withSuffix(DomainNameProvider|Host|Stringable|string|int|null $suffix): self + { + if (!$suffix instanceof EffectiveTopLevelDomain) { + $suffix = Suffix::fromUnknown($suffix); + } + + $domain = $this->domain->withoutRootLabel()->slice(count($this->suffix))->append($suffix); + + return new self( + $domain->when($this->domain->isAbsolute(), fn (DomainName $domainName) => $domain->withRootLabel()), + $suffix->normalize($this->domain) + ); + } + + /** + * @throws CannotProcessHost|UnableToResolveDomain + */ + public function withSubDomain(DomainNameProvider|Host|Stringable|string|int|null $subDomain): self + { + if (null === $this->suffix->value()) { + throw UnableToResolveDomain::dueToMissingRegistrableDomain($this->domain); + } + + $subDomain = RegisteredName::fromIDNA2008($subDomain); + if ($subDomain->isAbsolute()) { + $subDomain = $subDomain->withoutRootLabel(); + if (null === $subDomain->value()) { + throw SyntaxError::dueToMalformedValue($subDomain->withRootLabel()->toString()); + } + } + + if ($this->subDomain->value() === $subDomain->value()) { + return $this; + } + + $domain = $this->registrableDomain->prepend($subDomain); + + return new self($domain->when($this->domain->isAbsolute(), fn (DomainName $domainName) => $domain->withRootLabel()), $this->suffix); + } + + /** + * @throws CannotProcessHost|UnableToResolveDomain + */ + public function withSecondLevelDomain(DomainNameProvider|Host|Stringable|string|int|null $label): self + { + if (null === $this->suffix->value()) { + throw UnableToResolveDomain::dueToMissingRegistrableDomain($this->domain); + } + + $label = RegisteredName::fromIDNA2008($label); + if ($label->isAbsolute()) { + if (2 !== count($label)) { + throw UnableToResolveDomain::dueToInvalidSecondLevelDomain($label); + } + $label = $label->withoutRootLabel(); + } + + if (1 !== count($label)) { + throw UnableToResolveDomain::dueToInvalidSecondLevelDomain($label); + } + + $newRegistrableDomain = $this->registrableDomain->withoutLabel(-1)->prepend($label); + if ($newRegistrableDomain->value() === $this->registrableDomain->value()) { + return $this; + } + + return new self($newRegistrableDomain->prepend($this->subDomain), $this->suffix); + } + + /** + * Apply the callback if the given "condition" is (or resolves to) true. + * + * @param (callable($this): bool)|bool $condition + * @param callable($this): (self|null) $onSuccess + * @param ?callable($this): (self|null) $onFail + * + */ + public function when(callable|bool $condition, callable $onSuccess, ?callable $onFail = null): self + { + if (!is_bool($condition)) { + $condition = $condition($this); + } + + return match (true) { + $condition => $onSuccess($this), + null !== $onFail => $onFail($this), + default => $this, + } ?? $this; + } +} diff --git a/src/ResolvedDomainName.php b/src/ResolvedDomainName.php new file mode 100644 index 00000000..33d606fb --- /dev/null +++ b/src/ResolvedDomainName.php @@ -0,0 +1,59 @@ +domain(), $newDomain->domain()); + self::assertNotSame($domain->suffix()->value(), $newDomain->suffix()->value()); + } + + public function testRegistrableDomainIsNullWithFoundDomain(): void + { + $domain = ResolvedDomain::fromUnknown('faketld'); + self::assertNull($domain->suffix()->value()); + self::assertNull($domain->registrableDomain()->value()); + self::assertNull($domain->subDomain()->value()); + self::assertNull($domain->secondLevelDomain()->value()); + } + + #[DataProvider('provideWrongConstructor')] + public function testItThrowsExceptionMisMatchPublicSuffixDomain(?string $domain, int $length): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromICANN($domain, $length); + } + + /** + * @return iterable + */ + public static function provideWrongConstructor(): iterable + { + return [ + 'domain and public suffix are the same' => [ + 'domain' => 'co.uk', + 'length' => 2, + ], + 'domain has no labels' => [ + 'domain' => 'localhost', + 'length' => 1, + ], + ]; + } + + public function testItCanBeUsedWithInternalPhpMethod(): void + { + $domain = ResolvedDomain::fromICANN('www.ulb.ac.be', 2); + /** @var ResolvedDomain $generateDomain */ + $generateDomain = eval('return '.var_export($domain, true).';'); + self::assertEquals($domain, $generateDomain); + self::assertEquals('"www.ulb.ac.be"', json_encode($domain->jsonSerialize())); + self::assertSame('www.ulb.ac.be', $domain->toString()); + } + + #[DataProvider('countableProvider')] + public function testItImplementsCountable(?string $domain, int $nbLabels): void + { + self::assertCount($nbLabels, ResolvedDomain::fromUnknown($domain)); + } + + /** + * @return iterable + */ + public static function countableProvider(): iterable + { + return [ + 'null' => [null, 0], + 'empty string' => ['', 1], + 'simple' => ['foo.bar.baz', 3], + 'unicode' => ['www.食狮.公司.cn', 4], + ]; + } + + #[DataProvider('toUnicodeProvider')] + public function testItCanBeConvertedToUnicode( + ?string $domain, + ?string $publicSuffix, + ?string $expectedDomain, + ?string $expectedSuffix, + ?string $expectedIDNDomain, + ?string $expectedIDNSuffix + ): void { + $domain = ResolvedDomain::fromUnknown(Domain::fromIDNA2003($domain), count(Suffix::fromUnknown($publicSuffix))); + self::assertSame($expectedDomain, $domain->value()); + self::assertSame($expectedSuffix, $domain->suffix()->value()); + + /** @var ResolvedDomain $domainIDN */ + $domainIDN = $domain->toUnicode(); + self::assertSame($expectedIDNDomain, $domainIDN->value()); + self::assertSame($expectedIDNSuffix, $domainIDN->suffix()->value()); + } + + /** + * @return iterable + */ + public static function toUnicodeProvider(): iterable + { + return [ + 'simple domain' => [ + 'domain' => 'www.ulb.ac.be', + 'publicSuffix' => 'ac.be', + 'expectedDomain' => 'www.ulb.ac.be', + 'expectedSuffix' => 'ac.be', + 'expectedIDNDomain' => 'www.ulb.ac.be', + 'expectedIDNSuffix' => 'ac.be', + ], + 'ASCII to IDN domain' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'publicSuffix' => 'xn--85x722f.xn--55qx5d.cn', + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedSuffix' => 'xn--85x722f.xn--55qx5d.cn', + 'expectedIDNDomain' => 'www.食狮.公司.cn', + 'expectedIDNSuffix' => '食狮.公司.cn', + ], + 'IDN to IDN domain' => [ + 'domain' => 'www.食狮.公司.cn', + 'publicSuffix' => '食狮.公司.cn', + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedSuffix' => '食狮.公司.cn', + 'expectedIDNDomain' => 'www.食狮.公司.cn', + 'expectedIDNSuffix' => '食狮.公司.cn', + ], + 'empty string domain and null suffix' => [ + 'domain' => '', + 'publicSuffix' => null, + 'expectedDomain' => '', + 'expectedSuffix' => null, + 'expectedIDNDomain' => '', + 'expectedIDNSuffix' => null, + ], + 'null domain and suffix' => [ + 'domain' => null, + 'publicSuffix' => null, + 'expectedDomain' => null, + 'expectedSuffix' => null, + 'expectedIDNDomain' => null, + 'expectedIDNSuffix' => null, + ], + 'domain with null suffix' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'publicSuffix' => null, + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedSuffix' => null, + 'expectedIDNDomain' => 'www.食狮.公司.cn', + 'expectedIDNSuffix' => null, + ], + 'domain with URLencoded data' => [ + 'domain' => 'b%C3%A9b%C3%A9.be', + 'publicSuffix' => 'be', + 'expectedDomain' => 'bébé.be', + 'expectedSuffix' => 'be', + 'expectedIDNDomain' => 'bébé.be', + 'expectedIDNSuffix' => 'be', + ], + ]; + } + + #[DataProvider('toAsciiProvider')] + public function testItCanBeConvertedToAscii( + ?string $domain, + ?string $publicSuffix, + ?string $expectedDomain, + ?string $expectedSuffix, + ?string $expectedIDNDomain, + ?string $expectedIDNSuffix + ): void { + $domain = ResolvedDomain::fromUnknown(Domain::fromIDNA2003($domain), count(Domain::fromIDNA2003($publicSuffix))); + self::assertSame($expectedDomain, $domain->value()); + self::assertSame($expectedSuffix, $domain->suffix()->value()); + + /** @var ResolvedDomain $domainIDN */ + $domainIDN = $domain->toAscii(); + self::assertSame($expectedIDNDomain, $domainIDN->value()); + self::assertSame($expectedIDNSuffix, $domainIDN->suffix()->value()); + } + + /** + * @return iterable + */ + public static function toAsciiProvider(): iterable + { + return [ + 'simple domain' => [ + 'domain' => 'www.ulb.ac.be', + 'publicSuffix' => 'ac.be', + 'expectedDomain' => 'www.ulb.ac.be', + 'expectedSuffix' => 'ac.be', + 'expectedIDNDomain' => 'www.ulb.ac.be', + 'expectedIDNSuffix' => 'ac.be', + ], + 'ASCII to ASCII domain' => [ + 'domain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'publicSuffix' => 'xn--85x722f.xn--55qx5d.cn', + 'expectedDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedSuffix' => 'xn--85x722f.xn--55qx5d.cn', + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNSuffix' => 'xn--85x722f.xn--55qx5d.cn', + ], + 'ASCII to IDN domain' => [ + 'domain' => 'www.食狮.公司.cn', + 'publicSuffix' => '食狮.公司.cn', + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedSuffix' => '食狮.公司.cn', + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNSuffix' => 'xn--85x722f.xn--55qx5d.cn', + ], + 'null domain and suffix' => [ + 'domain' => null, + 'publicSuffix' => null, + 'expectedDomain' => null, + 'expectedSuffix' => null, + 'expectedIDNDomain' => null, + 'expectedIDNSuffix' => null, + ], + 'domain with null suffix' => [ + 'domain' => 'www.食狮.公司.cn', + 'publicSuffix' => null, + 'expectedDomain' => 'www.食狮.公司.cn', + 'expectedSuffix' => null, + 'expectedIDNDomain' => 'www.xn--85x722f.xn--55qx5d.cn', + 'expectedIDNSuffix' => null, + ], + ]; + } + + #[DataProvider('withSubDomainWorksProvider')] + public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, DomainName|string|null $subdomain, ?string $expected = null): void + { + $result = $domain->withSubDomain($subdomain); + + self::assertSame($expected, $result->subDomain()->value()); + self::assertEquals($domain->suffix(), $result->suffix()); + self::assertEquals($domain->registrableDomain(), $result->registrableDomain()); + } + + /** + * @return iterable + */ + public static function withSubDomainWorksProvider(): iterable + { + return [ + 'simple addition' => [ + 'domain' => ResolvedDomain::fromICANN('example.com', 1), + 'subdomain' => 'www', + 'expected' => 'www', + ], + 'simple addition IDN (1)' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('example.com'), 1), + 'subdomain' => Domain::fromIDNA2003('bébé'), + 'expected' => 'xn--bb-bjab', + ], + 'simple addition IDN (2)' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('Яндекс.РФ'), 1), + 'subdomain' => 'bébé', + 'expected' => 'bébé', + ], + 'simple removal' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('example.com'), 1), + 'subdomain' => null, + 'expected' => null, + ], + 'simple removal IDN' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('bébé.Яндекс.РФ'), 1), + 'subdomain' => 'xn--bb-bjab', + 'expected' => 'bébé', + ], + ]; + } + + public function testItCanThrowsDuringSubDomainChangesIfItHasNoSuffix(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromUnknown(null)->withSubDomain('www'); + } + + public function testItCanThrowsDuringSubDomainChangesIfItHasOnlyOneLabel(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromUnknown('localhost')->withSubDomain('www'); + } + + public function testItCanThrowsDuringSubDomainChangesIfTheSubDomainIsTheEmptyString(): void + { + $this->expectException(SyntaxError::class); + + ResolvedDomain::fromICANN('www.example.com', 1)->withSubDomain(''); + } + + #[DataProvider('withPublicSuffixWorksProvider')] + public function testItCanChangeItsSuffix( + ResolvedDomain $domain, + EffectiveTopLevelDomain|string|null $publicSuffix, + ?string $expected, + bool $isKnown, + bool $isICANN, + bool $isPrivate + ): void { + $result = $domain->withSuffix($publicSuffix); + $newPublicSuffix = $result->suffix(); + + self::assertSame($expected, $newPublicSuffix->value()); + self::assertSame($isKnown, $newPublicSuffix->isKnown()); + self::assertSame($isICANN, $newPublicSuffix->isICANN()); + self::assertSame($isPrivate, $newPublicSuffix->isPrivate()); + } + + /** + * @return iterable + */ + public static function withPublicSuffixWorksProvider(): iterable + { + $baseDomain = ResolvedDomain::fromICANN('example.com', 1); + $baseRootDomain = ResolvedDomain::fromICANN('example.com.', 1); + + return [ + 'simple update (1)' => [ + 'domain' => $baseDomain, + 'publicSuffix' => 'be', + 'expected' => 'be', + 'isKnown' => false, + 'isICANN' => false, + 'isPrivate' => false, + ], + 'simple update with root-label (1)' => [ + 'domain' => $baseRootDomain, + 'publicSuffix' => 'be', + 'expected' => 'be', + 'isKnown' => false, + 'isICANN' => false, + 'isPrivate' => false, + ], + 'simple update (2)' => [ + 'domain' => $baseDomain, + 'publicSuffix' => Suffix::fromPrivate('github.io'), + 'expected' => 'github.io', + 'isKnown' => true, + 'isICANN' => false, + 'isPrivate' => true, + ], + 'simple update with root-label (2)' => [ + 'domain' => $baseRootDomain, + 'publicSuffix' => Suffix::fromPrivate('github.io'), + 'expected' => 'github.io', + 'isKnown' => true, + 'isICANN' => false, + 'isPrivate' => true, + ], + 'same public suffix but PSL info is changed' => [ + 'domain' => $baseDomain, + 'publicSuffix' => Suffix::fromPrivate('com'), + 'expected' => 'com', + 'isKnown' => true, + 'isICANN' => false, + 'isPrivate' => true, + ], + 'same public suffix but PSL info is changed with root domain' => [ + 'domain' => $baseRootDomain, + 'publicSuffix' => Suffix::fromPrivate('com'), + 'expected' => 'com', + 'isKnown' => true, + 'isICANN' => false, + 'isPrivate' => true, + ], + 'same public suffix but PSL info does not changed' => [ + 'domain' => $baseDomain, + 'publicSuffix' => Suffix::fromICANN('com'), + 'expected' => 'com', + 'isKnown' => true, + 'isICANN' => true, + 'isPrivate' => false, + ], + 'simple update IDN (1)' => [ + 'domain' => $baseDomain, + 'publicSuffix' => Suffix::fromICANN(Domain::fromIDNA2008('рф')), + 'expected' => 'xn--p1ai', + 'isKnown' => true, + 'isICANN' => true, + 'isPrivate' => false, + ], + 'simple update IDN (2)' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('www.bébé.be'), 1), + 'publicSuffix' => Suffix::fromICANN(Domain::fromIDNA2003('xn--p1ai')), + 'expected' => 'рф', + 'isKnown' => true, + 'isICANN' => true, + 'isPrivate' => false, + ], + 'simple update IDN (2) with root domains' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('www.bébé.be.'), 1), + 'publicSuffix' => Suffix::fromICANN(Domain::fromIDNA2003('xn--p1ai')), + 'expected' => 'рф', + 'isKnown' => true, + 'isICANN' => true, + 'isPrivate' => false, + ], + 'adding the public suffix to a single label domain' => [ + 'domain' => ResolvedDomain::fromUnknown('localhost'), + 'publicSuffix' => 'www', + 'expected' => 'www', + 'isKnown' => false, + 'isICANN' => false, + 'isPrivate' => false, + ], + 'removing the public suffix list' => [ + 'domain' => ResolvedDomain::fromICANN(Domain::fromIDNA2003('www.bébé.be'), 1), + 'publicSuffix' => null, + 'expected' => null, + 'isKnown' => false, + 'isICANN' => false, + 'isPrivate' => false, + ], + 'with custom IDNA domain options' => [ + 'domain' => ResolvedDomain::fromICANN('www.bébé.be', 1), + 'publicSuffix' => null, + 'expected' => null, + 'isKnown' => false, + 'isICANN' => false, + 'isPrivate' => false, + ], + ]; + } + + public function testItCanThrowsDuringSuffixChangesIfTheDomainHasNotSuffix(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromUnknown(null)->withSuffix('www'); + } + + #[DataProvider('resolveCustomIDNAOptionsProvider')] + public function testItCanWorksWithIDNAOptions( + string $domainName, + string $publicSuffix, + string $expectedContent, + string $expectedAscii, + string $expectedUnicode, + string $expectedRegistrable, + ?string $expectedSubDomain + ): void { + $resolvedDomain = ResolvedDomain::fromICANN($domainName, count(Domain::fromIDNA2008($publicSuffix))); + + self::assertSame($expectedContent, $resolvedDomain->value()); + self::assertSame($expectedAscii, $resolvedDomain->toAscii()->value()); + self::assertSame($expectedUnicode, $resolvedDomain->toUnicode()->value()); + self::assertSame($expectedRegistrable, $resolvedDomain->registrableDomain()->value()); + self::assertSame($expectedSubDomain, $resolvedDomain->subDomain()->value()); + } + + /** + * @return iterable + */ + public static function resolveCustomIDNAOptionsProvider(): iterable + { + return [ + 'without deviation characters' => [ + 'example.com', + 'com', + 'example.com', + 'example.com', + 'example.com', + 'example.com', + null, + ], + 'without deviation characters with label' => [ + 'www.example.com', + 'com', + 'www.example.com', + 'www.example.com', + 'www.example.com', + 'example.com', + 'www', + ], + 'with deviation in domain' => [ + 'www.faß.de', + 'de', + 'www.faß.de', + 'www.xn--fa-hia.de', + 'www.faß.de', + 'faß.de', + 'www', + ], + 'with deviation in label' => [ + 'faß.test.de', + 'de', + 'faß.test.de', + 'xn--fa-hia.test.de', + 'faß.test.de', + 'test.de', + 'faß', + ], + ]; + } + + #[DataProvider('withSldWorksProvider')] + public function testWithSecondLevelDomain( + ?string $host, + ?string $publicSuffix, + ?string $sld, + ?string $expectedSld, + ?string $expectedHost + ): void { + $domain = ResolvedDomain::fromICANN($host, count(Domain::fromIDNA2008($publicSuffix))); + $newDomain = $domain->withSecondLevelDomain($sld); + + self::assertSame($expectedSld, $newDomain->secondLevelDomain()->value()); + self::assertEquals($expectedHost, $newDomain->value()); + self::assertEquals($domain->suffix(), $newDomain->suffix()); + self::assertEquals($domain->subDomain(), $newDomain->subDomain()); + } + + /** + * @return iterable + */ + public static function withSldWorksProvider(): iterable + { + return [ + [ + 'host' => 'example.com', + 'publicSuffix' => 'com', + 'sld' => 'www', + 'expectedSld' => 'www', + 'expectedHost' => 'www.com', + ], + [ + 'host' => 'example.com', + 'publicSuffix' => 'com', + 'sld' => 'www.', + 'expectedSld' => 'www', + 'expectedHost' => 'www.com', + ], + [ + 'host' => 'www.example.com', + 'publicSuffix' => 'com', + 'sld' => 'www', + 'expectedSld' => 'www', + 'expectedHost' => 'www.www.com', + ], + [ + 'host' => 'www.bbc.co.uk', + 'publicSuffix' => 'co.uk', + 'sld' => 'hamburger', + 'expectedSld' => 'hamburger', + 'expectedHost' => 'www.hamburger.co.uk', + ], + [ + 'host' => 'www.bbc.co.uk', + 'publicSuffix' => 'co.uk', + 'sld' => 'hamburger.', + 'expectedSld' => 'hamburger', + 'expectedHost' => 'www.hamburger.co.uk', + ], + ]; + } + + public function testItCanNotAppendAnEmptySLD(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromICANN('private.ulb.ac.be', 2)->withSecondLevelDomain(null); + } + + public function testItCanNotAppendAnEmptyRootLabelSLD(): void + { + $this->expectException(SyntaxError::class); + + ResolvedDomain::fromICANN('private.ulb.ac.be', 2)->withSecondLevelDomain('.'); + } + + public function testItCanNotAppendAnInvalidRootLabelSLD(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromICANN('private.ulb.ac.be', 2)->withSecondLevelDomain('toto.foo.'); + } + + public function testItCanNotAppendASLDToAResolvedDomainWithoutSuffix(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromUnknown('private.ulb.ac.be')->withSecondLevelDomain('yes'); + } + + public function testItCanNotAppendAnInvalidSLDToAResolvedDomain(): void + { + $this->expectException(UnableToResolveDomain::class); + + ResolvedDomain::fromIANA('private.ulb.ac.be')->withSecondLevelDomain('foo.bar'); + } + + public function testItCanNotAppendAnInvalidSubDomainToAResolvedDomain(): void + { + $this->expectException(SyntaxError::class); + + ResolvedDomain::fromIANA('private.ulb.ac.be')->withSubDomain(''); + } + + public function testItReturnsTheInstanceWhenTheSLDIsEqual(): void + { + $domain = ResolvedDomain::fromICANN('private.ulb.ac.be', 2); + + self::assertEquals($domain->withSecondLevelDomain('ulb'), $domain); + } + + public function testSubDomainCanHandleIpLikeValue(): void + { + self::assertSame( + '1.1.1.1.cloudflare-dns.com', + ResolvedDomain::fromICANN('cloudflare-dns.com', 1)->withSubDomain('1.1.1.1')->toString() + ); + } + + public function testSuffixCanHandleIpLikeValue(): void + { + self::assertSame( + 'cloudflare-dns.com.1.1.1.1', + ResolvedDomain::fromICANN('cloudflare-dns.com.1.1.1.1', 4)->toString() + ); + } + + public function testWithAndWithoutRootLabelResult(): void + { + $withoutRootLabelResult = ResolvedDomain::fromICANN('cloudflare-dns.com', 1); + $withRootLabelResult = $withoutRootLabelResult->withRootLabel(); + + self::assertTrue($withRootLabelResult->isAbsolute()); + self::assertFalse($withoutRootLabelResult->isAbsolute()); + self::assertEquals($withoutRootLabelResult, $withRootLabelResult->withoutRootLabel()); + self::assertSame($withoutRootLabelResult->suffix()->value(), $withRootLabelResult->suffix()->value()); + self::assertSame($withoutRootLabelResult->subDomain()->value(), $withRootLabelResult->subDomain()->value()); + self::assertSame($withoutRootLabelResult->registrableDomain()->value(), $withRootLabelResult->registrableDomain()->value()); + self::assertSame($withoutRootLabelResult->secondLevelDomain()->value(), $withRootLabelResult->secondLevelDomain()->value()); + self::assertNotSame($withoutRootLabelResult->domain()->value(), $withRootLabelResult->domain()->value()); + } +} diff --git a/src/ResourceUri.php b/src/ResourceUri.php new file mode 100644 index 00000000..1e57d8b2 --- /dev/null +++ b/src/ResourceUri.php @@ -0,0 +1,12 @@ +BEGIN|END) (?ICANN|PRIVATE) DOMAINS===,'; + private const PSL_SECTION = [ + 'ICANN' => [ + 'BEGIN' => self::ICANN_DOMAINS, + 'END' => '', + ], + 'PRIVATE' => [ + 'BEGIN' => self::PRIVATE_DOMAINS, + 'END' => '', + ], + ]; + + /** + * @param array{ICANN_DOMAINS: array, PRIVATE_DOMAINS: array} $rules + */ + private function __construct(private readonly array $rules) + { + } + + /** + * Returns a new instance from a file path. + * + * @param null|resource $context + * + * @throws UnableToLoadResource If the rules can not be loaded from the path + * @throws UnableToLoadPublicSuffixList If the rules contain in the resource are invalid + */ + public static function fromPath(string $path, $context = null): self + { + return self::fromString(Stream::getContentAsString($path, $context)); + } + + /** + * Returns a new instance from a string. + * + * @throws UnableToLoadPublicSuffixList If the rules contain in the resource are invalid + */ + public static function fromString(Stringable|string $content): self + { + return new self(self::parse((string) $content)); + } + + /** + * Convert the Public Suffix List into an associative, multidimensional array. + * + * @return array{ICANN_DOMAINS: array, PRIVATE_DOMAINS: array} + */ + private static function parse(string $content): array + { + $rules = [self::ICANN_DOMAINS => [], self::PRIVATE_DOMAINS => []]; + $section = ''; + $file = new SplTempFileObject(); + $file->fwrite($content); + $file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY); + /** @var string $line */ + foreach ($file as $line) { + $section = self::getSection($section, $line); + if (in_array($section, [self::PRIVATE_DOMAINS, self::ICANN_DOMAINS], true) && !str_contains($line, '//')) { + $rules[$section] = self::addRule($rules[$section], explode('.', $line)); + } + } + + return $rules; + } + + /** + * Returns the section type for a given line. + */ + private static function getSection(string $section, string $line): string + { + if (1 === preg_match(self::REGEX_PSL_SECTION, $line, $matches)) { + return self::PSL_SECTION[$matches['type']][$matches['point']]; + } + + return $section; + } + + /** + * Recursive method to build the array representation of the Public Suffix List. + * + * This method is based heavily on the code found in generateEffectiveTLDs.php + * + * @see https://github.com/usrflo/registered-domain-libs/blob/master/generateEffectiveTLDs.php + * A copy of the Apache License, Version 2.0, is provided with this distribution + * + * @param array $list Initially an empty array, this eventually becomes the array representation of a + * Public Suffix List section + * @param array $ruleParts One line (rule) from the Public Suffix List exploded on '.', or the remaining + * portion of that array during recursion + * + * @throws UnableToLoadPublicSuffixList if the domain name can not be converted using IDN to ASCII algorithm + * + * @return array + */ + private static function addRule(array $list, array $ruleParts): array + { + // Adheres to canonicalization rule from the "Formal Algorithm" section + // of https://publicsuffix.org/list/ + // "The domain and all rules must be canonicalized in the normal way + // for hostnames - lower-case, Punycode (RFC 3492)." + try { + /** @var string $line */ + $line = array_pop($ruleParts); + $rule = Idna::toAscii($line, Idna::IDNA2008_ASCII)->result(); + } catch (CannotProcessHost $exception) { + throw UnableToLoadPublicSuffixList::dueToInvalidRule($line ?? null, $exception); + } + + $isDomain = true; + if (str_starts_with($rule, '!')) { + $rule = substr($rule, 1); + $isDomain = false; + } + + if (isset($list[$rule]) && [] === $list[$rule]) { + $list[$rule] = [self::DOMAIN_RULE_MARKER => '']; + } + + if (!isset($list[$rule])) { + $list[$rule] = $isDomain ? [] : ['!' => '']; + } + + if ($isDomain && [] !== $ruleParts) { + $list[$rule] = self::addRule($list[$rule], $ruleParts); + } + + return $list; + } + + /** + * @param array{rules:array{ICANN_DOMAINS: array, PRIVATE_DOMAINS: array}} $properties + */ + public static function __set_state(array $properties): self + { + return new self($properties['rules']); + } + + public function resolve(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + try { + return $this->getCookieDomain($host); + } catch (UnableToResolveDomain $exception) { + return ResolvedDomain::fromUnknown($exception->domain()); + } catch (SyntaxError) { + return ResolvedDomain::fromUnknown(Domain::fromIDNA2008(null)); + } + } + + public function getCookieDomain(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + $domain = $this->validateDomain($host); + [$suffixLength, $section] = $this->resolveSuffix($domain->withoutRootLabel(), self::UNKNOWN_DOMAINS); + + return match (true) { + self::ICANN_DOMAINS === $section => ResolvedDomain::fromICANN($domain, $suffixLength), + self::PRIVATE_DOMAINS === $section => ResolvedDomain::fromPrivate($domain, $suffixLength), + default => ResolvedDomain::fromUnknown($domain, $suffixLength), + }; + } + + public function getICANNDomain(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + $domain = $this->validateDomain($host); + [$suffixLength, $section] = $this->resolveSuffix($domain, self::ICANN_DOMAINS); + if (self::ICANN_DOMAINS !== $section) { + throw UnableToResolveDomain::dueToMissingSuffix($domain, 'ICANN'); + } + + return ResolvedDomain::fromICANN($domain, $suffixLength); + } + + public function getPrivateDomain(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + $domain = $this->validateDomain($host); + [$suffixLength, $section] = $this->resolveSuffix($domain, self::PRIVATE_DOMAINS); + if (self::PRIVATE_DOMAINS !== $section) { + throw UnableToResolveDomain::dueToMissingSuffix($domain, 'private'); + } + + return ResolvedDomain::fromPrivate($domain, $suffixLength); + } + + /** + * Assert the domain is valid and is resolvable. + * + * @throws SyntaxError If the domain is invalid + * @throws UnableToResolveDomain If the domain can not be resolved + */ + private function validateDomain(DomainNameProvider|Host|Stringable|string|int|null $domain): DomainName + { + if ($domain instanceof DomainNameProvider) { + $domain = $domain->domain(); + } + + if (!$domain instanceof DomainName) { + $domain = Domain::fromIDNA2008($domain); + } + + return $domain; + } + + /** + * Returns the length and the section of the resolved effective top level domain. + * + * @param Rules::UNKNOWN_DOMAINS|Rules::ICANN_DOMAINS|Rules::PRIVATE_DOMAINS $section + * + * @return array{0: int, 1:Rules::UNKNOWN_DOMAINS|Rules::ICANN_DOMAINS|Rules::PRIVATE_DOMAINS} + */ + private function resolveSuffix(DomainName $domain, string $section): array + { + $icannSuffixLength = $this->getPublicSuffixLengthFromSection($domain, self::ICANN_DOMAINS); + if (1 > $icannSuffixLength) { + return [1, self::UNKNOWN_DOMAINS]; + } + + if (self::ICANN_DOMAINS === $section) { + return [$icannSuffixLength, self::ICANN_DOMAINS]; + } + + $privateSuffixLength = $this->getPublicSuffixLengthFromSection($domain, self::PRIVATE_DOMAINS); + if ($privateSuffixLength > $icannSuffixLength) { + return [$privateSuffixLength, self::PRIVATE_DOMAINS]; + } + + return [$icannSuffixLength, self::ICANN_DOMAINS]; + } + + /** + * Returns the public suffix label count for a domain name according to a PSL section. + */ + private function getPublicSuffixLengthFromSection(DomainName $domain, string $section): int + { + $rules = $this->rules[$section]; + $labelCount = 0; + foreach ($domain->toAscii() as $label) { + //match exception rule + if (isset($rules[$label]['!'])) { + return $labelCount; + } + + //match wildcard rule + if (array_key_exists('*', $rules)) { + ++$labelCount; + + return $labelCount; + } + + //no match found + if (!array_key_exists($label, $rules)) { + if (self::PRIVATE_DOMAINS !== $section) { + return $labelCount; + } + + // Suffix MATCHES default domain + if (array_key_exists(self::DOMAIN_RULE_MARKER, $rules)) { + return $labelCount; + } + + // Suffix MUST be fully matched else no suffix is found for private domain + if (self::hasRemainingRules($rules)) { + return 0; + } + + return $labelCount; + } + + ++$labelCount; + /** @var array $rules */ + $rules = $rules[$label]; + } + + return $labelCount; + } + + private static function hasRemainingRules(array $rules): bool + { + foreach ($rules as $rule) { + if ([] !== $rule) { + return true; + } + } + + return false; + } +} diff --git a/src/RulesTest.php b/src/RulesTest.php new file mode 100644 index 00000000..2b0bda9b --- /dev/null +++ b/src/RulesTest.php @@ -0,0 +1,603 @@ + [ + 'method' => 'GET', + 'header' => "Accept-language: en\r\nCookie: foo=bar\r\n", + ], + ]); + $rulesFromPath = Rules::fromPath(dirname(__DIR__).'/test_data/public_suffix_list.dat', $context); + + self::assertEquals(self::$rules, $rulesFromPath); + } + + public function testCreateFromPathThrowsException(): void + { + $this->expectException(UnableToLoadResource::class); + + Rules::fromPath('/foo/bar.dat'); + } + + public function testCreateFromPathThrowsExceptionIfTheContentIsInvalid(): void + { + $this->expectException(UnableToLoadPublicSuffixList::class); + + Rules::fromPath(dirname(__DIR__).'/test_data/invalid_suffix_list_content.dat'); + } + + public function testDomainInternalPhpMethod(): void + { + /** @var Rules $generateRules */ + $generateRules = eval('return '.var_export(self::$rules, true).';'); + + self::assertEquals(self::$rules, $generateRules); + } + + public function testNullWillReturnNullDomain(): void + { + $domain = self::$rules->resolve('COM'); + + self::assertFalse($domain->suffix()->isKnown()); + } + + public function testIsSuffixValidFalse(): void + { + $domain = self::$rules->resolve('www.example.faketld'); + + self::assertFalse($domain->suffix()->isKnown()); + } + + public function testIsSuffixValidTrue(): void + { + $domain = self::$rules->resolve('www.example.com'); + + self::assertTrue($domain->suffix()->isKnown()); + self::assertTrue($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + } + + public function testIsSuffixValidFalseWithPunycoded(): void + { + $domain = self::$rules->resolve('www.example.xn--85x722f'); + + self::assertFalse($domain->suffix()->isKnown()); + self::assertFalse($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + } + + public function testSubDomainIsNull(): void + { + $domain = self::$rules->resolve('ulb.ac.be'); + + self::assertTrue($domain->suffix()->isKnown()); + self::assertTrue($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + } + + public function testWithExceptionName(): void + { + $domain = self::$rules->resolve('_b%C3%A9bé.be-'); + + self::assertNull($domain->value()); + } + + public function testWithPrivateDomain(): void + { + $domain = self::$rules->resolve('thephpleague.github.io'); + + self::assertTrue($domain->suffix()->isKnown()); + self::assertFalse($domain->suffix()->isICANN()); + self::assertTrue($domain->suffix()->isPrivate()); + self::assertSame('github.io', $domain->suffix()->value()); + } + + public function testWithAbsoluteHostInvalid(): void + { + $domain = self::$rules->resolve('private.ulb.ac.be.'); + + self::assertSame('private.ulb.ac.be.', $domain->value()); + self::assertTrue($domain->suffix()->isKnown()); + self::assertTrue($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + self::assertSame('ac.be', $domain->suffix()->value()); + } + + public function testWithICANNDomainInvalid(): void + { + $domain = 'example.invalidICANNTLD'; + + $this->expectException(UnableToResolveDomain::class); + $this->expectExceptionMessage('The domain "'.strtolower($domain).'" does not contain a "ICANN" TLD.'); + + self::$rules->getICANNDomain($domain); + } + + public function testWithPrivateDomainInvalid(): void + { + $domain = 'private.ulb.ac.be'; + + $this->expectException(UnableToResolveDomain::class); + $this->expectExceptionMessage('The domain "'.$domain.'" does not contain a "private" TLD.'); + + self::$rules->getPrivateDomain($domain); + } + + public function testWithPrivateDomainValid(): void + { + $domain = self::$rules->getPrivateDomain('thephpleague.github.io'); + + self::assertSame('thephpleague.github.io', $domain->value()); + self::assertTrue($domain->suffix()->isKnown()); + self::assertFalse($domain->suffix()->isICANN()); + self::assertTrue($domain->suffix()->isPrivate()); + self::assertSame('github.io', $domain->suffix()->value()); + } + + public function testResolvingICANNDomainInvalid(): void + { + $domain = self::$rules->resolve('private.ulb.ac.be'); + + self::assertSame('private.ulb.ac.be', $domain->value()); + self::assertTrue($domain->suffix()->isKnown()); + self::assertTrue($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + self::assertSame('ac.be', $domain->suffix()->value()); + } + + public function testWithDomainObject(): void + { + $domain = ResolvedDomain::fromICANN('private.ulb.ac.be', 2); + + $newDomain = self::$rules->resolve($domain); + + self::assertSame('private.ulb.ac.be', $domain->value()); + self::assertTrue($domain->suffix()->isKnown()); + self::assertTrue($domain->suffix()->isICANN()); + self::assertFalse($domain->suffix()->isPrivate()); + self::assertSame('ac.be', $domain->suffix()->value()); + self::assertEquals($domain, $newDomain); + } + + public function testWithDomainInterfaceObject(): void + { + $domain = Suffix::fromICANN('ulb.ac.be'); + + self::assertSame( + 'ac.be', + self::$rules->getCookieDomain($domain)->suffix()->value() + ); + } + + #[DataProvider('parseDataProvider')] + public function testGetRegistrableDomain(?string $publicSuffix, ?string $registrableDomain, string $domain, ?string $expectedDomain): void + { + self::assertSame($registrableDomain, self::$rules->resolve($domain)->registrableDomain()->value()); + } + + #[DataProvider('parseDataProvider')] + public function testGetPublicSuffix(?string $publicSuffix, ?string $registrableDomain, string $domain, ?string $expectedDomain): void + { + self::assertSame($publicSuffix, self::$rules->resolve($domain)->suffix()->value()); + } + + #[DataProvider('parseDataProvider')] + public function testGetDomain(?string $publicSuffix, ?string $registrableDomain, string $domain, ?string $expectedDomain): void + { + self::assertSame($expectedDomain, self::$rules->resolve($domain)->value()); + } + + /** + * @return iterable + */ + public static function parseDataProvider(): iterable + { + return [ + // public suffix, registrable domain, domain + // BEGIN https://github.com/jeremykendall/php-domain-parser/issues/16 + 'com tld' => [ + 'publicSuffix' => 'com', + 'registrableDomain' => 'example.com', + 'domain' => 'us.example.com', + 'expectedDomain' => 'us.example.com', + ], + 'na tld' => [ + 'publicSuffix' => 'na', + 'registrableDomain' => 'example.na', + 'domain' => 'us.example.na', + 'expectedDomain' => 'us.example.na', + ], + 'us.na tld' => [ + 'publicSuffix' => 'us.na', + 'registrableDomain' => 'example.us.na', + 'domain' => 'www.example.us.na', + 'expectedDomain' => 'www.example.us.na', + ], + 'org tld' => [ + 'publicSuffix' => 'org', + 'registrableDomain' => 'example.org', + 'domain' => 'us.example.org', + 'expectedDomain' => 'us.example.org', + ], + 'biz tld (1)' => [ + 'publicSuffix' => 'biz', + 'registrableDomain' => 'broken.biz', + 'domain' => 'webhop.broken.biz', + 'expectedDomain' => 'webhop.broken.biz', + ], + 'biz tld (2)' => [ + 'publicSuffix' => 'webhop.biz', + 'registrableDomain' => 'broken.webhop.biz', + 'domain' => 'www.broken.webhop.biz', + 'expectedDomain' => 'www.broken.webhop.biz', + ], + // END https://github.com/jeremykendall/php-domain-parser/issues/16 + // Test ipv6 URL + 'IP (1)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '[::1]', + 'expectedDomain' => null, ], + 'IP (2)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '[2001:db8:85a3:8d3:1319:8a2e:370:7348]', + 'expectedDomain' => null, + ], + 'IP (3)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '[2001:db8:85a3:8d3:1319:8a2e:370:7348]', + 'expectedDomain' => null, + ], + // Test IP address: Fixes #43 + 'IP (4)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '192.168.1.2', + 'expectedDomain' => null, + ], + // Link-local addresses and zone indices + 'IP (5)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '[fe80::3%25eth0]', + 'expectedDomain' => null, ], + 'IP (6)' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => '[fe80::1%2511]', + 'expectedDomain' => null, + ], + 'fake tld' => [ + 'publicSuffix' => 'faketld', + 'registrableDomain' => 'example.faketld', + 'domain' => 'example.faketld', + 'expectedDomain' => 'example.faketld', + ], + 'fake tld with space' => [ + 'publicSuffix' => null, + 'registrableDomain' => null, + 'domain' => 'fake.t ld', + 'expectedDomain' => null, + ], + ]; + } + + public function testGetPublicSuffixThrowsCouldNotResolvePublicSuffix(): void + { + $this->expectException(UnableToResolveDomain::class); + + self::$rules->getICANNDomain('localhost'); + } + + #[DataProvider('invalidDomainParseProvider')] + public function testGetPublicSuffixThrowsInvalidDomainException(string $domain): void + { + $this->expectException(SyntaxError::class); + + self::$rules->getICANNDomain($domain); + } + + /** + * @return iterable + */ + public static function invalidDomainParseProvider(): iterable + { + return [ + 'IPv6' => ['[::1]'], + 'IPv4' => ['192.168.1.2'], + 'invalid host: label too long' => [implode('', array_fill(0, 64, 'a')).'.com'], + ]; + } + + #[DataProvider('invalidHostParseProvider')] + public function testGetPublicSuffixThrowsInvalidHostException(string $domain): void + { + $this->expectException(SyntaxError::class); + + self::$rules->getICANNDomain($domain); + } + + /** + * @return iterable + */ + public static function invalidHostParseProvider(): iterable + { + $longLabel = implode('.', array_fill(0, 62, 'a')); + + return [ + 'multiple label with URI delimiter' => ['local.ho/st'], + 'invalid host: invalid label according to RFC3986' => ['www.fußball.com-'], + 'invalid host: host contains space' => ['re view.com'], + 'invalid host: host too long' => ["$longLabel.$longLabel.$longLabel. $longLabel.$longLabel"], + ]; + } + + #[DataProvider('validPublicSectionProvider')] + public function testPublicSuffixSection(?string $domain, ?string $expected): void + { + self::assertSame($expected, self::$rules->getCookieDomain($domain)->suffix()->value()); + } + + /** + * @return iterable + */ + public static function validPublicSectionProvider(): iterable + { + return [ + 'idn domain' => [ + 'domain' => 'Яндекс.РФ', + 'expected' => 'рф', + ], + 'ascii domain' => [ + 'domain' => 'ulb.ac.be', + 'expected' => 'ac.be', + ], + 'unknown tld' => [ + 'domain' => 'yours.truly.faketld', + 'expected' => 'faketld', + ], + ]; + } + + /** + * This is my version of the checkPublicSuffix function referred to in the + * test instructions at the Public Suffix List project. + * + * "You will need to define a checkPublicSuffix() function which takes as a + * parameter a domain name and the public suffix, runs your implementation + * on the domain name and checks the result is the public suffix expected." + * + * @see http://publicsuffix.org/list/ + */ + public function checkPublicSuffix(?string $input, ?string $expected): void + { + self::assertSame($expected, self::$rules->resolve($input)->registrableDomain()->value()); + } + + /** + * This test case is based on the test data linked at + * http://publicsuffix.org/list/ and provided by Rob Strading of Comodo. + * + * @see http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1 + */ + public function testPublicSuffixSpec(): void + { + // Test data from Rob Stradling at Comodo + // http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1 + // Any copyright is dedicated to the Public Domain. + // http://creativecommons.org/publicdomain/zero/1.0/ + + // null input. + $this->checkPublicSuffix(null, null); + // Mixed case. + $this->checkPublicSuffix('COM', null); + $this->checkPublicSuffix('example.COM', 'example.com'); + $this->checkPublicSuffix('WwW.example.COM', 'example.com'); + // Leading dot. + $this->checkPublicSuffix('.com', null); + $this->checkPublicSuffix('.example', null); + $this->checkPublicSuffix('.example.com', null); + $this->checkPublicSuffix('.example.example', null); + // Unlisted TLD. + // Addresses algorithm rule #2: If no rules match, the prevailing rule is "*". + $this->checkPublicSuffix('example', null); + $this->checkPublicSuffix('example.example', 'example.example'); + $this->checkPublicSuffix('b.example.example', 'example.example'); + $this->checkPublicSuffix('a.b.example.example', 'example.example'); + // TLD with only 1 rule. + $this->checkPublicSuffix('biz', null); + $this->checkPublicSuffix('domain.biz', 'domain.biz'); + $this->checkPublicSuffix('b.domain.biz', 'domain.biz'); + $this->checkPublicSuffix('a.b.domain.biz', 'domain.biz'); + // TLD with some 2-level rules. + $this->checkPublicSuffix('com', null); + $this->checkPublicSuffix('example.com', 'example.com'); + $this->checkPublicSuffix('b.example.com', 'example.com'); + $this->checkPublicSuffix('a.b.example.com', 'example.com'); + + /* REPLACE uk.com by ac.be because uk.com is a PRIVATE DOMAIN */ + $this->checkPublicSuffix('ac.be', null); + $this->checkPublicSuffix('ulb.ac.be', 'ulb.ac.be'); + $this->checkPublicSuffix('b.ulb.ac.be', 'ulb.ac.be'); + $this->checkPublicSuffix('a.b.ulb.ac.be', 'ulb.ac.be'); + + $this->checkPublicSuffix('test.ac', 'test.ac'); + // TLD with only 1 (wildcard) rule. + $this->checkPublicSuffix('mm', null); + $this->checkPublicSuffix('c.mm', null); + $this->checkPublicSuffix('b.c.mm', 'b.c.mm'); + $this->checkPublicSuffix('a.b.c.mm', 'b.c.mm'); + // More complex TLD. + $this->checkPublicSuffix('jp', null); + $this->checkPublicSuffix('test.jp', 'test.jp'); + $this->checkPublicSuffix('www.test.jp', 'test.jp'); + $this->checkPublicSuffix('ac.jp', null); + $this->checkPublicSuffix('test.ac.jp', 'test.ac.jp'); + $this->checkPublicSuffix('www.test.ac.jp', 'test.ac.jp'); + $this->checkPublicSuffix('kyoto.jp', null); + $this->checkPublicSuffix('test.kyoto.jp', 'test.kyoto.jp'); + $this->checkPublicSuffix('ide.kyoto.jp', null); + $this->checkPublicSuffix('b.ide.kyoto.jp', 'b.ide.kyoto.jp'); + $this->checkPublicSuffix('a.b.ide.kyoto.jp', 'b.ide.kyoto.jp'); + $this->checkPublicSuffix('c.kobe.jp', null); + $this->checkPublicSuffix('b.c.kobe.jp', 'b.c.kobe.jp'); + $this->checkPublicSuffix('a.b.c.kobe.jp', 'b.c.kobe.jp'); + $this->checkPublicSuffix('city.kobe.jp', 'city.kobe.jp'); + $this->checkPublicSuffix('www.city.kobe.jp', 'city.kobe.jp'); + // TLD with a wildcard rule and exceptions. + $this->checkPublicSuffix('ck', null); + $this->checkPublicSuffix('test.ck', null); + $this->checkPublicSuffix('b.test.ck', 'b.test.ck'); + $this->checkPublicSuffix('a.b.test.ck', 'b.test.ck'); + $this->checkPublicSuffix('www.ck', 'www.ck'); + $this->checkPublicSuffix('www.www.ck', 'www.ck'); + // US K12. + $this->checkPublicSuffix('us', null); + $this->checkPublicSuffix('test.us', 'test.us'); + $this->checkPublicSuffix('www.test.us', 'test.us'); + $this->checkPublicSuffix('ak.us', null); + $this->checkPublicSuffix('test.ak.us', 'test.ak.us'); + $this->checkPublicSuffix('www.test.ak.us', 'test.ak.us'); + $this->checkPublicSuffix('k12.ak.us', null); + $this->checkPublicSuffix('test.k12.ak.us', 'test.k12.ak.us'); + $this->checkPublicSuffix('www.test.k12.ak.us', 'test.k12.ak.us'); + // IDN labels. + $this->checkPublicSuffix('食狮.com.cn', '食狮.com.cn'); + $this->checkPublicSuffix('食狮.公司.cn', '食狮.公司.cn'); + $this->checkPublicSuffix('www.食狮.公司.cn', '食狮.公司.cn'); + $this->checkPublicSuffix('shishi.公司.cn', 'shishi.公司.cn'); + $this->checkPublicSuffix('公司.cn', null); + $this->checkPublicSuffix('食狮.中国', '食狮.中国'); + $this->checkPublicSuffix('www.食狮.中国', '食狮.中国'); + $this->checkPublicSuffix('shishi.中国', 'shishi.中国'); + $this->checkPublicSuffix('中国', null); + // Same as above, but punycoded. + $this->checkPublicSuffix('xn--85x722f.com.cn', 'xn--85x722f.com.cn'); + $this->checkPublicSuffix('xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); + $this->checkPublicSuffix('www.xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); + $this->checkPublicSuffix('shishi.xn--55qx5d.cn', 'shishi.xn--55qx5d.cn'); + $this->checkPublicSuffix('xn--55qx5d.cn', null); + $this->checkPublicSuffix('xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); + $this->checkPublicSuffix('www.xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); + $this->checkPublicSuffix('shishi.xn--fiqs8s', 'shishi.xn--fiqs8s'); + $this->checkPublicSuffix('xn--fiqs8s', null); + } + + #[DataProvider('effectiveTLDProvider')] + public function testEffectiveTLDResolution(string $host, string $cookieETLD, string $icannETLD, string $privateETLD): void + { + self::assertSame($cookieETLD, self::$rules->getCookieDomain($host)->suffix()->toString()); + self::assertSame($icannETLD, self::$rules->getICANNDomain($host)->suffix()->toString()); + self::assertSame($privateETLD, self::$rules->getPrivateDomain($host)->suffix()->toString()); + } + + /** + * @return iterable + */ + public static function effectiveTLDProvider(): iterable + { + return [ + 'private domain effective TLD' => [ + 'host' => 'myblog.blogspot.com', + 'cookieETLD' => 'blogspot.com', + 'icannETLD' => 'com', + 'privateETLD' => 'blogspot.com', + ], + ]; + } + + public function testIssue321Success(): void + { + $result = self::$rules->resolve('node857-gelofesta.users.scale.virtualcloud.com.br'); + self::assertSame('users.scale.virtualcloud.com.br', $result->suffix()->value()); + self::assertTrue($result->suffix()->isPrivate()); + + $result = self::$rules->resolve('clientportal.virtualcloud.com.br'); + self::assertSame('com.br', $result->suffix()->value()); + self::assertTrue($result->suffix()->isICANN()); + } + + public function testIssue321Failure(): void + { + $this->expectException(UnableToResolveDomain::class); + + self::$rules->getPrivateDomain('clientportal.virtualcloud.com.br'); + } + + public function testWithMultiLevelPrivateDomain(): void + { + $domain = self::$rules->resolve('test-domain.eu.org'); + + self::assertFalse($domain->suffix()->isICANN()); + self::assertTrue($domain->suffix()->isPrivate()); + self::assertSame('eu.org', $domain->suffix()->value()); + + $domain = self::$rules->resolve('test-domain.lt.eu.org'); + + self::assertFalse($domain->suffix()->isICANN()); + self::assertTrue($domain->suffix()->isPrivate()); + self::assertSame('lt.eu.org', $domain->suffix()->value()); + } + + #[DataProvider('privateDomainWithWildcardProvider')] + public function testWithPrivateDomainThatHasWildcardSubdomain(string $inputDomain, string $expectedSuffix): void + { + $domain = self::$rules->getPrivateDomain($inputDomain); + + self::assertSame($expectedSuffix, $domain->suffix()->value()); + self::assertFalse($domain->suffix()->isICANN()); + self::assertTrue($domain->suffix()->isPrivate()); + } + + /** + * @return iterable + */ + public static function privateDomainWithWildcardProvider(): iterable + { + return [ + 'appspot subdomain' => [ + 'inputDomain' => 'test-domain.de.r.appspot.com', + 'expectedSuffix' => 'de.r.appspot.com', + ], + 'appspot root domain' => [ + 'inputDomain' => 'test-domain.appspot.com', + 'expectedSuffix' => 'appspot.com', + ], + 'qcx subdomain' => [ + 'inputDomain' => 'test-domain.de.sys.qcx.io', + 'expectedSuffix' => 'de.sys.qcx.io', + ], + 'qcx root domain' => [ + 'inputDomain' => 'test-domain.qcx.io', + 'expectedSuffix' => 'qcx.io', + ], + ]; + } +} diff --git a/src/Storage/PsrStorageFactory.php b/src/Storage/PsrStorageFactory.php new file mode 100644 index 00000000..5245f7de --- /dev/null +++ b/src/Storage/PsrStorageFactory.php @@ -0,0 +1,48 @@ +cache, $cachePrefix, $cacheTtl), + new PublicSuffixListPsr18Client($this->client, $this->requestFactory) + ); + } + + /** + * @param DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl + */ + public function createTopLevelDomainListStorage(string $cachePrefix = '', $cacheTtl = null): TopLevelDomainListStorage + { + return new TopLevelDomainsStorage( + new TopLevelDomainListPsr16Cache($this->cache, $cachePrefix, $cacheTtl), + new TopLevelDomainListPsr18Client($this->client, $this->requestFactory) + ); + } +} diff --git a/src/Storage/PsrStorageFactoryTest.php b/src/Storage/PsrStorageFactoryTest.php new file mode 100644 index 00000000..efa782f9 --- /dev/null +++ b/src/Storage/PsrStorageFactoryTest.php @@ -0,0 +1,38 @@ +factory = new PsrStorageFactory($cache, $client, $requestFactory); + } + + public function testItCanReturnARootZoneDatabaseStorageInstance(): void + { + $instance = $this->factory->createTopLevelDomainListStorage('foobar', '1 DAY'); + + self::assertInstanceOf(TopLevelDomainsStorage::class, $instance); + } + + public function testItCanReturnAPublicSuffixListStorageInstance(): void + { + $instance = $this->factory->createPublicSuffixListStorage('foobar', '1 DAY'); + + self::assertInstanceOf(RulesStorage::class, $instance); + } +} diff --git a/src/Storage/PublicSuffixListCache.php b/src/Storage/PublicSuffixListCache.php new file mode 100644 index 00000000..e5525611 --- /dev/null +++ b/src/Storage/PublicSuffixListCache.php @@ -0,0 +1,31 @@ +cacheTtl = TimeToLive::convert($cacheTtl); + } + + public function fetch(string $uri): ?PublicSuffixList + { + $cacheKey = $this->cacheKey($uri); + $publicSuffixList = $this->cache->get($cacheKey); + if (null === $publicSuffixList) { + return null; + } + + if (!$publicSuffixList instanceof PublicSuffixList) { + $this->cache->delete($cacheKey); + + return null; + } + + return $publicSuffixList; + } + + /** + * Returns the cache key according to the source URL. + */ + private function cacheKey(string $str): string + { + return $this->cachePrefix.md5(strtolower($str)); + } + + public function remember(string $uri, PublicSuffixList $publicSuffixList): bool + { + try { + return $this->cache->set($this->cacheKey($uri), $publicSuffixList, $this->cacheTtl); + } catch (Throwable $exception) { + if ($exception instanceof CacheException) { + return false; + } + + throw $exception; + } + } + + public function forget(string $uri): bool + { + return $this->cache->delete($this->cacheKey($uri)); + } +} diff --git a/src/Storage/PublicSuffixListPsr16CacheTest.php b/src/Storage/PublicSuffixListPsr16CacheTest.php new file mode 100644 index 00000000..686294b8 --- /dev/null +++ b/src/Storage/PublicSuffixListPsr16CacheTest.php @@ -0,0 +1,167 @@ +method('get')->willReturn(null); + + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', '1 DAY'); + + self::assertNull($pslCache->fetch('http://www.example.com')); + } + + public function testItReturnsAnInstanceIfTheCorrectCacheExists(): void + { + $rules = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn($rules); + + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', 86400); + + self::assertEquals($rules, $pslCache->fetch('http://www.example.com')); + } + + public function testItReturnsNullIfTheCacheContentContainsInvalidJsonData(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn('foobar'); + + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', 86400); + self::assertNull($pslCache->fetch('http://www.example.com')); + } + + public function testItReturnsNullIfTheCacheContentCannotBeConvertedToTheCorrectInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn('{"foo":"bar"}'); + + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new DateTimeImmutable('+1 DAY')); + + self::assertNull($pslCache->fetch('http://www.example.com')); + } + + public function testItCanStoreAPublicSuffixListInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->willReturn(true); + + $psl = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertTrue($pslCache->remember('http://www.example.com', $psl)); + } + + public function testItReturnsFalseIfItCantStoreAPublicSuffixListInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->willReturn(false); + + $psl = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertFalse($pslCache->remember('http://www.example.com', $psl)); + } + + public function testItReturnsFalseIfItCantCacheAPublicSuffixListInstance(): void + { + $exception = new class ('Something went wrong.', 0) extends RuntimeException implements CacheException { + }; + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->will(self::throwException($exception)); + + $psl = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertFalse($pslCache->remember('http://www.example.com', $psl)); + } + + public function testItWillThrowIfItCantCacheAPublicSuffixListInstance(): void + { + $exception = new class ('Something went wrong.', 0) extends RuntimeException { + }; + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->will(self::throwException($exception)); + + $psl = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + $pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new class () { + public function __toString(): string + { + return '1 DAY'; + } + }); + $this->expectException(RuntimeException::class); + + $pslCache->remember('http://www.example.com', $psl); + } + + public function testItCanDeleteTheCachedDatabase(): void + { + $uri = 'http://www.example.com'; + + $cache = self::createStub(CacheInterface::class); + $cache->method('delete')->willReturn(true); + + $instance = new PublicSuffixListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + self::assertTrue($instance->forget($uri)); + } + + public function testItWillThrowIfTheTTLIsNotParsable(): void + { + $this->expectException(InvalidArgumentException::class); + + $cache = self::createStub(CacheInterface::class); + new PublicSuffixListPsr16Cache($cache, 'pdp_', 'foobar'); + } + + protected function restoreExceptionHandler(): void + { + while (true) { + $previousHandler = set_exception_handler(static fn () => null); + restore_exception_handler(); + if (null === $previousHandler) { + break; + } + + restore_exception_handler(); + } + } + + protected function restoreErrorHandler(): void + { + while (true) { + $previousHandler = set_error_handler(static fn (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) => null); + restore_error_handler(); + $isPhpUnitErrorHandler = ($previousHandler instanceof ErrorHandler); + if (null === $previousHandler || $isPhpUnitErrorHandler) { + break; + } + restore_error_handler(); + } + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->restoreErrorHandler(); + $this->restoreExceptionHandler(); + } +} diff --git a/src/Storage/PublicSuffixListPsr18Client.php b/src/Storage/PublicSuffixListPsr18Client.php new file mode 100644 index 00000000..aea583f0 --- /dev/null +++ b/src/Storage/PublicSuffixListPsr18Client.php @@ -0,0 +1,37 @@ +requestFactory->createRequest('GET', $uri); + try { + $response = $this->client->sendRequest($request); + } catch (ClientExceptionInterface $exception) { + throw UnableToLoadResource::dueToUnavailableService($uri, $exception); + } + + if (400 <= $response->getStatusCode()) { + throw UnableToLoadResource::dueToUnexpectedStatusCode($uri, $response->getStatusCode()); + } + + return Rules::fromString($response->getBody()); + } +} diff --git a/src/Storage/PublicSuffixListPsr18ClientTest.php b/src/Storage/PublicSuffixListPsr18ClientTest.php new file mode 100644 index 00000000..eb4b2373 --- /dev/null +++ b/src/Storage/PublicSuffixListPsr18ClientTest.php @@ -0,0 +1,93 @@ +get('http://www.example.com'); + + self::assertInstanceOf(Rules::class, $psl); + } + + public function testItWillThrowIfTheClientCanNotConnectToTheRemoteURI(): void + { + $client = new class () implements ClientInterface { + public function sendRequest(RequestInterface $request): ResponseInterface + { + throw new ConnectException('foobar', $request, null); + } + }; + + $requestFactory = new class () implements RequestFactoryInterface { + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + }; + + $this->expectException(UnableToLoadResource::class); + $this->expectExceptionMessage('Could not access the URI: `http://www.example.com`.'); + + $storage = new PublicSuffixListPsr18Client($client, $requestFactory); + $storage->get('http://www.example.com'); + } + + public function testItWillThrowIfTheReturnedStatusCodeIsNotOK(): void + { + $client = new class () implements ClientInterface { + public function sendRequest(RequestInterface $request): ResponseInterface + { + return new Response(404); + } + }; + + $requestFactory = new class () implements RequestFactoryInterface { + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + }; + + $this->expectException(UnableToLoadResource::class); + $this->expectExceptionMessage('Invalid response from URI: `http://www.example.com`.'); + $this->expectExceptionCode(404); + + $storage = new PublicSuffixListPsr18Client($client, $requestFactory); + $storage->get('http://www.example.com'); + } +} diff --git a/src/Storage/PublicSuffixListStorage.php b/src/Storage/PublicSuffixListStorage.php new file mode 100644 index 00000000..dcb2337a --- /dev/null +++ b/src/Storage/PublicSuffixListStorage.php @@ -0,0 +1,10 @@ +cache->fetch($uri); + if (null !== $publicSuffixList) { + return $publicSuffixList; + } + + $publicSuffixList = $this->client->get($uri); + + $this->cache->remember($uri, $publicSuffixList); + + return $publicSuffixList; + } + + public function delete(string $uri): bool + { + return $this->cache->forget($uri); + } +} diff --git a/src/Storage/RulesStorageTest.php b/src/Storage/RulesStorageTest.php new file mode 100644 index 00000000..8606ffe3 --- /dev/null +++ b/src/Storage/RulesStorageTest.php @@ -0,0 +1,111 @@ +get('http://www.example.com'); + + self::assertInstanceOf(Rules::class, $psl); + } + + public function testIsCanReturnAPublicSuffixListInstanceFromTheInnerStorage(): void + { + $cache = new class () implements PublicSuffixListCache { + public function fetch(string $uri): ?PublicSuffixList + { + return null; + } + + public function remember(string $uri, PublicSuffixList $publicSuffixList): bool + { + return true; + } + + public function forget(string $uri): bool + { + return true; + } + }; + + $client = new class () implements PublicSuffixListClient { + public function get(string $uri): PublicSuffixList + { + return Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + } + }; + + $storage = new RulesStorage($cache, $client); + $psl = $storage->get('http://www.example.com'); + + self::assertInstanceOf(Rules::class, $psl); + } + + public function testIsCanDeleteAPublicSuffixListInstanceFromTheInnerStorage(): void + { + $cache = new class () implements PublicSuffixListCache { + public function fetch(string $uri): ?PublicSuffixList + { + return null; + } + + public function remember(string $uri, PublicSuffixList $publicSuffixList): bool + { + return true; + } + + public function forget(string $uri): bool + { + return 'http://www.example.com' === $uri; + } + }; + + $client = new class () implements PublicSuffixListClient { + public function get(string $uri): PublicSuffixList + { + return Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat'); + } + }; + + $storage = new RulesStorage($cache, $client); + $storage->get('http://www.example.com'); + + self::assertTrue($storage->delete('http://www.example.com')); + self::assertFalse($storage->delete('https://www.example.com')); + } +} diff --git a/src/Storage/TimeToLive.php b/src/Storage/TimeToLive.php new file mode 100644 index 00000000..6d0289fc --- /dev/null +++ b/src/Storage/TimeToLive.php @@ -0,0 +1,105 @@ + true); + $interval = DateInterval::createFromDateString($duration); + restore_error_handler(); + if (!$interval instanceof DateInterval) { + throw new InvalidArgumentException( + 'The ttl value "'.$duration.'" can not be parsable by `DateInterval::createFromDateString`.' + ); + } + + } catch (Throwable $exception) { + if (!$exception instanceof InvalidArgumentException) { + throw new InvalidArgumentException( + 'The ttl value "'.$duration.'" can not be parsable by `DateInterval::createFromDateString`.', + 0, + $exception + ); + } + + throw $exception; + } + + return $interval; + } + + public static function until(DateTimeInterface $date): DateInterval + { + return (new DateTimeImmutable('NOW', $date->getTimezone()))->diff($date, false); + } + + /** + * Returns a DateInterval relative to the current date and time. + * + * DEPRECATION WARNING! This method will be removed in the next major point release + * + * @deprecated 6.1.0 deprecated + * @codeCoverageIgnore + * @see TimeToLive::until + */ + public static function fromDateTimeInterface(DateTimeInterface $date): DateInterval + { + return self::until($date); + } + + /** + * Returns a DateInterval from string parsing. + * + * DEPRECATION WARNING! This method will be removed in the next major point release + * + * @deprecated 6.1.0 deprecated + * @see TimeToLive::fromDurationString + * @codeCoverageIgnore + * + * @throws InvalidArgumentException if the value can not be parsable + * + */ + public static function fromScalar(Stringable|int|string $duration): DateInterval + { + return self::fromDurationString((string) $duration); + } + + /** + * Convert the input data into a DateInterval object or null. + * + * @throws InvalidArgumentException if the value can not be computed + */ + public static function convert(DateInterval|DateTimeInterface|Stringable|int|string|null $ttl): ?DateInterval + { + if ($ttl instanceof Stringable) { + $ttl = (string) $ttl; + } + + return match (true) { + $ttl instanceof DateInterval || null === $ttl => $ttl, + $ttl instanceof DateTimeInterface => self::until($ttl), + is_int($ttl) => self::fromDurationString($ttl.' seconds'), + false !== ($seconds = filter_var($ttl, FILTER_VALIDATE_INT)) => self::fromDurationString($seconds.' seconds'), + default => self::fromDurationString($ttl), + }; + } +} diff --git a/src/Storage/TimeToLiveTest.php b/src/Storage/TimeToLiveTest.php new file mode 100644 index 00000000..43d7bff8 --- /dev/null +++ b/src/Storage/TimeToLiveTest.php @@ -0,0 +1,103 @@ +invert); + self::assertSame(0, TimeToLive::until($tomorrow)->invert); + } + + #[DataProvider('validDurationString')] + public function testItCanBeInstantiatedFromDurationInput(string $input, DateInterval $expected): void + { + $now = new DateTimeImmutable(); + + self::assertEquals($now->add($expected), $now->add(TimeToLive::fromDurationString($input))); + } + + /** + * @return iterable + */ + public static function validDurationString(): iterable + { + $threeDays = new DateInterval('P3D'); + + yield 'string' => [ + 'input' => '3 days', + 'expected' => $threeDays, + ]; + + yield 'stringable negative days' => [ + 'input' => '-3 days', + 'expected' => DateInterval::createFromDateString('-3 DAYS'), + ]; + } + + public function testItCastToNullWithNull(): void + { + self::assertNull(TimeToLive::convert(null)); + } + + #[DataProvider('validDurationInt')] + public function testItCanBeInstantiatedFromSeconds(int|string|Stringable|DateInterval $input, DateInterval $expected): void + { + /** @var DateInterval $ttl */ + $ttl = TimeToLive::convert($input); + $now = new DateTimeImmutable(); + + self::assertEquals($now->add($expected), $now->add($ttl)); + } + + /** + * @return iterable + */ + public static function validDurationInt(): iterable + { + $seconds = new DateInterval('PT2345S'); + + yield 'DateInterval' => [ + 'input' => $seconds, + 'expected' => $seconds, + ]; + + yield 'stringable object' => [ + 'input' => new class () { + public function __toString(): string + { + return '2345'; + } + }, + 'expected' => $seconds, + ]; + + yield 'numeric string' => [ + 'input' => '2345', + 'expected' => $seconds, + ]; + + yield 'seconds' => [ + 'input' => 2345, + 'expected' => $seconds, + ]; + + yield 'negative seconds' => [ + 'input' => '-2345', + 'expected' => DateInterval::createFromDateString('-2345 seconds'), + ]; + } +} diff --git a/src/Storage/TopLevelDomainListCache.php b/src/Storage/TopLevelDomainListCache.php new file mode 100644 index 00000000..2d168785 --- /dev/null +++ b/src/Storage/TopLevelDomainListCache.php @@ -0,0 +1,31 @@ +cacheTtl = TimeToLive::convert($cacheTtl); + } + + public function fetch(string $uri): ?TopLevelDomainList + { + $cacheKey = $this->cacheKey($uri); + $topLevelDomainList = $this->cache->get($cacheKey); + if (null === $topLevelDomainList) { + return null; + } + + if (!$topLevelDomainList instanceof TopLevelDomainList) { + $this->cache->delete($cacheKey); + + return null; + } + + return $topLevelDomainList; + } + + /** + * Returns the cache key according to the source URL. + */ + private function cacheKey(string $str): string + { + return $this->cachePrefix.md5(strtolower($str)); + } + + public function remember(string $uri, TopLevelDomainList $topLevelDomainList): bool + { + try { + return $this->cache->set($this->cacheKey($uri), $topLevelDomainList, $this->cacheTtl); + } catch (Throwable $exception) { + if ($exception instanceof CacheException) { + return false; + } + + throw $exception; + } + } + + public function forget(string $uri): bool + { + return $this->cache->delete($this->cacheKey($uri)); + } +} diff --git a/src/Storage/TopLevelDomainListPsr16CacheTest.php b/src/Storage/TopLevelDomainListPsr16CacheTest.php new file mode 100644 index 00000000..fc911446 --- /dev/null +++ b/src/Storage/TopLevelDomainListPsr16CacheTest.php @@ -0,0 +1,166 @@ +method('get')->willReturn(null); + + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', '1 DAY'); + + self::assertNull($instance->fetch('http://www.example.com')); + } + + public function testItReturnsAnInstanceIfTheCorrectCacheExists(): void + { + $topLevelDomainList = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn($topLevelDomainList); + + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', 86400); + + self::assertEquals($topLevelDomainList, $instance->fetch('http://www.example.com')); + } + + public function testItReturnsNullIfTheCacheContentContainsInvalidJsonData(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn('foobar'); + + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertNull($instance->fetch('http://www.example.com')); + } + + public function testItReturnsNullIfTheCacheContentCannotBeConvertedToTheCorrectInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('get')->willReturn('{"foo":"bar"}'); + + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateTimeImmutable('+1 DAY')); + + self::assertNull($instance->fetch('http://www.example.com')); + } + + public function testItCanStoreAPublicSuffixListInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->willReturn(true); + + $rzd = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertTrue($instance->remember('http://www.example.com', $rzd)); + } + + public function testItReturnsFalseIfItCantStoreAPublicSuffixListInstance(): void + { + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->willReturn(false); + + $rzd = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertFalse($instance->remember('http://www.example.com', $rzd)); + } + + public function testItReturnsFalseIfItCantCacheATopLevelDomainListInstance(): void + { + $exception = new class ('Something went wrong.', 0) extends RuntimeException implements CacheException { + }; + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->will(self::throwException($exception)); + + $rzd = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + self::assertFalse($instance->remember('http://www.example.com', $rzd)); + } + + public function testItThrowsIfItCantCacheATopLevelDomainListInstance(): void + { + $exception = new class ('Something went wrong.', 0) extends RuntimeException { + }; + $cache = self::createStub(CacheInterface::class); + $cache->method('set')->will(self::throwException($exception)); + + $rzd = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + + $this->expectException(RuntimeException::class); + + $instance->remember('http://www.example.com', $rzd); + } + + public function testItCanDeleteTheCachedDatabase(): void + { + $uri = 'http://www.example.com'; + + $cache = self::createStub(CacheInterface::class); + $cache->method('delete')->willReturn(true); + + $instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D')); + self::assertTrue($instance->forget($uri)); + } + + public function testItWillThrowIfTheTTLIsNotParsable(): void + { + $this->expectException(InvalidArgumentException::class); + + $cache = self::createStub(CacheInterface::class); + new TopLevelDomainListPsr16Cache($cache, 'pdp_', 'foobar'); + } + + + + protected function restoreExceptionHandler(): void + { + while (true) { + $previousHandler = set_exception_handler(static fn () => null); + restore_exception_handler(); + if (null === $previousHandler) { + break; + } + + restore_exception_handler(); + } + } + + protected function restoreErrorHandler(): void + { + while (true) { + $previousHandler = set_error_handler(static fn (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) => null); + restore_error_handler(); + $isPhpUnitErrorHandler = ($previousHandler instanceof ErrorHandler); + if (null === $previousHandler || $isPhpUnitErrorHandler) { + break; + } + restore_error_handler(); + } + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->restoreErrorHandler(); + $this->restoreExceptionHandler(); + } +} diff --git a/src/Storage/TopLevelDomainListPsr18Client.php b/src/Storage/TopLevelDomainListPsr18Client.php new file mode 100644 index 00000000..90c9d752 --- /dev/null +++ b/src/Storage/TopLevelDomainListPsr18Client.php @@ -0,0 +1,37 @@ +requestFactory->createRequest('GET', $uri); + try { + $response = $this->client->sendRequest($request); + } catch (ClientExceptionInterface $exception) { + throw UnableToLoadResource::dueToUnavailableService($uri, $exception); + } + + if (400 <= $response->getStatusCode()) { + throw UnableToLoadResource::dueToUnexpectedStatusCode($uri, $response->getStatusCode()); + } + + return TopLevelDomains::fromString($response->getBody()); + } +} diff --git a/src/Storage/TopLevelDomainListPsr18ClientTest.php b/src/Storage/TopLevelDomainListPsr18ClientTest.php new file mode 100644 index 00000000..eb5a5b47 --- /dev/null +++ b/src/Storage/TopLevelDomainListPsr18ClientTest.php @@ -0,0 +1,94 @@ +get('http://www.example.com'); + + self::assertInstanceOf(TopLevelDomains::class, $rzd); + } + + public function testItWillThrowIfTheClientCanNotConnectToTheRemoteURI(): void + { + $client = new class () implements ClientInterface { + public function sendRequest(RequestInterface $request): ResponseInterface + { + throw new ConnectException('foobar', $request, null); + } + }; + + $requestFactory = new class () implements RequestFactoryInterface { + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + }; + + $this->expectException(UnableToLoadResource::class); + $this->expectExceptionMessage('Could not access the URI: `http://www.example.com`.'); + + $storage = new TopLevelDomainListPsr18Client($client, $requestFactory); + $storage->get('http://www.example.com'); + } + + public function testItWillThrowIfTheReturnedStatusCodeIsNotOK(): void + { + $client = new class () implements ClientInterface { + public function sendRequest(RequestInterface $request): ResponseInterface + { + return new Response(404); + } + }; + + $requestFactory = new class () implements RequestFactoryInterface { + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + }; + + $this->expectException(UnableToLoadResource::class); + $this->expectExceptionMessage('Invalid response from URI: `http://www.example.com`.'); + $this->expectExceptionCode(404); + + $storage = new TopLevelDomainListPsr18Client($client, $requestFactory); + $storage->get('http://www.example.com'); + } +} diff --git a/src/Storage/TopLevelDomainListStorage.php b/src/Storage/TopLevelDomainListStorage.php new file mode 100644 index 00000000..7fb312d1 --- /dev/null +++ b/src/Storage/TopLevelDomainListStorage.php @@ -0,0 +1,10 @@ +cache->fetch($uri); + if (null !== $topLevelDomains) { + return $topLevelDomains; + } + + $topLevelDomains = $this->client->get($uri); + + $this->cache->remember($uri, $topLevelDomains); + + return $topLevelDomains; + } + + public function delete(string $uri): bool + { + return $this->cache->forget($uri); + } +} diff --git a/src/Storage/TopLevelDomainsStorageTest.php b/src/Storage/TopLevelDomainsStorageTest.php new file mode 100644 index 00000000..2da00d18 --- /dev/null +++ b/src/Storage/TopLevelDomainsStorageTest.php @@ -0,0 +1,109 @@ +get('http://www.example.com')); + } + + public function testIsCanReturnARootZoneDatabaseInstanceFromTheInnerStorage(): void + { + $cache = new class () implements TopLevelDomainListCache { + public function fetch(string $uri): ?TopLevelDomainList + { + return null; + } + + public function remember(string $uri, TopLevelDomainList $topLevelDomainList): bool + { + return true; + } + + public function forget(string $uri): bool + { + return true; + } + }; + + $client = new class () implements TopLevelDomainListClient { + public function get(string $uri): TopLevelDomainList + { + return TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + } + }; + + $storage = new TopLevelDomainsStorage($cache, $client); + + self::assertInstanceOf(TopLevelDomains::class, $storage->get('http://www.example.com')); + } + + public function testIsCanDeleteARootZoneDatabaseInstanceFromTheInnerStorage(): void + { + $cache = new class () implements TopLevelDomainListCache { + public function fetch(string $uri): ?TopLevelDomainList + { + return null; + } + + public function remember(string $uri, TopLevelDomainList $topLevelDomainList): bool + { + return true; + } + + public function forget(string $uri): bool + { + return 'http://www.example.com' === $uri; + } + }; + + $client = new class () implements TopLevelDomainListClient { + public function get(string $uri): TopLevelDomainList + { + return TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt'); + } + }; + + $storage = new TopLevelDomainsStorage($cache, $client); + $storage->get('http://www.example.com'); + + self::assertTrue($storage->delete('http://www.example.com')); + self::assertFalse($storage->delete('https://www.example.com')); + } +} diff --git a/src/Stream.php b/src/Stream.php new file mode 100644 index 00000000..253b9b69 --- /dev/null +++ b/src/Stream.php @@ -0,0 +1,54 @@ + true); + $stream = fopen(...$args); + restore_error_handler(); + + return $stream; + } +} diff --git a/src/Suffix.php b/src/Suffix.php new file mode 100644 index 00000000..6a4989dd --- /dev/null +++ b/src/Suffix.php @@ -0,0 +1,172 @@ + count($domain)) { + throw SyntaxError::dueToInvalidSuffix($domain, self::ICANN); + } + + return new self($domain, self::ICANN); + } + + /** + * @throws CannotProcessHost + */ + public static function fromPrivate(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + $domain = self::setDomainName($domain); + if (1 > count($domain)) { + throw SyntaxError::dueToInvalidSuffix($domain, self::PRIVATE); + } + + return new self($domain, self::PRIVATE); + } + + /** + * @throws CannotProcessHost + */ + public static function fromIANA(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + $domain = self::setDomainName($domain); + if (1 !== count($domain)) { + throw SyntaxError::dueToInvalidSuffix($domain, self::IANA); + } + + return new self($domain, self::IANA); + } + + /** + * @throws CannotProcessHost + */ + public static function fromUnknown(DomainNameProvider|Host|Stringable|string|int|null $domain): self + { + return new self(self::setDomainName($domain), self::UNKNOWN); + } + + /** + * @throws CannotProcessHost + */ + private static function setDomainName(int|DomainNameProvider|Host|string|Stringable|null $domain): DomainName + { + if ($domain instanceof DomainNameProvider) { + $domain = $domain->domain(); + } + + if (!$domain instanceof DomainName) { + $domain = RegisteredName::fromIDNA2008($domain); + } + + if ($domain->isAbsolute()) { + throw SyntaxError::dueToInvalidSuffix($domain); + } + + return $domain; + } + + public function isKnown(): bool + { + return self::UNKNOWN !== $this->section; + } + + public function isIANA(): bool + { + return self::IANA === $this->section; + } + + public function isPublicSuffix(): bool + { + return in_array($this->section, [self::ICANN, self::PRIVATE], true); + } + + public function isICANN(): bool + { + return self::ICANN === $this->section; + } + + public function isPrivate(): bool + { + return self::PRIVATE === $this->section; + } + + public function domain(): DomainName + { + return $this->domain; + } + + public function count(): int + { + return count($this->domain); + } + + public function jsonSerialize(): ?string + { + return $this->domain->jsonSerialize(); + } + + public function value(): ?string + { + return $this->domain->value(); + } + + public function toString(): string + { + return $this->domain->toString(); + } + + public function toAscii(): self + { + return new self($this->domain->toAscii(), $this->section); + } + + public function toUnicode(): self + { + return new self($this->domain->toUnicode(), $this->section); + } + + /** + * @throws CannotProcessHost + */ + public function normalize(DomainName $domain): self + { + $newDomain = $domain->clear()->append($this->toUnicode()); + if ($domain->isAscii()) { + $newDomain = $newDomain->toAscii(); + } + + return new self($newDomain, $this->section); + } +} diff --git a/src/SuffixTest.php b/src/SuffixTest.php new file mode 100644 index 00000000..bf472667 --- /dev/null +++ b/src/SuffixTest.php @@ -0,0 +1,151 @@ +domain(), $newDomain->domain()); + self::assertNotEquals($domain->isICANN(), $newDomain->isICANN()); + } + + public function testInternalPhpMethod(): void + { + $publicSuffix = Suffix::fromICANN('ac.be'); + /** @var Suffix $generatePublicSuffix */ + $generatePublicSuffix = eval('return '.var_export($publicSuffix, true).';'); + self::assertEquals($publicSuffix, $generatePublicSuffix); + self::assertEquals('"ac.be"', json_encode($publicSuffix)); + self::assertSame('ac.be', $publicSuffix->toString()); + } + + public function testPSToUnicodeWithUrlEncode(): void + { + self::assertSame('bébe', Suffix::fromUnknown('b%C3%A9be')->toUnicode()->value()); + } + + #[DataProvider('invalidPublicSuffixProvider')] + public function testConstructorThrowsException(string $publicSuffix): void + { + $this->expectException(SyntaxError::class); + + Suffix::fromUnknown($publicSuffix); + } + + /** + * @return iterable> + */ + public static function invalidPublicSuffixProvider(): iterable + { + return [ + 'empty string' => [''], + 'absolute host' => ['foo.'], + ]; + } + + public function testFromICANN(): void + { + $suffix = Suffix::fromICANN('be'); + + self::assertTrue($suffix->isKnown()); + self::assertTrue($suffix->isPublicSuffix()); + self::assertTrue($suffix->isICANN()); + self::assertFalse($suffix->isPrivate()); + self::assertFalse($suffix->isIANA()); + self::assertSame('be', $suffix->domain()->toString()); + $this->expectException(SyntaxError::class); + + Suffix::fromICANN(null); + } + + public function testFromPrivate(): void + { + $suffix = Suffix::fromPrivate('be'); + + self::assertTrue($suffix->isKnown()); + self::assertTrue($suffix->isPublicSuffix()); + self::assertFalse($suffix->isICANN()); + self::assertTrue($suffix->isPrivate()); + self::assertFalse($suffix->isIANA()); + self::assertSame('be', $suffix->domain()->toString()); + + $this->expectException(SyntaxError::class); + + Suffix::fromPrivate(null); + } + + public function testFromIANA(): void + { + $suffix = Suffix::fromIANA('be'); + + self::assertTrue($suffix->isKnown()); + self::assertFalse($suffix->isPublicSuffix()); + self::assertFalse($suffix->isICANN()); + self::assertFalse($suffix->isPrivate()); + self::assertTrue($suffix->isIANA()); + self::assertSame('be', $suffix->domain()->toString()); + + $this->expectException(SyntaxError::class); + + Suffix::fromIANA('ac.be'); + } + + #[DataProvider('conversionReturnsTheSameInstanceProvider')] + public function testConversionReturnsTheSameInstance(?string $publicSuffix): void + { + $instance = Suffix::fromUnknown($publicSuffix); + + self::assertEquals($instance->toUnicode(), $instance); + self::assertEquals($instance->toAscii(), $instance); + } + + /** + * @return iterable + */ + public static function conversionReturnsTheSameInstanceProvider(): iterable + { + return [ + 'ascii only domain' => ['ac.be'], + 'null domain' => [null], + ]; + } + + public function testToUnicodeReturnsSameInstance(): void + { + $instance = Suffix::fromUnknown('食狮.公司.cn'); + + self::assertEquals($instance->toUnicode(), $instance); + } + + #[DataProvider('countableProvider')] + public function testCountable(?string $domain, int $nbLabels): void + { + $domain = Suffix::fromUnknown($domain); + + self::assertCount($nbLabels, $domain); + } + + /** + * @return iterable}> + */ + public static function countableProvider(): iterable + { + return [ + 'null' => [null, 0, []], + 'simple' => ['foo.bar.baz', 3, ['baz', 'bar', 'foo']], + 'unicode' => ['www.食狮.公司.cn', 4, ['cn', '公司', '食狮', 'www']], + 'ipv4 like' => ['1.2.3.4', 4, ['1', '2', '3', '4']], + ]; + } +} diff --git a/src/SyntaxError.php b/src/SyntaxError.php new file mode 100644 index 00000000..b8827d53 --- /dev/null +++ b/src/SyntaxError.php @@ -0,0 +1,54 @@ +value() ?? 'NULL').'"` is invalid.'); + } + + return new self('The suffix `"'.($publicSuffix->value() ?? 'NULL').'"` is an invalid `'.$type.'` suffix.'); + } + + public static function dueToUnsupportedType(string $domain): self + { + return new self('The domain `'.$domain.'` is invalid: this is an IPv4 host.'); + } + + public static function dueToInvalidLabelKey(Host $domain, int $key): self + { + return new self('the given key `'.$key.'` is invalid for the domain `'.($domain->value() ?? 'NULL').'`.'); + } + + public function idnaInfo(): ?IdnaInfo + { + return $this->idnaInfo; + } +} diff --git a/src/TopLevelDomainList.php b/src/TopLevelDomainList.php new file mode 100644 index 00000000..1ca3eb5b --- /dev/null +++ b/src/TopLevelDomainList.php @@ -0,0 +1,47 @@ + + */ +interface TopLevelDomainList extends Countable, DomainNameResolver, IteratorAggregate +{ + /** + * Returns the Version ID. + */ + public function version(): string; + + /** + * Returns the List Last Modified Date. + */ + public function lastUpdated(): DateTimeImmutable; + + + public function count(): int; + + /** + * Tells whether the list is empty. + */ + public function isEmpty(): bool; + + /** + * @return Iterator + */ + public function getIterator(): Iterator; + + /** + * Returns PSL info for a given domain against the PSL rules for ICANN domain detection. + * + * @throws SyntaxError if the domain is invalid + * @throws UnableToResolveDomain if the domain does not contain a IANA Effective TLD + */ + public function getIANADomain(Host $host): ResolvedDomainName; +} diff --git a/src/TopLevelDomains.php b/src/TopLevelDomains.php new file mode 100644 index 00000000..98384c24 --- /dev/null +++ b/src/TopLevelDomains.php @@ -0,0 +1,219 @@ +\d+), Last Updated (?.*?)$/'; + + /** + * @param array $records + */ + private function __construct( + private readonly array $records, + private readonly string $version, + private readonly DateTimeImmutable $lastUpdated + ) { + } + + /** + * Returns a new instance from a file path. + * + * @param null|resource $context + * + * @throws UnableToLoadResource If the rules can not be loaded from the path + * @throws UnableToLoadTopLevelDomainList If the content is invalid or can not be correctly parsed and converted + */ + public static function fromPath(string $path, $context = null): self + { + return self::fromString(Stream::getContentAsString($path, $context)); + } + + /** + * Returns a new instance from a string. + * + * @throws UnableToLoadTopLevelDomainList if the content is invalid or can not be correctly parsed and converted + */ + public static function fromString(Stringable|string $content): self + { + $data = self::parse((string) $content); + + return new self($data['records'], $data['version'], $data['lastUpdated']); + } + + /** + * Converts the IANA Top Level Domain List into a TopLevelDomains associative array. + * + * @throws UnableToLoadTopLevelDomainList if the content is invalid or can not be correctly parsed and converted + * + * @return array{version:string, lastUpdated:DateTimeImmutable, records:array} + */ + public static function parse(string $content): array + { + $data = []; + $file = new SplTempFileObject(); + $file->fwrite($content); + $file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY); + /** @var string $line */ + foreach ($file as $line) { + $line = trim($line); + if ([] === $data) { + $data = self::extractHeader($line) + ['records' => []]; + continue; + } + + if (!str_contains($line, '#')) { + $data['records'][self::extractRootZone($line)] = 1; + continue; + } + + throw UnableToLoadTopLevelDomainList::dueToInvalidLine($line); + } + + if (isset($data['version'], $data['lastUpdated'], $data['records'])) { + return $data; + } + + throw UnableToLoadTopLevelDomainList::dueToFailedConversion(); + } + + /** + * Extract IANA Top Level Domain List header info. + * + * @throws UnableToLoadTopLevelDomainList if the Header line is invalid + * + * @return array{version:string, lastUpdated:DateTimeImmutable} + */ + private static function extractHeader(string $content): array + { + if (1 !== preg_match(self::REGEXP_HEADER_LINE, $content, $matches)) { + throw UnableToLoadTopLevelDomainList::dueToInvalidVersionLine($content); + } + + /** @var DateTimeImmutable $date */ + $date = DateTimeImmutable::createFromFormat(self::IANA_DATE_FORMAT, $matches['date']); + + return [ + 'version' => $matches['version'], + 'lastUpdated' => $date, + ]; + } + + /** + * Extract IANA Root Zone. + * + * @throws UnableToLoadTopLevelDomainList If the Top Level Domain is invalid + */ + private static function extractRootZone(string $content): string + { + try { + $tld = Suffix::fromIANA($content); + } catch (CannotProcessHost $exception) { + throw UnableToLoadTopLevelDomainList::dueToInvalidTopLevelDomain($content, $exception); + } + + return $tld->toAscii()->toString(); + } + + /** + * @param array{records:array, version:string, lastUpdated:DateTimeImmutable} $properties + */ + public static function __set_state(array $properties): self + { + return new self($properties['records'], $properties['version'], $properties['lastUpdated']); + } + + public function version(): string + { + return $this->version; + } + + public function lastUpdated(): DateTimeImmutable + { + return $this->lastUpdated; + } + + public function count(): int + { + return count($this->records); + } + + public function isEmpty(): bool + { + return [] === $this->records; + } + + /** + * @return Iterator + */ + public function getIterator(): Iterator + { + yield from array_keys($this->records); + } + + public function resolve(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + try { + $domain = $this->validateDomain($host); + if ($this->containsTopLevelDomain($domain->withoutRootLabel())) { + return ResolvedDomain::fromIANA($domain); + } + return ResolvedDomain::fromUnknown($domain); + } catch (UnableToResolveDomain $exception) { + return ResolvedDomain::fromUnknown($exception->domain()); + } catch (SyntaxError $exception) { + return ResolvedDomain::fromUnknown(null); + } + } + + /** + * Assert the domain is valid and is resolvable. + * + * @throws SyntaxError If the domain is invalid + * @throws UnableToResolveDomain If the domain can not be resolved + */ + private function validateDomain(DomainNameProvider|Host|Stringable|string|int|null $domain): DomainName + { + if ($domain instanceof DomainNameProvider) { + $domain = $domain->domain(); + } + + if (!$domain instanceof DomainName) { + $domain = Domain::fromIDNA2008($domain); + } + + if (null === $domain->label(0)) { + throw UnableToResolveDomain::dueToUnresolvableDomain($domain); + } + + return $domain; + } + + private function containsTopLevelDomain(DomainName $domain): bool + { + return isset($this->records[$domain->toAscii()->label(0)]); + } + + public function getIANADomain(DomainNameProvider|Host|Stringable|string|int|null $host): ResolvedDomainName + { + $domain = $this->validateDomain($host); + if (!$this->containsTopLevelDomain($domain->withoutRootLabel())) { + throw UnableToResolveDomain::dueToMissingSuffix($domain, 'IANA'); + } + + return ResolvedDomain::fromIANA($domain); + } +} diff --git a/src/TopLevelDomainsTest.php b/src/TopLevelDomainsTest.php new file mode 100644 index 00000000..e756c6c1 --- /dev/null +++ b/src/TopLevelDomainsTest.php @@ -0,0 +1,307 @@ + [ + 'method' => 'GET', + 'header' => "Accept-language: en\r\nCookie: foo=bar\r\n", + ], + ]); + + $topLevelDomains = TopLevelDomains::fromPath(dirname(__DIR__).'/test_data/tlds-alpha-by-domain.txt', $context); + + self::assertEquals(self::$topLevelDomains, $topLevelDomains); + } + + public function testCreateFromPathThrowsException(): void + { + $this->expectException(UnableToLoadResource::class); + + TopLevelDomains::fromPath('/foo/bar.dat'); + } + + #[DataProvider('invalidContentProvider')] + public function testConverterThrowsException(string $content): void + { + $this->expectException(UnableToLoadTopLevelDomainList::class); + + TopLevelDomains::fromString($content); + } + + /** + * @return iterable + */ + public static function invalidContentProvider(): iterable + { + $doubleHeader = << [$doubleHeader], + 'invalid header' => [$invalidHeader], + 'empty content' => [''], + 'header not on the first line' => [$headerNoFirstLine], + 'invalid tld content' => [$invalidTldContent], + 'invalid root zone' => [$invalidTldContentNotRootZone], + 'empty tld' => [$invalidTldContentEmptyTld], + ]; + } + + public function testSetState(): void + { + /** @var TopLevelDomains $topLevelDomains */ + $topLevelDomains = eval('return '.var_export(self::$topLevelDomains, true).';'); + + self::assertEquals(self::$topLevelDomains, $topLevelDomains); + } + + public function testGetterProperties(): void + { + $topLevelDomains = TopLevelDomains::fromPath(dirname(__DIR__).'/test_data/root_zones.dat'); + + self::assertCount(15, $topLevelDomains); + self::assertSame('2018082200', $topLevelDomains->version()); + self::assertEquals( + new DateTimeImmutable('2018-08-22 07:07:01', new DateTimeZone('UTC')), + $topLevelDomains->lastUpdated() + ); + self::assertFalse($topLevelDomains->isEmpty()); + } + + public function testIterator(): void + { + foreach (self::$topLevelDomains as $tld) { + self::assertStringNotContainsString($tld, '.'); + } + } + + #[DataProvider('validDomainProvider')] + public function testResolve(DomainNameProvider|Host|Stringable|string|int|null $tld): void + { + self::assertSame( + Domain::fromIDNA2008($tld)->label(0), + self::$topLevelDomains->resolve($tld)->suffix()->value() + ); + } + + #[DataProvider('validDomainProvider')] + public function testGetTopLevelDomain(DomainNameProvider|Host|Stringable|string|int|null $tld): void + { + self::assertSame( + Domain::fromIDNA2008($tld)->label(0), + self::$topLevelDomains->getIANADomain($tld)->suffix()->value() + ); + } + + /** + * @return iterable> + */ + public static function validDomainProvider(): iterable + { + $resolvedDomain = ResolvedDomain::fromICANN(Domain::fromIDNA2008('www.example.com'), 1); + + return [ + 'simple domain' => ['GOOGLE.COM'], + 'case insensitive domain (1)' => ['GooGlE.com'], + 'case insensitive domain (2)' => ['gooGle.coM'], + 'case insensitive domain (3)' => ['GooGLE.CoM'], + 'IDN to ASCII domain' => ['GOOGLE.XN--VERMGENSBERATUNG-PWB'], + 'Unicode domain (1)' => ['الاعلى-للاتصالات.قطر'], + 'Unicode domain (2)' => ['кто.рф'], + 'Unicode domain (3)' => ['Deutsche.Vermögensberatung.vermögensberater'], + 'object with __toString method' => [new class () { + public function __toString(): string + { + return 'www.இந.இந்தியா'; + } + }], + 'external domain name' => [$resolvedDomain], + ]; + } + + public function testTopLevelDomainWithInvalidDomain(): void + { + $this->expectException(SyntaxError::class); + + self::$topLevelDomains->getIANADomain('###'); + } + + public function testResolveWithInvalidDomain(): void + { + $result = self::$topLevelDomains->resolve('###'); + self::assertFalse($result->suffix()->isIANA()); + self::assertNull($result->value()); + } + + public function testResolveWithAbsoluteDomainName(): void + { + $result = self::$topLevelDomains->resolve('example.com.'); + self::assertSame('example.com.', $result->value()); + self::assertTrue($result->suffix()->isIANA()); + self::assertSame('com', $result->suffix()->value()); + } + + public function testTopLevelDomainWithUnResolvableDomain(): void + { + $this->expectException(UnableToResolveDomain::class); + + self::$topLevelDomains->getIANADomain('localhost'); + } + + public function testTopLevelDomainWithUnResolvableDomain2(): void + { + $this->expectException(UnableToResolveDomain::class); + + self::$topLevelDomains->getIANADomain('localhost.'); + } + + public function testResolveWithUnResolvableDomain(): void + { + $result = self::$topLevelDomains->resolve('localhost'); + + self::assertSame($result->toString(), 'localhost'); + self::assertNull($result->suffix()->value()); + self::assertFalse($result->suffix()->isIANA()); + } + + public function testGetTopLevelDomainWithUnResolvableDomain(): void + { + $this->expectException(UnableToResolveDomain::class); + + self::$topLevelDomains->getIANADomain('localhost'); + } + + public function testResolveWithUnregisteredTLD(): void + { + $collection = TopLevelDomains::fromPath(dirname(__DIR__).'/test_data/root_zones.dat'); + + self::assertNull($collection->resolve('localhost.locale')->suffix()->value()); + } + + public function testGetTopLevelDomainWithUnregisteredTLD(): void + { + $this->expectException(UnableToResolveDomain::class); + + $collection = TopLevelDomains::fromPath(dirname(__DIR__).'/test_data/root_zones.dat'); + $collection->getIANADomain('localhost.locale'); + } + + /** + * @return iterable> + */ + public static function validTldProvider(): iterable + { + return [ + 'simple TLD' => ['COM'], + 'case insenstive detection (1)' => ['cOm'], + 'case insenstive detection (2)' => ['CoM'], + 'case insenstive detection (3)' => ['com'], + 'IDN to ASCI TLD' => ['XN--CLCHC0EA0B2G2A9GCD'], + 'Unicode TLD (1)' => ['المغرب'], + 'Unicode TLD (2)' => ['مليسيا'], + 'Unicode TLD (3)' => ['рф'], + 'Unicode TLD (4)' => ['இந்தியா'], + 'Unicode TLD (5)' => ['vermögensberater'], + 'object with __toString method' => [new class () { + public function __toString(): string + { + return 'COM'; + } + }], + 'externalDomain' => [Suffix::fromICANN('com')], + ]; + } + + /** + * @return iterable> + */ + public static function invalidTldProvider(): iterable + { + return [ + 'invalid TLD (1)' => ['COMM'], + 'invalid TLD with leading dot' => ['.CCOM'], + 'invalid TLD case insensitive' => ['cCoM'], + 'invalid TLD case insensitive with leading dot' => ['.cCoM'], + 'invalid TLD (2)' => ['BLABLA'], + 'invalid TLD (3)' => ['CO M'], + 'invalid TLD (4)' => ['D.E'], + 'invalid Unicode TLD' => ['CÖM'], + 'invalid IDN to ASCII' => ['XN--TTT'], + 'invalid IDN to ASCII with leading dot' => ['.XN--TTT'], + 'null' => [null], + 'object with __toString method' => [new class () { + public function __toString(): string + { + return 'COMMM'; + } + }], + ]; + } +} diff --git a/src/UnableToLoadPublicSuffixList.php b/src/UnableToLoadPublicSuffixList.php new file mode 100644 index 00000000..442916b2 --- /dev/null +++ b/src/UnableToLoadPublicSuffixList.php @@ -0,0 +1,16 @@ +domain = $domain; + } + + public static function dueToInvalidSecondLevelDomain(DomainName $domain): self + { + return new self('The submitted Second Level Domain is invalid `'.($domain->value() ?? 'NULL').'`; it should contains only one label.', $domain); + } + + public static function dueToIdenticalValue(DomainName $domain): self + { + return new self('The public suffix and the domain name are identical `'.$domain->toString().'`.', $domain); + } + + public static function dueToMissingSuffix(DomainName $domain, string $type): self + { + return new self('The domain "'.($domain->value() ?? 'NULL').'" does not contain a "'.$type.'" TLD.', $domain); + } + + public static function dueToUnresolvableDomain(DomainName $domain): self + { + return new self('The domain "'.($domain->value() ?? 'NULL').'" can not contain a public suffix.', $domain); + } + + public static function dueToMissingRegistrableDomain(DomainName $domain): self + { + return new self('A subdomain can not be added to a domain "'.($domain->value() ?? 'NULL').'" without a registrable domain part.', $domain); + } + + public function domain(): ?DomainName + { + return $this->domain; + } +} diff --git a/src/pdp-parse-url.php b/src/pdp-parse-url.php deleted file mode 100644 index 11ff60f9..00000000 --- a/src/pdp-parse-url.php +++ /dev/null @@ -1,62 +0,0 @@ - $value) { - if ($name === 'scheme') { - continue; - } - - $parts[$name] = urldecode($value); - } - } else { - $parts = urldecode($parts); - } - - return $parts; - } - } -} diff --git a/test_data/invalid_suffix_list_content.dat b/test_data/invalid_suffix_list_content.dat new file mode 100644 index 00000000..3312f098 --- /dev/null +++ b/test_data/invalid_suffix_list_content.dat @@ -0,0 +1,10 @@ +// ===BEGIN ICANN DOMAINS=== +com +a⒈com +// ===END ICANN DOMAINS=== + +// ===BEGIN PRIVATE DOMAINS=== +github.io +githubusercontent.com +gitlab.io +// ===END PRIVATE DOMAINS=== diff --git a/data/public-suffix-list.txt b/test_data/public_suffix_list.dat similarity index 60% rename from data/public-suffix-list.txt rename to test_data/public_suffix_list.dat index ee0269c3..086b8dcc 100644 --- a/data/public-suffix-list.txt +++ b/test_data/public_suffix_list.dat @@ -1,10 +1,15 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, +// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. + +// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. // ===BEGIN ICANN DOMAINS=== -// ac : http://en.wikipedia.org/wiki/.ac +// ac : https://en.wikipedia.org/wiki/.ac ac com.ac edu.ac @@ -13,11 +18,11 @@ net.ac mil.ac org.ac -// ad : http://en.wikipedia.org/wiki/.ad +// ad : https://en.wikipedia.org/wiki/.ad ad nom.ad -// ae : http://en.wikipedia.org/wiki/.ae +// ae : https://en.wikipedia.org/wiki/.ae // see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php ae co.ae @@ -28,7 +33,7 @@ ac.ae gov.ae mil.ae -// aero : see http://www.information.aero/index.php?id=66 +// aero : see https://www.information.aero/index.php?id=66 aero accident-investigation.aero accident-prevention.aero @@ -74,7 +79,6 @@ exchange.aero express.aero federation.aero flight.aero -freight.aero fuel.aero gliding.aero government.aero @@ -150,10 +154,15 @@ mil.al net.al org.al -// am : http://en.wikipedia.org/wiki/.am +// am : https://www.amnic.net/policy/en/Policy_EN.pdf am +co.am +com.am +commune.am +net.am +org.am -// ao : http://en.wikipedia.org/wiki/.ao +// ao : https://en.wikipedia.org/wiki/.ao // http://www.dns.ao/REGISTR.DOC ao ed.ao @@ -163,22 +172,27 @@ co.ao pb.ao it.ao -// aq : http://en.wikipedia.org/wiki/.aq +// aq : https://en.wikipedia.org/wiki/.aq aq -// ar : https://nic.ar/normativa-vigente.xhtml +// ar : https://nic.ar/es/nic-argentina/normativa ar +bet.ar com.ar +coop.ar edu.ar gob.ar gov.ar int.ar mil.ar +musica.ar +mutual.ar net.ar org.ar +senasa.ar tur.ar -// arpa : http://en.wikipedia.org/wiki/.arpa +// arpa : https://en.wikipedia.org/wiki/.arpa // Confirmed by registry 2008-06-18 arpa e164.arpa @@ -188,22 +202,23 @@ iris.arpa uri.arpa urn.arpa -// as : http://en.wikipedia.org/wiki/.as +// as : https://en.wikipedia.org/wiki/.as as gov.as -// asia : http://en.wikipedia.org/wiki/.asia +// asia : https://en.wikipedia.org/wiki/.asia asia -// at : http://en.wikipedia.org/wiki/.at +// at : https://en.wikipedia.org/wiki/.at // Confirmed by registry 2008-06-17 at ac.at co.at gv.at or.at +sth.ac.at -// au : http://en.wikipedia.org/wiki/.au +// au : https://en.wikipedia.org/wiki/.au // http://www.auda.org.au/ au // 2LDs @@ -229,6 +244,8 @@ vic.au wa.au // 3LDs act.edu.au +catholic.edu.au +// eq.edu.au - Removed at the request of the Queensland Department of Education nsw.edu.au nt.edu.au qld.edu.au @@ -244,15 +261,18 @@ sa.gov.au tas.gov.au vic.gov.au wa.gov.au +// 4LDs +// education.tas.edu.au - Removed at the request of the Department of Education Tasmania +schools.nsw.edu.au -// aw : http://en.wikipedia.org/wiki/.aw +// aw : https://en.wikipedia.org/wiki/.aw aw com.aw -// ax : http://en.wikipedia.org/wiki/.ax +// ax : https://en.wikipedia.org/wiki/.ax ax -// az : http://en.wikipedia.org/wiki/.az +// az : https://en.wikipedia.org/wiki/.az az com.az net.az @@ -267,20 +287,16 @@ name.az pro.az biz.az -// ba : http://en.wikipedia.org/wiki/.ba +// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf ba -org.ba -net.ba +com.ba edu.ba gov.ba mil.ba -unsa.ba -unbi.ba -co.ba -com.ba -rs.ba +net.ba +org.ba -// bb : http://en.wikipedia.org/wiki/.bb +// bb : https://en.wikipedia.org/wiki/.bb bb biz.bb co.bb @@ -293,19 +309,19 @@ org.bb store.bb tv.bb -// bd : http://en.wikipedia.org/wiki/.bd +// bd : https://en.wikipedia.org/wiki/.bd *.bd -// be : http://en.wikipedia.org/wiki/.be +// be : https://en.wikipedia.org/wiki/.be // Confirmed by registry 2008-06-08 be ac.be -// bf : http://en.wikipedia.org/wiki/.bf +// bf : https://en.wikipedia.org/wiki/.bf bf gov.bf -// bg : http://en.wikipedia.org/wiki/.bg +// bg : https://en.wikipedia.org/wiki/.bg // https://www.register.bg/user/static/rules/en/index.html bg a.bg @@ -345,7 +361,7 @@ z.bg 8.bg 9.bg -// bh : http://en.wikipedia.org/wiki/.bh +// bh : https://en.wikipedia.org/wiki/.bh bh com.bh edu.bh @@ -353,7 +369,7 @@ net.bh org.bh gov.bh -// bi : http://en.wikipedia.org/wiki/.bi +// bi : https://en.wikipedia.org/wiki/.bi // http://whois.nic.bi/ bi co.bi @@ -362,10 +378,10 @@ edu.bi or.bi org.bi -// biz : http://en.wikipedia.org/wiki/.biz +// biz : https://en.wikipedia.org/wiki/.biz biz -// bj : http://en.wikipedia.org/wiki/.bj +// bj : https://en.wikipedia.org/wiki/.bj bj asso.bj barreau.bj @@ -379,91 +395,228 @@ gov.bm net.bm org.bm -// bn : http://en.wikipedia.org/wiki/.bn -*.bn +// bn : http://www.bnnic.bn/faqs +bn +com.bn +edu.bn +gov.bn +net.bn +org.bn -// bo : http://www.nic.bo/ +// bo : https://nic.bo/delegacion2015.php#h-1.10 bo com.bo edu.bo -gov.bo gob.bo int.bo org.bo net.bo mil.bo tv.bo +web.bo +// Social Domains +academia.bo +agro.bo +arte.bo +blog.bo +bolivia.bo +ciencia.bo +cooperativa.bo +democracia.bo +deporte.bo +ecologia.bo +economia.bo +empresa.bo +indigena.bo +industria.bo +info.bo +medicina.bo +movimiento.bo +musica.bo +natural.bo +nombre.bo +noticias.bo +patria.bo +politica.bo +profesional.bo +plurinacional.bo +pueblo.bo +revista.bo +salud.bo +tecnologia.bo +tksat.bo +transporte.bo +wiki.bo // br : http://registro.br/dominio/categoria.html // Submitted by registry br +9guacu.br +abc.br adm.br adv.br agr.br +aju.br am.br +anani.br +aparecida.br +app.br arq.br art.br ato.br b.br +barueri.br +belem.br +bhz.br +bib.br bio.br blog.br bmd.br +boavista.br +bsb.br +campinagrande.br +campinas.br +caxias.br cim.br cng.br cnt.br com.br +contagem.br coop.br +coz.br +cri.br +cuiaba.br +curitiba.br +def.br +des.br +det.br +dev.br ecn.br eco.br edu.br emp.br +enf.br eng.br esp.br etc.br eti.br far.br +feira.br flog.br +floripa.br fm.br fnd.br +fortal.br fot.br +foz.br fst.br g12.br +geo.br ggf.br +goiania.br gov.br +// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil +ac.gov.br +al.gov.br +am.gov.br +ap.gov.br +ba.gov.br +ce.gov.br +df.gov.br +es.gov.br +go.gov.br +ma.gov.br +mg.gov.br +ms.gov.br +mt.gov.br +pa.gov.br +pb.gov.br +pe.gov.br +pi.gov.br +pr.gov.br +rj.gov.br +rn.gov.br +ro.gov.br +rr.gov.br +rs.gov.br +sc.gov.br +se.gov.br +sp.gov.br +to.gov.br +gru.br imb.br ind.br inf.br +jab.br +jampa.br +jdf.br +joinville.br jor.br jus.br leg.br lel.br +log.br +londrina.br +macapa.br +maceio.br +manaus.br +maringa.br mat.br med.br mil.br +morena.br mp.br mus.br +natal.br net.br +niteroi.br *.nom.br not.br ntr.br odo.br +ong.br org.br +osasco.br +palmas.br +poa.br ppg.br pro.br psc.br psi.br +pvh.br qsl.br radio.br rec.br +recife.br +rep.br +ribeirao.br +rio.br +riobranco.br +riopreto.br +salvador.br +sampa.br +santamaria.br +santoandre.br +saobernardo.br +saogonca.br +seg.br +sjc.br slg.br +slz.br +sorocaba.br srv.br taxi.br +tc.br +tec.br teo.br +the.br tmp.br trd.br tur.br tv.br +udi.br vet.br +vix.br vlog.br wiki.br zlg.br @@ -476,7 +629,7 @@ org.bs edu.bs gov.bs -// bt : http://en.wikipedia.org/wiki/.bt +// bt : https://en.wikipedia.org/wiki/.bt bt com.bt edu.bt @@ -488,14 +641,14 @@ org.bt // Submitted by registry bv -// bw : http://en.wikipedia.org/wiki/.bw +// bw : https://en.wikipedia.org/wiki/.bw // http://www.gobin.info/domainname/bw.doc // list of other 2nd level tlds ? bw co.bw org.bw -// by : http://en.wikipedia.org/wiki/.by +// by : https://en.wikipedia.org/wiki/.by // http://tld.by/rules_2006_en.html // list of other 2nd level tlds ? by @@ -509,7 +662,7 @@ com.by // http://hoster.by/ of.by -// bz : http://en.wikipedia.org/wiki/.bz +// bz : https://en.wikipedia.org/wiki/.bz // http://www.belizenic.bz/ bz com.bz @@ -518,7 +671,7 @@ org.bz edu.bz gov.bz -// ca : http://en.wikipedia.org/wiki/.ca +// ca : https://en.wikipedia.org/wiki/.ca ca // ca geographical names ab.ca @@ -535,31 +688,31 @@ pe.ca qc.ca sk.ca yk.ca -// gc.ca: http://en.wikipedia.org/wiki/.gc.ca +// gc.ca: https://en.wikipedia.org/wiki/.gc.ca // see also: http://registry.gc.ca/en/SubdomainFAQ gc.ca -// cat : http://en.wikipedia.org/wiki/.cat +// cat : https://en.wikipedia.org/wiki/.cat cat -// cc : http://en.wikipedia.org/wiki/.cc +// cc : https://en.wikipedia.org/wiki/.cc cc -// cd : http://en.wikipedia.org/wiki/.cd +// cd : https://en.wikipedia.org/wiki/.cd // see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 cd gov.cd -// cf : http://en.wikipedia.org/wiki/.cf +// cf : https://en.wikipedia.org/wiki/.cf cf -// cg : http://en.wikipedia.org/wiki/.cg +// cg : https://en.wikipedia.org/wiki/.cg cg -// ch : http://en.wikipedia.org/wiki/.ch +// ch : https://en.wikipedia.org/wiki/.ch ch -// ci : http://en.wikipedia.org/wiki/.ci +// ci : https://en.wikipedia.org/wiki/.ci // http://www.nic.ci/index.php?page=charte ci org.ci @@ -578,25 +731,26 @@ presse.ci md.ci gouv.ci -// ck : http://en.wikipedia.org/wiki/.ck +// ck : https://en.wikipedia.org/wiki/.ck *.ck !www.ck -// cl : http://en.wikipedia.org/wiki/.cl +// cl : https://www.nic.cl +// Confirmed by .CL registry cl -gov.cl -gob.cl co.cl +gob.cl +gov.cl mil.cl -// cm : http://en.wikipedia.org/wiki/.cm plus bug 981927 +// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 cm co.cm com.cm gov.cm net.cm -// cn : http://en.wikipedia.org/wiki/.cn +// cn : https://en.wikipedia.org/wiki/.cn // Submitted by registry cn ac.cn @@ -645,7 +799,7 @@ hk.cn mo.cn tw.cn -// co : http://en.wikipedia.org/wiki/.co +// co : https://en.wikipedia.org/wiki/.co // Submitted by registry co arts.co @@ -662,10 +816,10 @@ org.co rec.co web.co -// com : http://en.wikipedia.org/wiki/.com +// com : https://en.wikipedia.org/wiki/.com com -// coop : http://en.wikipedia.org/wiki/.coop +// coop : https://en.wikipedia.org/wiki/.coop coop // cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do @@ -678,7 +832,7 @@ go.cr or.cr sa.cr -// cu : http://en.wikipedia.org/wiki/.cu +// cu : https://en.wikipedia.org/wiki/.cu cu com.cu edu.cu @@ -687,8 +841,14 @@ net.cu gov.cu inf.cu -// cv : http://en.wikipedia.org/wiki/.cv +// cv : https://en.wikipedia.org/wiki/.cv +// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules cv +com.cv +edu.cv +int.cv +nome.cv +org.cv // cw : http://www.una.cw/cw_registry/ // Confirmed by registry 2013-03-26 @@ -698,42 +858,44 @@ edu.cw net.cw org.cw -// cx : http://en.wikipedia.org/wiki/.cx +// cx : https://en.wikipedia.org/wiki/.cx // list of other 2nd level tlds ? cx gov.cx -// cy : http://en.wikipedia.org/wiki/.cy +// cy : http://www.nic.cy/ +// Submitted by registry Panayiotou Fotia +// namespace policies URL https://www.nic.cy/portal//sites/default/files/symfonia_gia_eggrafi.pdf +cy ac.cy biz.cy com.cy ekloges.cy gov.cy ltd.cy -name.cy +mil.cy net.cy org.cy -parliament.cy press.cy pro.cy tm.cy -// cz : http://en.wikipedia.org/wiki/.cz +// cz : https://en.wikipedia.org/wiki/.cz cz -// de : http://en.wikipedia.org/wiki/.de +// de : https://en.wikipedia.org/wiki/.de // Confirmed by registry (with technical // reservations) 2008-07-01 de -// dj : http://en.wikipedia.org/wiki/.dj +// dj : https://en.wikipedia.org/wiki/.dj dj -// dk : http://en.wikipedia.org/wiki/.dk +// dk : https://en.wikipedia.org/wiki/.dk // Confirmed by registry 2008-06-17 dk -// dm : http://en.wikipedia.org/wiki/.dm +// dm : https://en.wikipedia.org/wiki/.dm dm com.dm net.dm @@ -741,7 +903,7 @@ org.dm edu.dm gov.dm -// do : http://en.wikipedia.org/wiki/.do +// do : https://en.wikipedia.org/wiki/.do do art.do com.do @@ -754,16 +916,18 @@ org.do sld.do web.do -// dz : http://en.wikipedia.org/wiki/.dz +// dz : http://www.nic.dz/images/pdf_nic/charte.pdf dz +art.dz +asso.dz com.dz +edu.dz +gov.dz org.dz net.dz -gov.dz -edu.dz -asso.dz pol.dz -art.dz +soc.dz +tm.dz // ec : http://www.nic.ec/reg/paso1.asp // Submitted by registry @@ -781,7 +945,7 @@ gov.ec gob.ec mil.ec -// edu : http://en.wikipedia.org/wiki/.edu +// edu : https://en.wikipedia.org/wiki/.edu edu // ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B @@ -797,7 +961,7 @@ aip.ee org.ee fie.ee -// eg : http://en.wikipedia.org/wiki/.eg +// eg : https://en.wikipedia.org/wiki/.eg eg com.eg edu.eg @@ -809,7 +973,7 @@ net.eg org.eg sci.eg -// er : http://en.wikipedia.org/wiki/.er +// er : https://en.wikipedia.org/wiki/.er *.er // es : https://www.nic.es/site_ingles/ingles/dominios/index.html @@ -820,7 +984,7 @@ org.es gob.es edu.es -// et : http://en.wikipedia.org/wiki/.et +// et : https://en.wikipedia.org/wiki/.et et com.et gov.et @@ -831,42 +995,56 @@ name.et info.et net.et -// eu : http://en.wikipedia.org/wiki/.eu +// eu : https://en.wikipedia.org/wiki/.eu eu -// fi : http://en.wikipedia.org/wiki/.fi +// fi : https://en.wikipedia.org/wiki/.fi fi -// aland.fi : http://en.wikipedia.org/wiki/.ax +// aland.fi : https://en.wikipedia.org/wiki/.ax // This domain is being phased out in favor of .ax. As there are still many // domains under aland.fi, we still keep it on the list until aland.fi is // completely removed. // TODO: Check for updates (expected to be phased out around Q1/2009) aland.fi -// fj : http://en.wikipedia.org/wiki/.fj -*.fj - -// fk : http://en.wikipedia.org/wiki/.fk +// fj : http://domains.fj/ +// Submitted by registry 2020-02-11 +fj +ac.fj +biz.fj +com.fj +gov.fj +info.fj +mil.fj +name.fj +net.fj +org.fj +pro.fj + +// fk : https://en.wikipedia.org/wiki/.fk *.fk -// fm : http://en.wikipedia.org/wiki/.fm +// fm : https://en.wikipedia.org/wiki/.fm +com.fm +edu.fm +net.fm +org.fm fm -// fo : http://en.wikipedia.org/wiki/.fo +// fo : https://en.wikipedia.org/wiki/.fo fo // fr : http://www.afnic.fr/ -// domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs +// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf fr -com.fr asso.fr +com.fr +gouv.fr nom.fr prd.fr -presse.fr tm.fr -// domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels +// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html aeroport.fr -assedic.fr avocat.fr avoues.fr cci.fr @@ -874,7 +1052,6 @@ chambagri.fr chirurgiens-dentistes.fr experts-comptables.fr geometre-expert.fr -gouv.fr greta.fr huissier-justice.fr medecin.fr @@ -883,14 +1060,16 @@ pharmacien.fr port.fr veterinaire.fr -// ga : http://en.wikipedia.org/wiki/.ga +// ga : https://en.wikipedia.org/wiki/.ga ga // gb : This registry is effectively dormant // Submitted by registry gb -// gd : http://en.wikipedia.org/wiki/.gd +// gd : https://en.wikipedia.org/wiki/.gd +edu.gd +gov.gd gd // ge : http://www.nic.net.ge/policy_en.pdf @@ -903,7 +1082,7 @@ mil.ge net.ge pvt.ge -// gf : http://en.wikipedia.org/wiki/.gf +// gf : https://en.wikipedia.org/wiki/.gf gf // gg : http://www.channelisles.net/register-domains/ @@ -913,7 +1092,7 @@ co.gg net.gg org.gg -// gh : http://en.wikipedia.org/wiki/.gh +// gh : https://en.wikipedia.org/wiki/.gh // see also: http://www.nic.gh/reg_now.php // Although domains directly at second level are not possible at the moment, // they have been possible for some time and may come back. @@ -933,7 +1112,7 @@ mod.gi edu.gi org.gi -// gl : http://en.wikipedia.org/wiki/.gl +// gl : https://en.wikipedia.org/wiki/.gl // http://nic.gl gl co.gl @@ -955,7 +1134,7 @@ gov.gn org.gn net.gn -// gov : http://en.wikipedia.org/wiki/.gov +// gov : https://en.wikipedia.org/wiki/.gov gov // gp : http://www.nic.gp/index.php?lang=en @@ -967,7 +1146,7 @@ edu.gp org.gp asso.gp -// gq : http://en.wikipedia.org/wiki/.gq +// gq : https://en.wikipedia.org/wiki/.gq gq // gr : https://grweb.ics.forth.gr/english/1617-B-2005.html @@ -979,10 +1158,10 @@ net.gr org.gr gov.gr -// gs : http://en.wikipedia.org/wiki/.gs +// gs : https://en.wikipedia.org/wiki/.gs gs -// gt : http://www.gt/politicas_de_registro.html +// gt : https://www.gt/sitio/registration_policy.php?lang=en gt com.gt edu.gt @@ -992,13 +1171,24 @@ mil.gt net.gt org.gt -// gu : http://gadao.gov.gu/registration.txt -*.gu - -// gw : http://en.wikipedia.org/wiki/.gw +// gu : http://gadao.gov.gu/register.html +// University of Guam : https://www.uog.edu +// Submitted by uognoc@triton.uog.edu +gu +com.gu +edu.gu +gov.gu +guam.gu +info.gu +net.gu +org.gu +web.gu + +// gw : https://en.wikipedia.org/wiki/.gw +// gw : https://nic.gw/regras/ gw -// gy : http://en.wikipedia.org/wiki/.gy +// gy : https://en.wikipedia.org/wiki/.gy // http://registry.gy/ gy co.gy @@ -1008,7 +1198,7 @@ gov.gy net.gy org.gy -// hk : https://www.hkdnr.hk +// hk : https://www.hkirc.hk // Submitted by registry hk com.hk @@ -1033,7 +1223,7 @@ org.hk 組織.hk 組织.hk -// hm : http://en.wikipedia.org/wiki/.hm +// hm : https://en.wikipedia.org/wiki/.hm hm // hn : http://www.nic.hn/politicas/ps02,,05.html @@ -1107,7 +1297,7 @@ tozsde.hu utazas.hu video.hu -// id : https://register.pandi.or.id/ +// id : https://pandi.id/en/domain/registration-requirements/ id ac.id biz.id @@ -1118,10 +1308,11 @@ mil.id my.id net.id or.id +ponpes.id sch.id web.id -// ie : http://en.wikipedia.org/wiki/.ie +// ie : https://en.wikipedia.org/wiki/.ie ie gov.ie @@ -1149,7 +1340,7 @@ plc.co.im tt.im tv.im -// in : http://en.wikipedia.org/wiki/.in +// in : https://en.wikipedia.org/wiki/.in // see also: https://registry.in/Policies // Please note, that nic.in is not an official eTLD, but used by most // government institutions. @@ -1167,10 +1358,10 @@ res.in gov.in mil.in -// info : http://en.wikipedia.org/wiki/.info +// info : https://en.wikipedia.org/wiki/.info info -// int : http://en.wikipedia.org/wiki/.int +// int : https://en.wikipedia.org/wiki/.int // Confirmed by registry 2008-06-18 int eu.int @@ -1215,14 +1406,12 @@ gov.is org.is int.is -// it : http://en.wikipedia.org/wiki/.it +// it : https://en.wikipedia.org/wiki/.it it gov.it edu.it -// Reserved geo-names: -// http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf -// There is also a list of reserved geo-names corresponding to Italian municipalities -// http://www.nic.it/documenti/appendice-c.pdf, but it is not included here. +// Reserved geo-names (regions and provinces): +// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf // Regions abr.it abruzzo.it @@ -1276,6 +1465,12 @@ sicily.it taa.it tos.it toscana.it +trentin-sud-tirol.it +trentin-süd-tirol.it +trentin-sudtirol.it +trentin-südtirol.it +trentin-sued-tirol.it +trentin-suedtirol.it trentino-a-adige.it trentino-aadige.it trentino-alto-adige.it @@ -1283,9 +1478,12 @@ trentino-altoadige.it trentino-s-tirol.it trentino-stirol.it trentino-sud-tirol.it +trentino-süd-tirol.it trentino-sudtirol.it +trentino-südtirol.it trentino-sued-tirol.it trentino-suedtirol.it +trentino.it trentinoa-adige.it trentinoaadige.it trentinoalto-adige.it @@ -1293,9 +1491,17 @@ trentinoaltoadige.it trentinos-tirol.it trentinostirol.it trentinosud-tirol.it +trentinosüd-tirol.it trentinosudtirol.it +trentinosüdtirol.it trentinosued-tirol.it trentinosuedtirol.it +trentinsud-tirol.it +trentinsüd-tirol.it +trentinsudtirol.it +trentinsüdtirol.it +trentinsued-tirol.it +trentinsuedtirol.it tuscany.it umb.it umbria.it @@ -1310,7 +1516,13 @@ valleaosta.it valled-aosta.it valledaosta.it vallee-aoste.it +vallée-aoste.it +vallee-d-aoste.it +vallée-d-aoste.it valleeaoste.it +valléeaoste.it +valleedaoste.it +valléedaoste.it vao.it vda.it ven.it @@ -1343,6 +1555,9 @@ at.it av.it avellino.it ba.it +balsan-sudtirol.it +balsan-südtirol.it +balsan-suedtirol.it balsan.it bari.it barletta-trani-andria.it @@ -1357,13 +1572,21 @@ bl.it bn.it bo.it bologna.it +bolzano-altoadige.it bolzano.it +bozen-sudtirol.it +bozen-südtirol.it +bozen-suedtirol.it bozen.it br.it brescia.it brindisi.it bs.it bt.it +bulsan-sudtirol.it +bulsan-südtirol.it +bulsan-suedtirol.it +bulsan.it bz.it ca.it cagliari.it @@ -1381,7 +1604,9 @@ catanzaro.it cb.it ce.it cesena-forli.it +cesena-forlì.it cesenaforli.it +cesenaforlì.it ch.it chieti.it ci.it @@ -1412,7 +1637,9 @@ florence.it fm.it foggia.it forli-cesena.it +forlì-cesena.it forlicesena.it +forlìcesena.it fr.it frosinone.it ge.it @@ -1543,6 +1770,7 @@ sp.it sr.it ss.it suedtirol.it +südtirol.it sv.it ta.it taranto.it @@ -1561,7 +1789,6 @@ trani-barletta-andria.it traniandriabarletta.it tranibarlettaandria.it trapani.it -trentino.it trento.it treviso.it trieste.it @@ -1613,10 +1840,10 @@ gov.jo mil.jo name.jo -// jobs : http://en.wikipedia.org/wiki/.jobs +// jobs : https://en.wikipedia.org/wiki/.jobs jobs -// jp : http://en.wikipedia.org/wiki/.jp +// jp : https://en.wikipedia.org/wiki/.jp // http://jprs.co.jp/en/jpdomain.html // Submitted by registry jp @@ -2545,11 +2772,8 @@ arao.kumamoto.jp aso.kumamoto.jp choyo.kumamoto.jp gyokuto.kumamoto.jp -hitoyoshi.kumamoto.jp kamiamakusa.kumamoto.jp -kashima.kumamoto.jp kikuchi.kumamoto.jp -kosa.kumamoto.jp kumamoto.kumamoto.jp mashiki.kumamoto.jp mifune.kumamoto.jp @@ -2634,7 +2858,6 @@ iwanuma.miyagi.jp kakuda.miyagi.jp kami.miyagi.jp kawasaki.miyagi.jp -kesennuma.miyagi.jp marumori.miyagi.jp matsushima.miyagi.jp minamisanriku.miyagi.jp @@ -3420,8 +3643,17 @@ uenohara.yamanashi.jp yamanakako.yamanashi.jp yamanashi.yamanashi.jp -// ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145 -*.ke +// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains +ke +ac.ke +co.ke +go.ke +info.ke +me.ke +mobi.ke +ne.ke +or.ke +sc.ke // kg : http://www.domain.kg/dmn_n.html kg @@ -3445,7 +3677,7 @@ gov.ki info.ki com.ki -// km : http://en.wikipedia.org/wiki/.km +// km : https://en.wikipedia.org/wiki/.km // http://www.domaine.km/documents/charte.doc km org.km @@ -3458,7 +3690,7 @@ mil.km ass.km com.km // These are only mentioned as proposed suggestions at domaine.km, but -// http://en.wikipedia.org/wiki/.km says they're available for registration: +// https://en.wikipedia.org/wiki/.km says they're available for registration: coop.km asso.km presse.km @@ -3468,7 +3700,7 @@ pharmaciens.km veterinaire.km gouv.km -// kn : http://en.wikipedia.org/wiki/.kn +// kn : https://en.wikipedia.org/wiki/.kn // http://www.dot.kn/domainRules.html kn net.kn @@ -3485,7 +3717,7 @@ org.kp rep.kp tra.kp -// kr : http://en.wikipedia.org/wiki/.kr +// kr : https://en.wikipedia.org/wiki/.kr // see also: http://domain.nida.or.kr/eng/registration.jsp kr ac.kr @@ -3519,19 +3751,26 @@ jeonnam.kr seoul.kr ulsan.kr -// kw : http://en.wikipedia.org/wiki/.kw -*.kw +// kw : https://www.nic.kw/policies/ +// Confirmed by registry +kw +com.kw +edu.kw +emb.kw +gov.kw +ind.kw +net.kw +org.kw // ky : http://www.icta.ky/da_ky_reg_dom.php // Confirmed by registry 2008-06-17 ky -edu.ky -gov.ky com.ky -org.ky +edu.ky net.ky +org.ky -// kz : http://en.wikipedia.org/wiki/.kz +// kz : https://en.wikipedia.org/wiki/.kz // see also: http://www.nic.kz/rules/index.jsp kz org.kz @@ -3541,7 +3780,7 @@ gov.kz mil.kz com.kz -// la : http://en.wikipedia.org/wiki/.la +// la : https://en.wikipedia.org/wiki/.la // Submitted by registry la int.la @@ -3553,7 +3792,7 @@ per.la com.la org.la -// lb : http://en.wikipedia.org/wiki/.lb +// lb : https://en.wikipedia.org/wiki/.lb // Submitted by registry lb com.lb @@ -3562,7 +3801,7 @@ gov.lb net.lb org.lb -// lc : http://en.wikipedia.org/wiki/.lc +// lc : https://en.wikipedia.org/wiki/.lc // see also: http://www.nic.lc/rules.htm lc com.lc @@ -3572,10 +3811,10 @@ org.lc edu.lc gov.lc -// li : http://en.wikipedia.org/wiki/.li +// li : https://en.wikipedia.org/wiki/.li li -// lk : http://www.nic.lk/seclevpr.html +// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure lk gov.lk sch.lk @@ -3602,12 +3841,20 @@ gov.lr org.lr net.lr -// ls : http://en.wikipedia.org/wiki/.ls +// ls : http://www.nic.ls/ +// Confirmed by registry ls +ac.ls +biz.ls co.ls +edu.ls +gov.ls +info.ls +net.ls org.ls +sc.ls -// lt : http://en.wikipedia.org/wiki/.lt +// lt : https://en.wikipedia.org/wiki/.lt lt // gov.lt : http://www.gov.lt/index_en.php gov.lt @@ -3639,7 +3886,7 @@ med.ly org.ly id.ly -// ma : http://en.wikipedia.org/wiki/.ma +// ma : https://en.wikipedia.org/wiki/.ma // http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf ma co.ma @@ -3654,10 +3901,10 @@ mc tm.mc asso.mc -// md : http://en.wikipedia.org/wiki/.md +// md : https://en.wikipedia.org/wiki/.md md -// me : http://en.wikipedia.org/wiki/.me +// me : https://en.wikipedia.org/wiki/.me me co.me net.me @@ -3680,13 +3927,13 @@ mil.mg com.mg co.mg -// mh : http://en.wikipedia.org/wiki/.mh +// mh : https://en.wikipedia.org/wiki/.mh mh -// mil : http://en.wikipedia.org/wiki/.mil +// mil : https://en.wikipedia.org/wiki/.mil mil -// mk : http://en.wikipedia.org/wiki/.mk +// mk : https://en.wikipedia.org/wiki/.mk // see also: http://dns.marnet.net.mk/postapka.php mk com.mk @@ -3698,7 +3945,7 @@ inf.mk name.mk // ml : http://www.gobin.info/domainname/ml-template.doc -// see also: http://en.wikipedia.org/wiki/.ml +// see also: https://en.wikipedia.org/wiki/.ml ml com.ml edu.ml @@ -3708,10 +3955,10 @@ net.ml org.ml presse.ml -// mm : http://en.wikipedia.org/wiki/.mm +// mm : https://en.wikipedia.org/wiki/.mm *.mm -// mn : http://en.wikipedia.org/wiki/.mn +// mn : https://en.wikipedia.org/wiki/.mn mn gov.mn edu.mn @@ -3725,17 +3972,17 @@ org.mo edu.mo gov.mo -// mobi : http://en.wikipedia.org/wiki/.mobi +// mobi : https://en.wikipedia.org/wiki/.mobi mobi // mp : http://www.dot.mp/ // Confirmed by registry 2008-06-17 mp -// mq : http://en.wikipedia.org/wiki/.mq +// mq : https://en.wikipedia.org/wiki/.mq mq -// mr : http://en.wikipedia.org/wiki/.mr +// mr : https://en.wikipedia.org/wiki/.mr mr gov.mr @@ -3755,7 +4002,7 @@ edu.mt net.mt org.mt -// mu : http://en.wikipedia.org/wiki/.mu +// mu : https://en.wikipedia.org/wiki/.mu mu com.mu net.mu @@ -4134,8 +4381,6 @@ niepce.museum norfolk.museum north.museum nrw.museum -nuernberg.museum -nuremberg.museum nyc.museum nyny.museum oceanographic.museum @@ -4317,7 +4562,7 @@ zoology.museum ירושלים.museum иком.museum -// mv : http://en.wikipedia.org/wiki/.mv +// mv : https://en.wikipedia.org/wiki/.mv // "mv" included because, contra Wikipedia, google.mv exists. mv aero.mv @@ -4358,19 +4603,29 @@ gob.mx edu.mx net.mx -// my : http://www.mynic.net.my/ +// my : http://www.mynic.my/ +// Available strings: https://mynic.my/resources/domains/buying-a-domain/ my +biz.my com.my -net.my -org.my -gov.my edu.my +gov.my mil.my name.my +net.my +org.my -// mz : http://www.gobin.info/domainname/mz-template.doc -*.mz -!teledata.mz +// mz : http://www.uem.mz/ +// Submitted by registry +mz +ac.mz +adv.mz +co.mz +edu.mz +gov.mz +mil.mz +net.mz +org.mz // na : http://www.na-nic.com.na/ // http://www.info.na/domain/ @@ -4399,14 +4654,15 @@ name // nc : http://www.cctld.nc/ nc asso.nc +nom.nc -// ne : http://en.wikipedia.org/wiki/.ne +// ne : https://en.wikipedia.org/wiki/.ne ne -// net : http://en.wikipedia.org/wiki/.net +// net : https://en.wikipedia.org/wiki/.net net -// nf : http://en.wikipedia.org/wiki/.nf +// nf : https://en.wikipedia.org/wiki/.nf nf com.nf net.nf @@ -4433,36 +4689,34 @@ org.ng sch.ng // ni : http://www.nic.ni/ +ni +ac.ni +biz.ni +co.ni com.ni -gob.ni edu.ni -org.ni -nom.ni -net.ni -mil.ni -co.ni -biz.ni -web.ni -int.ni -ac.ni +gob.ni in.ni info.ni +int.ni +mil.ni +net.ni +nom.ni +org.ni +web.ni -// nl : http://en.wikipedia.org/wiki/.nl +// nl : https://en.wikipedia.org/wiki/.nl // https://www.sidn.nl/ // ccTLD for the Netherlands nl -// BV.nl will be a registry for dutch BV's (besloten vennootschap) -bv.nl - -// no : http://www.norid.no/regelverk/index.en.html -// The Norwegian registry has declined to notify us of updates. The web pages -// referenced below are the official source of the data. There is also an -// announce mailing list: -// https://postlister.uninett.no/sympa/info/norid-diskusjon +// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/ +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ +// RSS feed: https://teknisk.norid.no/en/feed/ no -// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ fhs.no vgs.no fylkesbibl.no @@ -4470,13 +4724,13 @@ folkebibl.no museum.no idrett.no priv.no -// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ mil.no stat.no dep.no kommune.no herad.no -// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ // counties aa.no ah.no @@ -5237,10 +5491,10 @@ org.nr net.nr com.nr -// nu : http://en.wikipedia.org/wiki/.nu +// nu : https://en.wikipedia.org/wiki/.nu nu -// nz : http://en.wikipedia.org/wiki/.nz +// nz : https://en.wikipedia.org/wiki/.nz // Submitted by registry nz ac.nz @@ -5260,7 +5514,7 @@ org.nz parliament.nz school.nz -// om : http://en.wikipedia.org/wiki/.om +// om : https://en.wikipedia.org/wiki/.om om co.om com.om @@ -5272,7 +5526,10 @@ net.om org.om pro.om -// org : http://en.wikipedia.org/wiki/.org +// onion : https://tools.ietf.org/html/rfc7686 +onion + +// org : https://en.wikipedia.org/wiki/.org org // pa : http://www.nic.pa/ @@ -5307,7 +5564,7 @@ com.pf org.pf edu.pf -// pg : http://en.wikipedia.org/wiki/.pg +// pg : https://en.wikipedia.org/wiki/.pg *.pg // ph : http://www.domains.ph/FAQ2.asp @@ -5557,7 +5814,7 @@ org.pn edu.pn net.pn -// post : http://en.wikipedia.org/wiki/.post +// post : https://en.wikipedia.org/wiki/.post post // pr : http://www.nic.pr/index.asp?f=1 @@ -5572,22 +5829,26 @@ pro.pr biz.pr info.pr name.pr -// these aren't mentioned on nic.pr, but on http://en.wikipedia.org/wiki/.pr +// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr est.pr prof.pr ac.pr -// pro : http://www.nic.pro/support_faq.htm +// pro : http://registry.pro/get-pro pro +aaa.pro aca.pro +acct.pro +avocat.pro bar.pro cpa.pro +eng.pro jur.pro law.pro med.pro -eng.pro +recht.pro -// ps : http://en.wikipedia.org/wiki/.ps +// ps : https://en.wikipedia.org/wiki/.ps // http://www.nic.ps/registration/policy.html#reg ps edu.ps @@ -5598,7 +5859,7 @@ com.ps org.ps net.ps -// pt : http://online.dns.pt/dns/start_dns +// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/ pt net.pt gov.pt @@ -5609,7 +5870,7 @@ publ.pt com.pt nome.pt -// pw : http://en.wikipedia.org/wiki/.pw +// pw : https://en.wikipedia.org/wiki/.pw pw co.pw ne.pw @@ -5669,156 +5930,19 @@ gov.rs in.rs org.rs -// ru : http://www.cctld.ru/ru/docs/aktiv_8.php -// Industry domains +// ru : https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf +// Submitted by George Georgievsky ru -ac.ru -com.ru -edu.ru -int.ru -net.ru -org.ru -pp.ru -// Geographical domains -adygeya.ru -altai.ru -amur.ru -arkhangelsk.ru -astrakhan.ru -bashkiria.ru -belgorod.ru -bir.ru -bryansk.ru -buryatia.ru -cbg.ru -chel.ru -chelyabinsk.ru -chita.ru -chukotka.ru -chuvashia.ru -dagestan.ru -dudinka.ru -e-burg.ru -grozny.ru -irkutsk.ru -ivanovo.ru -izhevsk.ru -jar.ru -joshkar-ola.ru -kalmykia.ru -kaluga.ru -kamchatka.ru -karelia.ru -kazan.ru -kchr.ru -kemerovo.ru -khabarovsk.ru -khakassia.ru -khv.ru -kirov.ru -koenig.ru -komi.ru -kostroma.ru -krasnoyarsk.ru -kuban.ru -kurgan.ru -kursk.ru -lipetsk.ru -magadan.ru -mari.ru -mari-el.ru -marine.ru -mordovia.ru -// mosreg.ru Bug 1090800 - removed at request of Aleksey Konstantinov -msk.ru -murmansk.ru -nalchik.ru -nnov.ru -nov.ru -novosibirsk.ru -nsk.ru -omsk.ru -orenburg.ru -oryol.ru -palana.ru -penza.ru -perm.ru -ptz.ru -rnd.ru -ryazan.ru -sakhalin.ru -samara.ru -saratov.ru -simbirsk.ru -smolensk.ru -spb.ru -stavropol.ru -stv.ru -surgut.ru -tambov.ru -tatarstan.ru -tom.ru -tomsk.ru -tsaritsyn.ru -tsk.ru -tula.ru -tuva.ru -tver.ru -tyumen.ru -udm.ru -udmurtia.ru -ulan-ude.ru -vladikavkaz.ru -vladimir.ru -vladivostok.ru -volgograd.ru -vologda.ru -voronezh.ru -vrn.ru -vyatka.ru -yakutia.ru -yamal.ru -yaroslavl.ru -yekaterinburg.ru -yuzhno-sakhalinsk.ru -// More geographical domains -amursk.ru -baikal.ru -cmw.ru -fareast.ru -jamal.ru -kms.ru -k-uralsk.ru -kustanai.ru -kuzbass.ru -mytis.ru -nakhodka.ru -nkz.ru -norilsk.ru -oskol.ru -pyatigorsk.ru -rubtsovsk.ru -snz.ru -syzran.ru -vdonsk.ru -zgrad.ru -// State domains -gov.ru -mil.ru -// Technical domains -test.ru -// rw : http://www.nic.rw/cgi-bin/policy.pl +// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf rw -gov.rw -net.rw -edu.rw ac.rw -com.rw co.rw -int.rw +coop.rw +gov.rw mil.rw -gouv.rw +net.rw +org.rw // sa : http://www.nic.net.sa/ sa @@ -5860,7 +5984,7 @@ tv.sd gov.sd info.sd -// se : http://en.wikipedia.org/wiki/.se +// se : https://en.wikipedia.org/wiki/.se // Submitted by registry se a.se @@ -5920,14 +6044,14 @@ gov.sh org.sh mil.sh -// si : http://en.wikipedia.org/wiki/.si +// si : https://en.wikipedia.org/wiki/.si si // sj : No registrations at this time. // Submitted by registry sj -// sk : http://en.wikipedia.org/wiki/.sk +// sk : https://en.wikipedia.org/wiki/.sk // list of 2nd level domains ? sk @@ -5940,10 +6064,10 @@ edu.sl gov.sl org.sl -// sm : http://en.wikipedia.org/wiki/.sm +// sm : https://en.wikipedia.org/wiki/.sm sm -// sn : http://en.wikipedia.org/wiki/.sn +// sn : https://en.wikipedia.org/wiki/.sn sn art.sn com.sn @@ -5953,15 +6077,30 @@ org.sn perso.sn univ.sn -// so : http://www.soregistry.com/ +// so : http://sonic.so/policies/ so com.so +edu.so +gov.so +me.so net.so org.so -// sr : http://en.wikipedia.org/wiki/.sr +// sr : https://en.wikipedia.org/wiki/.sr sr +// ss : https://registry.nic.ss/ +// Submitted by registry +ss +biz.ss +com.ss +edu.ss +gov.ss +me.ss +net.ss +org.ss +sch.ss + // st : http://www.nic.st/html/policyrules/ st co.st @@ -5969,7 +6108,6 @@ com.st consulado.st edu.st embaixada.st -gov.st mil.st net.st org.st @@ -5977,40 +6115,8 @@ principe.st saotome.st store.st -// su : http://en.wikipedia.org/wiki/.su +// su : https://en.wikipedia.org/wiki/.su su -adygeya.su -arkhangelsk.su -balashov.su -bashkiria.su -bryansk.su -dagestan.su -grozny.su -ivanovo.su -kalmykia.su -kaluga.su -karelia.su -khakassia.su -krasnodar.su -kurgan.su -lenug.su -mordovia.su -msk.su -murmansk.su -nalchik.su -nov.su -obninsk.su -penza.su -pokrovsk.su -sochi.su -spb.su -togliatti.su -troitsk.su -tula.su -tuva.su -vladikavkaz.su -vladimir.su -vologda.su // sv : http://www.svnet.org.sv/niveldos.pdf sv @@ -6020,12 +6126,12 @@ gob.sv org.sv red.sv -// sx : http://en.wikipedia.org/wiki/.sx +// sx : https://en.wikipedia.org/wiki/.sx // Submitted by registry sx gov.sx -// sy : http://en.wikipedia.org/wiki/.sy +// sy : https://en.wikipedia.org/wiki/.sy // see also: http://www.gobin.info/domainname/sy.doc sy edu.sy @@ -6035,31 +6141,31 @@ mil.sy com.sy org.sy -// sz : http://en.wikipedia.org/wiki/.sz +// sz : https://en.wikipedia.org/wiki/.sz // http://www.sispa.org.sz/ sz co.sz ac.sz org.sz -// tc : http://en.wikipedia.org/wiki/.tc +// tc : https://en.wikipedia.org/wiki/.tc tc -// td : http://en.wikipedia.org/wiki/.td +// td : https://en.wikipedia.org/wiki/.td td -// tel: http://en.wikipedia.org/wiki/.tel +// tel: https://en.wikipedia.org/wiki/.tel // http://www.telnic.org/ tel -// tf : http://en.wikipedia.org/wiki/.tf +// tf : https://en.wikipedia.org/wiki/.tf tf -// tg : http://en.wikipedia.org/wiki/.tg +// tg : https://en.wikipedia.org/wiki/.tg // http://www.nic.tg/ tg -// th : http://en.wikipedia.org/wiki/.th +// th : https://en.wikipedia.org/wiki/.th // Submitted by registry th ac.th @@ -6088,10 +6194,10 @@ org.tj test.tj web.tj -// tk : http://en.wikipedia.org/wiki/.tk +// tk : https://en.wikipedia.org/wiki/.tk tk -// tl : http://en.wikipedia.org/wiki/.tl +// tl : https://en.wikipedia.org/wiki/.tl tl gov.tl @@ -6106,31 +6212,24 @@ gov.tm mil.tm edu.tm -// tn : http://en.wikipedia.org/wiki/.tn -// http://whois.ati.tn/ +// tn : http://www.registre.tn/fr/ +// https://whois.ati.tn/ tn com.tn ens.tn fin.tn gov.tn ind.tn +info.tn intl.tn +mincom.tn nat.tn net.tn org.tn -info.tn perso.tn tourism.tn -edunet.tn -rnrt.tn -rns.tn -rnu.tn -mincom.tn -agrinet.tn -defense.tn -turen.tn -// to : http://en.wikipedia.org/wiki/.to +// to : https://en.wikipedia.org/wiki/.to // Submitted by registry to com.to @@ -6140,40 +6239,36 @@ org.to edu.to mil.to -// subTLDs: https://www.nic.tr/forms/eng/policies.pdf -// and: https://www.nic.tr/forms/politikalar.pdf -// Submitted by +// tr : https://nic.tr/ +// https://nic.tr/forms/eng/policies.pdf +// https://nic.tr/index.php?USRACTN=PRICELST tr -com.tr -info.tr -biz.tr -net.tr -org.tr -web.tr -gen.tr -tv.tr av.tr -dr.tr bbs.tr -name.tr -tel.tr -gov.tr bel.tr -pol.tr +biz.tr +com.tr +dr.tr +edu.tr +gen.tr +gov.tr +info.tr mil.tr k12.tr -edu.tr kep.tr - +name.tr +net.tr +org.tr +pol.tr +tel.tr +tsk.tr +tv.tr +web.tr // Used by Northern Cyprus nc.tr - // Used by government agencies of Northern Cyprus gov.nc.tr -// travel : http://en.wikipedia.org/wiki/.travel -travel - // tt : http://www.nic.tt/ tt co.tt @@ -6194,12 +6289,12 @@ name.tt gov.tt edu.tt -// tv : http://en.wikipedia.org/wiki/.tv +// tv : https://en.wikipedia.org/wiki/.tv // Not listing any 2LDs as reserved since none seem to exist in practice, // Wikipedia notwithstanding. tv -// tw : http://en.wikipedia.org/wiki/.tw +// tw : https://en.wikipedia.org/wiki/.tw tw edu.tw gov.tw @@ -6257,7 +6352,6 @@ cv.ua dn.ua dnepropetrovsk.ua dnipropetrovsk.ua -dominic.ua donetsk.ua dp.ua if.ua @@ -6325,7 +6419,7 @@ ne.ug com.ug org.ug -// uk : http://en.wikipedia.org/wiki/.uk +// uk : https://en.wikipedia.org/wiki/.uk // Submitted by registry uk ac.uk @@ -6340,7 +6434,7 @@ plc.uk police.uk *.sch.uk -// us : http://en.wikipedia.org/wiki/.us +// us : https://en.wikipedia.org/wiki/.us us dni.us fed.us @@ -6451,7 +6545,7 @@ k12.ok.us k12.or.us k12.pa.us k12.pr.us -k12.ri.us +// k12.ri.us Removed at request of Kim Cournoyer k12.sc.us // k12.sd.us Bug 934131 - Removed at request of James Booze k12.tn.us @@ -6528,7 +6622,7 @@ lib.ca.us lib.co.us lib.ct.us lib.dc.us -lib.de.us +// lib.de.us Issue #243 - Moved to Private section at request of Ed Moore lib.fl.us lib.ga.us lib.gu.us @@ -6581,6 +6675,17 @@ lib.wy.us pvt.k12.ma.us chtr.k12.ma.us paroch.k12.ma.us +// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following +// see also: http://domreg.merit.edu +// see also: whois -h whois.domreg.merit.edu help +ann-arbor.mi.us +cog.mi.us +dst.mi.us +eaton.mi.us +gen.mi.us +mus.mi.us +tec.mi.us +washtenaw.mi.us // uy : http://www.nic.org.uy/ uy @@ -6598,10 +6703,10 @@ com.uz net.uz org.uz -// va : http://en.wikipedia.org/wiki/.va +// va : https://en.wikipedia.org/wiki/.va va -// vc : http://en.wikipedia.org/wiki/.vc +// vc : https://en.wikipedia.org/wiki/.vc // Submitted by registry vc com.vc @@ -6612,9 +6717,10 @@ mil.vc edu.vc // ve : https://registro.nic.ve/ -// Submitted by registry +// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve ve arts.ve +bib.ve co.ve com.ve e12.ve @@ -6626,13 +6732,15 @@ info.ve int.ve mil.ve net.ve +nom.ve org.ve +rar.ve rec.ve store.ve tec.ve web.ve -// vg : http://en.wikipedia.org/wiki/.vg +// vg : https://en.wikipedia.org/wiki/.vg vg // vi : http://www.nic.vi/newdomainform.htm @@ -6661,7 +6769,7 @@ name.vn pro.vn health.vn -// vu : http://en.wikipedia.org/wiki/.vu +// vu : https://en.wikipedia.org/wiki/.vu // http://www.vunic.vu/ vu com.vu @@ -6672,7 +6780,7 @@ org.vu // wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf wf -// ws : http://en.wikipedia.org/wiki/.ws +// ws : https://en.wikipedia.org/wiki/.ws // http://samoanic.ws/index.dhtml ws com.ws @@ -6702,6 +6810,12 @@ yt // xn--54b7fta0cc ("Bangla", Bangla) : BD বাংলা +// xn--90ae ("bg", Bulgarian) : BG +бг + +// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH +البحرين + // xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY // Operated by .by registry бел @@ -6723,6 +6837,17 @@ yt // http://www.dotmasr.eg/ مصر +// xn--e1a4c ("eu", Cyrillic) : EU +// https://eurid.eu +ею + +// xn--qxa6a ("eu", Greek) : EU +// https://eurid.eu +ευ + +// xn--mgbah1a3hjkrd ("Mauritania", Arabic) : MR +موريتانيا + // xn--node ("ge", Georgian Mkhedruli) : GE გე @@ -6731,13 +6856,53 @@ yt ελ // xn--j6w193g ("Hong Kong", Chinese) : HK -// https://www2.hkirc.hk/register/rules.jsp +// https://www.hkirc.hk +// Submitted by registry +// https://www.hkirc.hk/content.jsp?id=30#!/34 香港 +公司.香港 +教育.香港 +政府.香港 +個人.香港 +網絡.香港 +組織.香港 + +// xn--2scrj9c ("Bharat", Kannada) : IN +// India +ಭಾರತ + +// xn--3hcrj9c ("Bharat", Oriya) : IN +// India +ଭାରତ + +// xn--45br5cyl ("Bharatam", Assamese) : IN +// India +ভাৰত + +// xn--h2breg3eve ("Bharatam", Sanskrit) : IN +// India +भारतम् + +// xn--h2brj9c8c ("Bharot", Santali) : IN +// India +भारोत + +// xn--mgbgu82a ("Bharat", Sindhi) : IN +// India +ڀارت + +// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN +// India +ഭാരതം // xn--h2brj9c ("Bharat", Devanagari) : IN // India भारत +// xn--mgbbh1a ("Bharat", Kashmiri) : IN +// India +بارت + // xn--mgbbh1a71e ("Bharat", Arabic) : IN // India بھارت @@ -6783,12 +6948,15 @@ yt // xn--80ao21a ("Kaz", Kazakh) : KZ қаз +// xn--q7ce6a ("Lao", Lao) : LA +ລາວ + // xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK -// http://nic.lk +// https://nic.lk ලංකා // xn--xkc2al3hye2a ("Ilangai", Tamil) : LK -// http://nic.lk +// https://nic.lk இலங்கை // xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA @@ -6836,7 +7004,8 @@ yt ак.срб // xn--p1ai ("rf", Russian-Cyrillic) : RU -// http://www.cctld.ru/en/docs/rulesrf.php +// https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf +// Submitted by George Georgievsky рф // xn--wgbl6a ("Qatar", Arabic) : QA @@ -6875,6 +7044,12 @@ yt // xn--o3cw4h ("Thai", Thai) : TH // http://www.thnic.co.th ไทย +ศึกษา.ไทย +ธุรกิจ.ไทย +รัฐบาล.ไทย +ทหาร.ไทย +เน็ต.ไทย +องค์กร.ไทย // xn--pgbs0dh ("Tunisia", Arabic) : TN // http://nic.tn @@ -6901,9 +7076,15 @@ yt xxx // ye : http://www.y.net.ye/services/domain_name.htm -*.ye - -// za : http://www.zadna.org.za/content/page/domain-information +ye +com.ye +edu.ye +gov.ye +net.ye +mil.ye +org.ye + +// za : https://www.zadna.org.za/content/page/domain-information/ ac.za agric.za alt.za @@ -6915,6 +7096,7 @@ law.za mil.za net.za ngo.za +nic.za nis.za nom.za org.za @@ -6922,15 +7104,35 @@ school.za tm.za web.za -// zm : http://en.wikipedia.org/wiki/.zm -*.zm - -// zw : http://en.wikipedia.org/wiki/.zw -*.zw - - -// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2016-01-04T22:39:54Z - +// zm : https://zicta.zm/ +// Submitted by registry +zm +ac.zm +biz.zm +co.zm +com.zm +edu.zm +gov.zm +info.zm +mil.zm +net.zm +org.zm +sch.zm + +// zw : https://www.potraz.gov.zw/ +// Confirmed by registry 2017-01-25 +zw +ac.zw +co.zw +gov.zw +mil.zw +org.zw + + +// newGTLDs + +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-02-02T15:12:37Z +// This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -6955,13 +7157,13 @@ abc // able : 2015-06-25 Able Inc. able -// abogado : 2014-04-24 Top Level Domain Holdings Limited +// abogado : 2014-04-24 Registry Services, LLC abogado // abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre abudhabi -// academy : 2013-11-07 Half Oaks, LLC +// academy : 2013-11-07 Binky Moon, LLC academy // accenture : 2014-08-15 Accenture plc @@ -6970,16 +7172,13 @@ accenture // accountant : 2014-11-20 dot Accountant Limited accountant -// accountants : 2014-03-20 Knob Town, LLC +// accountants : 2014-03-20 Binky Moon, LLC accountants // aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG aco -// active : 2014-05-01 The Active Network, Inc -active - -// actor : 2013-12-12 United TLD Holdco Ltd. +// actor : 2013-12-12 Dog Beach, LLC actor // adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) @@ -6997,34 +7196,25 @@ aeg // aetna : 2015-05-21 Aetna Life Insurance Company aetna -// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. -afamilycompany - // afl : 2014-10-02 Australian Football League afl // africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa africa -// africamagic : 2015-03-05 Electronic Media Network (Pty) Ltd -africamagic - // agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) agakhan -// agency : 2013-11-14 Steel Falls, LLC +// agency : 2013-11-14 Binky Moon, LLC agency // aig : 2014-12-18 American International Group, Inc. aig -// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. -aigo - // airbus : 2015-07-30 Airbus S.A.S. airbus -// airforce : 2014-03-06 United TLD Holdco Ltd. +// airforce : 2014-03-06 Dog Beach, LLC airforce // airtel : 2014-10-24 Bharti Airtel Limited @@ -7051,12 +7241,15 @@ allstate // ally : 2015-06-18 Ally Financial Inc. ally -// alsace : 2014-07-02 REGION D ALSACE +// alsace : 2014-07-02 Region Grand Est alsace // alstom : 2015-07-30 ALSTOM alstom +// amazon : 2019-12-19 Amazon Registry Services, Inc. +amazon + // americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc. americanexpress @@ -7081,16 +7274,16 @@ analytics // android : 2014-08-07 Charleston Road Registry Inc. android -// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd. anquan // anz : 2015-07-31 Australia and New Zealand Banking Group Limited anz -// aol : 2015-09-17 AOL Inc. +// aol : 2015-09-17 Oath Inc. aol -// apartments : 2014-12-11 June Maple, LLC +// apartments : 2014-12-11 Binky Moon, LLC apartments // app : 2015-05-14 Charleston Road Registry Inc. @@ -7108,64 +7301,67 @@ arab // aramco : 2014-11-20 Aramco Services Company aramco -// archi : 2014-02-06 STARTING DOT LIMITED +// archi : 2014-02-06 Afilias Limited archi -// army : 2014-03-06 United TLD Holdco Ltd. +// army : 2014-03-06 Dog Beach, LLC army +// art : 2016-03-24 UK Creative Ideas Limited +art + // arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E. arte // asda : 2015-07-31 Wal-Mart Stores, Inc. asda -// associates : 2014-03-06 Baxter Hill, LLC +// associates : 2014-03-06 Binky Moon, LLC associates // athleta : 2015-07-30 The Gap, Inc. athleta -// attorney : 2014-03-20 +// attorney : 2014-03-20 Dog Beach, LLC attorney -// auction : 2014-03-20 +// auction : 2014-03-20 Dog Beach, LLC auction // audi : 2015-05-21 AUDI Aktiengesellschaft audi -// audible : 2015-06-25 Amazon EU S.à r.l. +// audible : 2015-06-25 Amazon Registry Services, Inc. audible -// audio : 2014-03-20 Uniregistry, Corp. +// audio : 2014-03-20 UNR Corp. audio // auspost : 2015-08-13 Australian Postal Corporation auspost -// author : 2014-12-18 Amazon EU S.à r.l. +// author : 2014-12-18 Amazon Registry Services, Inc. author -// auto : 2014-11-13 +// auto : 2014-11-13 XYZ.COM LLC auto -// autos : 2014-01-09 DERAutos, LLC +// autos : 2014-01-09 XYZ.COM LLC autos -// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca +// avianca : 2015-01-08 Avianca Holdings S.A. avianca -// aws : 2015-06-25 Amazon EU S.à r.l. +// aws : 2015-06-25 AWS Registry LLC aws -// axa : 2013-12-19 AXA SA +// axa : 2013-12-19 AXA Group Operations SAS axa // azure : 2014-12-18 Microsoft Corporation azure -// baby : 2015-04-09 Johnson & Johnson Services, Inc. +// baby : 2015-04-09 XYZ.COM LLC baby // baidu : 2015-01-08 Baidu, Inc. @@ -7177,7 +7373,7 @@ banamex // bananarepublic : 2015-07-31 The Gap, Inc. bananarepublic -// band : 2014-06-12 +// band : 2014-06-12 Dog Beach, LLC band // bank : 2014-09-25 fTLD Registry Services LLC @@ -7198,7 +7394,7 @@ barclays // barefoot : 2015-06-11 Gallo Vineyards, Inc. barefoot -// bargains : 2013-11-14 Half Hallow, LLC +// bargains : 2013-11-14 Binky Moon, LLC bargains // baseball : 2015-10-29 MLB Advanced Media DH, LLC @@ -7231,10 +7427,10 @@ bcn // beats : 2015-05-14 Beats Electronics, LLC beats -// beauty : 2015-12-03 L'Oréal +// beauty : 2015-12-03 XYZ.COM LLC beauty -// beer : 2014-01-09 Top Level Domain Holdings Limited +// beer : 2014-01-09 Registry Services, LLC beer // bentley : 2014-12-18 Bentley Motors Limited @@ -7249,7 +7445,7 @@ best // bestbuy : 2015-07-31 BBY Solutions, Inc. bestbuy -// bet : 2015-05-07 Afilias plc +// bet : 2015-05-07 Afilias Limited bet // bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited @@ -7261,31 +7457,28 @@ bible // bid : 2013-12-19 dot Bid Limited bid -// bike : 2013-08-27 Grand Hollow, LLC +// bike : 2013-08-27 Binky Moon, LLC bike // bing : 2014-12-18 Microsoft Corporation bing -// bingo : 2014-12-04 Sand Cedar, LLC +// bingo : 2014-12-04 Binky Moon, LLC bingo -// bio : 2014-03-06 STARTING DOT LIMITED +// bio : 2014-03-06 Afilias Limited bio // black : 2014-01-16 Afilias Limited black -// blackfriday : 2014-01-16 Uniregistry, Corp. +// blackfriday : 2014-01-16 UNR Corp. blackfriday -// blanco : 2015-07-16 BLANCO GmbH + Co KG -blanco - // blockbuster : 2015-07-30 Dish DBS Corporation blockbuster -// blog : 2015-05-14 PRIMER NIVEL S.A. +// blog : 2015-05-14 Knock Knock WHOIS There, LLC blog // bloomberg : 2014-07-17 Bloomberg IP Holdings LLC @@ -7300,55 +7493,49 @@ bms // bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft bmw -// bnl : 2014-07-24 Banca Nazionale del Lavoro -bnl - // bnpparibas : 2014-05-29 BNP Paribas bnpparibas -// boats : 2014-12-04 DERBoats, LLC +// boats : 2014-12-04 XYZ.COM LLC boats // boehringer : 2015-07-09 Boehringer Ingelheim International GmbH boehringer -// bofa : 2015-07-31 NMS Services, Inc. +// bofa : 2015-07-31 Bank of America Corporation bofa // bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br bom -// bond : 2014-06-05 Bond University Limited +// bond : 2014-06-05 ShortDot SA bond // boo : 2014-01-30 Charleston Road Registry Inc. boo -// book : 2015-08-27 Amazon EU S.à r.l. +// book : 2015-08-27 Amazon Registry Services, Inc. book // booking : 2015-07-16 Booking.com B.V. booking -// boots : 2015-01-08 THE BOOTS COMPANY PLC -boots - // bosch : 2015-06-18 Robert Bosch GMBH bosch // bostik : 2015-05-28 Bostik SA bostik -// boston : 2015-12-10 Boston Globe Media Partners, LLC +// boston : 2015-12-10 Registry Services, LLC boston -// bot : 2014-12-18 Amazon EU S.à r.l. +// bot : 2014-12-18 Amazon Registry Services, Inc. bot -// boutique : 2013-11-14 Over Galley, LLC +// boutique : 2013-11-14 Binky Moon, LLC boutique -// box : 2015-11-12 NS1 Limited +// box : 2015-11-12 Intercap Registry Inc. box // bradesco : 2014-12-18 Banco Bradesco S.A. @@ -7360,7 +7547,7 @@ bridgestone // broadway : 2014-12-22 Celebrate Broadway, Inc. broadway -// broker : 2014-12-11 IG Group Holdings PLC +// broker : 2014-12-11 Dog Beach, LLC broker // brother : 2015-01-29 Brother Industries, Ltd. @@ -7369,7 +7556,7 @@ brother // brussels : 2014-02-06 DNS.be vzw brussels -// budapest : 2013-11-21 Top Level Domain Holdings Limited +// budapest : 2013-11-21 Minds + Machines Group Limited budapest // bugatti : 2015-07-23 Bugatti International SA @@ -7378,13 +7565,13 @@ bugatti // build : 2013-11-07 Plan Bee LLC build -// builders : 2013-11-07 Atomic Madison, LLC +// builders : 2013-11-07 Binky Moon, LLC builders -// business : 2013-11-07 Spring Cross, LLC +// business : 2013-11-07 Binky Moon, LLC business -// buy : 2014-12-18 Amazon EU S.à r.l. +// buy : 2014-12-18 Amazon Registry Services, Inc. buy // buzz : 2013-10-02 DOTSTRATEGY CO. @@ -7393,25 +7580,28 @@ buzz // bzh : 2014-02-27 Association www.bzh bzh -// cab : 2013-10-24 Half Sunset, LLC +// cab : 2013-10-24 Binky Moon, LLC cab -// cafe : 2015-02-11 Pioneer Canyon, LLC +// cafe : 2015-02-11 Binky Moon, LLC cafe // cal : 2014-07-24 Charleston Road Registry Inc. cal -// call : 2014-12-18 Amazon EU S.à r.l. +// call : 2014-12-18 Amazon Registry Services, Inc. call // calvinklein : 2015-07-30 PVH gTLD Holdings LLC calvinklein -// camera : 2013-08-27 Atomic Maple, LLC +// cam : 2016-04-21 Cam Connecting SARL +cam + +// camera : 2013-08-27 Binky Moon, LLC camera -// camp : 2013-11-07 Delta Dynamite, LLC +// camp : 2013-11-07 Binky Moon, LLC camp // cancerresearch : 2014-05-15 Australian Cancer Research Foundation @@ -7423,52 +7613,46 @@ canon // capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry capetown -// capital : 2014-03-06 Delta Mill, LLC +// capital : 2014-03-06 Binky Moon, LLC capital // capitalone : 2015-08-06 Capital One Financial Corporation capitalone -// car : 2015-01-22 +// car : 2015-01-22 XYZ.COM LLC car // caravan : 2013-12-12 Caravan International, Inc. caravan -// cards : 2013-12-05 Foggy Hollow, LLC +// cards : 2013-12-05 Binky Moon, LLC cards -// care : 2014-03-06 Goose Cross +// care : 2014-03-06 Binky Moon, LLC care // career : 2013-10-09 dotCareer LLC career -// careers : 2013-10-02 Wild Corner, LLC +// careers : 2013-10-02 Binky Moon, LLC careers -// cars : 2014-11-13 +// cars : 2014-11-13 XYZ.COM LLC cars -// cartier : 2014-06-23 Richemont DNS Inc. -cartier - -// casa : 2013-11-21 Top Level Domain Holdings Limited +// casa : 2013-11-21 Registry Services, LLC casa -// case : 2015-09-03 CNH Industrial N.V. +// case : 2015-09-03 Helium TLDs Ltd case -// caseih : 2015-09-03 CNH Industrial N.V. -caseih - -// cash : 2014-03-06 Delta Lake, LLC +// cash : 2014-03-06 Binky Moon, LLC cash -// casino : 2014-12-18 Binky Sky, LLC +// casino : 2014-12-18 Binky Moon, LLC casino -// catering : 2013-12-05 New Falls. LLC +// catering : 2013-12-05 Binky Moon, LLC catering // catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) @@ -7486,10 +7670,7 @@ cbre // cbs : 2015-08-06 CBS Domains Inc. cbs -// ceb : 2015-04-09 The Corporate Executive Board Company -ceb - -// center : 2013-11-07 Tin Mill, LLC +// center : 2013-11-07 Binky Moon, LLC center // ceo : 2013-11-07 CEOTLD Pty Ltd @@ -7501,7 +7682,7 @@ cern // cfa : 2014-08-28 CFA Institute cfa -// cfd : 2014-12-11 IG Group Holdings PLC +// cfd : 2014-12-11 ShortDot SA cfd // chanel : 2015-04-09 Chanel International B.V. @@ -7510,37 +7691,34 @@ chanel // channel : 2014-05-08 Charleston Road Registry Inc. channel -// chase : 2015-04-30 JPMorgan Chase & Co. +// charity : 2018-04-11 Binky Moon, LLC +charity + +// chase : 2015-04-30 JPMorgan Chase Bank, National Association chase -// chat : 2014-12-04 Sand Fields, LLC +// chat : 2014-12-04 Binky Moon, LLC chat -// cheap : 2013-11-14 Sand Cover, LLC +// cheap : 2013-11-14 Binky Moon, LLC cheap // chintai : 2015-06-11 CHINTAI Corporation chintai -// chloe : 2014-10-16 Richemont DNS Inc. -chloe - -// christmas : 2013-11-21 Uniregistry, Corp. +// christmas : 2013-11-21 UNR Corp. christmas // chrome : 2014-07-24 Charleston Road Registry Inc. chrome -// chrysler : 2015-07-30 FCA US LLC. -chrysler - -// church : 2014-02-06 Holly Fields, LLC +// church : 2014-02-06 Binky Moon, LLC church // cipriani : 2015-02-19 Hotel Cipriani Srl cipriani -// circle : 2014-12-18 Amazon EU S.à r.l. +// circle : 2014-12-18 Amazon Registry Services, Inc. circle // cisco : 2014-12-22 Cisco Technology, Inc. @@ -7555,52 +7733,52 @@ citi // citic : 2014-01-09 CITIC Group Corporation citic -// city : 2014-05-29 Snow Sky, LLC +// city : 2014-05-29 Binky Moon, LLC city // cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc. cityeats -// claims : 2014-03-20 Black Corner, LLC +// claims : 2014-03-20 Binky Moon, LLC claims -// cleaning : 2013-12-05 Fox Shadow, LLC +// cleaning : 2013-12-05 Binky Moon, LLC cleaning -// click : 2014-06-05 Uniregistry, Corp. +// click : 2014-06-05 UNR Corp. click -// clinic : 2014-03-20 Goose Park, LLC +// clinic : 2014-03-20 Binky Moon, LLC clinic // clinique : 2015-10-01 The Estée Lauder Companies Inc. clinique -// clothing : 2013-08-27 Steel Lake, LLC +// clothing : 2013-08-27 Binky Moon, LLC clothing -// cloud : 2015-04-16 ARUBA S.p.A. +// cloud : 2015-04-16 Aruba PEC S.p.A. cloud -// club : 2013-11-08 .CLUB DOMAINS, LLC +// club : 2013-11-08 Registry Services, LLC club // clubmed : 2015-06-25 Club Méditerranée S.A. clubmed -// coach : 2014-10-09 Koko Island, LLC +// coach : 2014-10-09 Binky Moon, LLC coach -// codes : 2013-10-31 Puff Willow, LLC +// codes : 2013-10-31 Binky Moon, LLC codes -// coffee : 2013-10-17 Trixy Cover, LLC +// coffee : 2013-10-17 Binky Moon, LLC coffee // college : 2014-01-16 XYZ.COM LLC college -// cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH +// cologne : 2014-02-05 dotKoeln GmbH cologne // comcast : 2015-07-23 Comcast IP Holdings I, LLC @@ -7609,67 +7787,70 @@ comcast // commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA commbank -// community : 2013-12-05 Fox Orchard, LLC +// community : 2013-12-05 Binky Moon, LLC community -// company : 2013-11-07 Silver Avenue, LLC +// company : 2013-11-07 Binky Moon, LLC company -// compare : 2015-10-08 iSelect Ltd +// compare : 2015-10-08 Registry Services, LLC compare -// computer : 2013-10-24 Pine Mill, LLC +// computer : 2013-10-24 Binky Moon, LLC computer // comsec : 2015-01-08 VeriSign, Inc. comsec -// condos : 2013-12-05 Pine House, LLC +// condos : 2013-12-05 Binky Moon, LLC condos -// construction : 2013-09-16 Fox Dynamite, LLC +// construction : 2013-09-16 Binky Moon, LLC construction -// consulting : 2013-12-05 +// consulting : 2013-12-05 Dog Beach, LLC consulting -// contact : 2015-01-08 Top Level Spectrum, Inc. +// contact : 2015-01-08 Dog Beach, LLC contact -// contractors : 2013-09-10 Magic Woods, LLC +// contractors : 2013-09-10 Binky Moon, LLC contractors -// cooking : 2013-11-21 Top Level Domain Holdings Limited +// cooking : 2013-11-21 Registry Services, LLC cooking // cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. cookingchannel -// cool : 2013-11-14 Koko Lake, LLC +// cool : 2013-11-14 Binky Moon, LLC cool -// corsica : 2014-09-25 Collectivité Territoriale de Corse +// corsica : 2014-09-25 Collectivité de Corse corsica -// country : 2013-12-19 Top Level Domain Holdings Limited +// country : 2013-12-19 DotCountry LLC country -// coupon : 2015-02-26 Amazon EU S.à r.l. +// coupon : 2015-02-26 Amazon Registry Services, Inc. coupon -// coupons : 2015-03-26 Black Island, LLC +// coupons : 2015-03-26 Binky Moon, LLC coupons // courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD courses -// credit : 2014-03-20 Snow Shadow, LLC +// cpa : 2019-06-10 American Institute of Certified Public Accountants +cpa + +// credit : 2014-03-20 Binky Moon, LLC credit -// creditcard : 2014-03-20 Binky Frostbite, LLC +// creditcard : 2014-03-20 Binky Moon, LLC creditcard -// creditunion : 2015-01-22 CUNA Performance Resources, LLC +// creditunion : 2015-01-22 DotCooperation LLC creditunion // cricket : 2014-10-09 dot Cricket Limited @@ -7684,19 +7865,16 @@ crs // cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd. cruise -// cruises : 2013-12-05 Spring Way, LLC +// cruises : 2013-12-05 Binky Moon, LLC cruises -// csc : 2014-09-25 Alliance-One Services, Inc. -csc - -// cuisinella : 2014-04-03 SALM S.A.S. +// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S. cuisinella // cymru : 2014-05-08 Nominet UK cymru -// cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd. +// cyou : 2015-01-22 ShortDot SA cyou // dabur : 2014-02-06 Dabur India Limited @@ -7705,13 +7883,16 @@ dabur // dad : 2014-01-23 Charleston Road Registry Inc. dad -// dance : 2013-10-24 United TLD Holdco Ltd. +// dance : 2013-10-24 Dog Beach, LLC dance +// data : 2016-06-02 Dish DBS Corporation +data + // date : 2014-11-20 dot Date Limited date -// dating : 2013-12-05 Pine Fest, LLC +// dating : 2013-12-05 Binky Moon, LLC dating // datsun : 2014-03-27 NISSAN MOTOR CO., LTD. @@ -7723,22 +7904,22 @@ day // dclk : 2014-11-20 Charleston Road Registry Inc. dclk -// dds : 2015-05-07 Top Level Domain Holdings Limited +// dds : 2015-05-07 Registry Services, LLC dds -// deal : 2015-06-25 Amazon EU S.à r.l. +// deal : 2015-06-25 Amazon Registry Services, Inc. deal -// dealer : 2014-12-22 Dealer Dot Com, Inc. +// dealer : 2014-12-22 Intercap Registry Inc. dealer -// deals : 2014-05-22 Sand Sunset, LLC +// deals : 2014-05-22 Binky Moon, LLC deals -// degree : 2014-03-06 +// degree : 2014-03-06 Dog Beach, LLC degree -// delivery : 2014-09-11 Steel Station, LLC +// delivery : 2014-09-11 Binky Moon, LLC delivery // dell : 2014-10-24 Dell Inc. @@ -7750,19 +7931,19 @@ deloitte // delta : 2015-02-19 Delta Air Lines, Inc. delta -// democrat : 2013-10-24 United TLD Holdco Ltd. +// democrat : 2013-10-24 Dog Beach, LLC democrat -// dental : 2014-03-20 Tin Birch, LLC +// dental : 2014-03-20 Binky Moon, LLC dental -// dentist : 2014-03-20 +// dentist : 2014-03-20 Dog Beach, LLC dentist // desi : 2013-11-14 Desi Networks LLC desi -// design : 2014-11-07 Top Level Design, LLC +// design : 2014-11-07 Registry Services, LLC design // dev : 2014-10-16 Charleston Road Registry Inc. @@ -7771,22 +7952,22 @@ dev // dhl : 2015-07-23 Deutsche Post AG dhl -// diamonds : 2013-09-22 John Edge, LLC +// diamonds : 2013-09-22 Binky Moon, LLC diamonds -// diet : 2014-06-26 Uniregistry, Corp. +// diet : 2014-06-26 UNR Corp. diet -// digital : 2014-03-06 Dash Park, LLC +// digital : 2014-03-06 Binky Moon, LLC digital -// direct : 2014-04-10 Half Trail, LLC +// direct : 2014-04-10 Binky Moon, LLC direct -// directory : 2013-09-20 Extra Madison, LLC +// directory : 2013-09-20 Binky Moon, LLC directory -// discount : 2014-03-06 Holly Hill, LLC +// discount : 2014-03-06 Binky Moon, LLC discount // discover : 2015-07-23 Discover Financial Services @@ -7804,21 +7985,15 @@ dnp // docs : 2014-10-16 Charleston Road Registry Inc. docs -// dodge : 2015-07-30 FCA US LLC. -dodge +// doctor : 2016-06-02 Binky Moon, LLC +doctor -// dog : 2014-12-04 Koko Mill, LLC +// dog : 2014-12-04 Binky Moon, LLC dog -// doha : 2014-09-18 Communications Regulatory Authority (CRA) -doha - -// domains : 2013-10-17 Sugar Cross, LLC +// domains : 2013-10-17 Binky Moon, LLC domains -// doosan : 2014-04-03 Doosan Corporation -doosan - // dot : 2015-05-21 Dish DBS Corporation dot @@ -7828,25 +8003,16 @@ download // drive : 2015-03-05 Charleston Road Registry Inc. drive -// dstv : 2015-03-12 MultiChoice (Proprietary) Limited -dstv - // dtv : 2015-06-04 Dish DBS Corporation dtv // dubai : 2015-01-01 Dubai Smart Government Department dubai -// duck : 2015-07-23 Johnson Shareholdings, Inc. -duck - // dunlop : 2015-07-02 The Goodyear Tire & Rubber Company dunlop -// duns : 2015-08-06 The Dun & Bradstreet Corporation -duns - -// dupont : 2015-06-25 E.I. du Pont de Nemours and Company +// dupont : 2015-06-25 DuPont Specialty Products USA, LLC dupont // durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry @@ -7855,8 +8021,8 @@ durban // dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG dvag -// dwg : 2015-07-23 Autodesk, Inc. -dwg +// dvr : 2016-05-26 DISH Technologies L.L.C. +dvr // earth : 2014-12-04 Interlink Co., Ltd. earth @@ -7864,40 +8030,37 @@ earth // eat : 2014-01-23 Charleston Road Registry Inc. eat +// eco : 2016-07-08 Big Room Inc. +eco + // edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V. edeka -// education : 2013-11-07 Brice Way, LLC +// education : 2013-11-07 Binky Moon, LLC education -// email : 2013-10-31 Spring Madison, LLC +// email : 2013-10-31 Binky Moon, LLC email // emerck : 2014-04-03 Merck KGaA emerck -// emerson : 2015-07-23 Emerson Electric Co. -emerson - -// energy : 2014-09-11 Binky Birch, LLC +// energy : 2014-09-11 Binky Moon, LLC energy -// engineer : 2014-03-06 United TLD Holdco Ltd. +// engineer : 2014-03-06 Dog Beach, LLC engineer -// engineering : 2014-03-06 Romeo Canyon +// engineering : 2014-03-06 Binky Moon, LLC engineering -// enterprises : 2013-09-20 Snow Oaks, LLC +// enterprises : 2013-09-20 Binky Moon, LLC enterprises -// epost : 2015-07-23 Deutsche Post AG -epost - // epson : 2014-12-04 Seiko Epson Corporation epson -// equipment : 2013-08-27 Corn Station, LLC +// equipment : 2013-08-27 Binky Moon, LLC equipment // ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson @@ -7909,12 +8072,9 @@ erni // esq : 2014-05-08 Charleston Road Registry Inc. esq -// estate : 2013-08-27 Trixy Park, LLC +// estate : 2013-08-27 Binky Moon, LLC estate -// esurance : 2015-07-23 Esurance Insurance Company -esurance - // etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) etisalat @@ -7924,22 +8084,19 @@ eurovision // eus : 2013-12-12 Puntueus Fundazioa eus -// events : 2013-12-05 Pioneer Maple, LLC +// events : 2013-12-05 Binky Moon, LLC events -// everbank : 2014-05-15 EverBank -everbank - -// exchange : 2014-03-06 Spring Falls, LLC +// exchange : 2014-03-06 Binky Moon, LLC exchange -// expert : 2013-11-21 Magic Pass, LLC +// expert : 2013-11-21 Binky Moon, LLC expert -// exposed : 2013-12-05 Victor Beach, LLC +// exposed : 2013-12-05 Binky Moon, LLC exposed -// express : 2015-02-11 Sea Sunset, LLC +// express : 2015-02-11 Binky Moon, LLC express // extraspace : 2015-05-14 Extra Space Storage LLC @@ -7948,7 +8105,7 @@ extraspace // fage : 2014-12-18 Fage International S.A. fage -// fail : 2014-03-06 Atomic Pipe, LLC +// fail : 2014-03-06 Binky Moon, LLC fail // fairwinds : 2014-11-13 FairWinds Partners, LLC @@ -7957,25 +8114,25 @@ fairwinds // faith : 2014-11-20 dot Faith Limited faith -// family : 2015-04-02 +// family : 2015-04-02 Dog Beach, LLC family -// fan : 2014-03-06 +// fan : 2014-03-06 Dog Beach, LLC fan -// fans : 2014-11-07 Asiamix Digital Limited +// fans : 2014-11-07 ZDNS International Limited fans -// farm : 2013-11-07 Just Maple, LLC +// farm : 2013-11-07 Binky Moon, LLC farm // farmers : 2015-07-09 Farmers Insurance Exchange farmers -// fashion : 2014-07-03 Top Level Domain Holdings Limited +// fashion : 2014-07-03 Registry Services, LLC fashion -// fast : 2014-12-18 Amazon EU S.à r.l. +// fast : 2014-12-18 Amazon Registry Services, Inc. fast // fedex : 2015-08-06 Federal Express Corporation @@ -7996,7 +8153,7 @@ fiat // fidelity : 2015-07-30 Fidelity Brokerage Services LLC fidelity -// fido : 2015-08-06 Rogers Communications Partnership +// fido : 2015-08-06 Rogers Communications Canada Inc. fido // film : 2015-01-08 Motion Picture Domain Registry Pty Ltd @@ -8005,82 +8162,82 @@ film // final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br final -// finance : 2014-03-20 Cotton Cypress, LLC +// finance : 2014-03-20 Binky Moon, LLC finance -// financial : 2014-03-06 Just Cover, LLC +// financial : 2014-03-06 Binky Moon, LLC financial -// fire : 2015-06-25 Amazon EU S.à r.l. +// fire : 2015-06-25 Amazon Registry Services, Inc. fire -// firestone : 2014-12-18 Bridgestone Corporation +// firestone : 2014-12-18 Bridgestone Licensing Services, Inc firestone // firmdale : 2014-03-27 Firmdale Holdings Limited firmdale -// fish : 2013-12-12 Fox Woods, LLC +// fish : 2013-12-12 Binky Moon, LLC fish -// fishing : 2013-11-21 Top Level Domain Holdings Limited +// fishing : 2013-11-21 Registry Services, LLC fishing -// fit : 2014-11-07 Top Level Domain Holdings Limited +// fit : 2014-11-07 Registry Services, LLC fit -// fitness : 2014-03-06 Brice Orchard, LLC +// fitness : 2014-03-06 Binky Moon, LLC fitness -// flickr : 2015-04-02 Yahoo! Domain Services Inc. +// flickr : 2015-04-02 Flickr, Inc. flickr -// flights : 2013-12-05 Fox Station, LLC +// flights : 2013-12-05 Binky Moon, LLC flights // flir : 2015-07-23 FLIR Systems, Inc. flir -// florist : 2013-11-07 Half Cypress, LLC +// florist : 2013-11-07 Binky Moon, LLC florist -// flowers : 2014-10-09 Uniregistry, Corp. +// flowers : 2014-10-09 UNR Corp. flowers -// flsmidth : 2014-07-24 FLSmidth A/S -flsmidth - // fly : 2014-05-08 Charleston Road Registry Inc. fly // foo : 2014-01-23 Charleston Road Registry Inc. foo +// food : 2016-04-21 Lifestyle Domain Holdings, Inc. +food + // foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc. foodnetwork -// football : 2014-12-18 Foggy Farms, LLC +// football : 2014-12-18 Binky Moon, LLC football // ford : 2014-11-13 Ford Motor Company ford -// forex : 2014-12-11 IG Group Holdings PLC +// forex : 2014-12-11 Dog Beach, LLC forex -// forsale : 2014-05-22 +// forsale : 2014-05-22 Dog Beach, LLC forsale // forum : 2015-04-02 Fegistry, LLC forum -// foundation : 2013-12-05 John Dale, LLC +// foundation : 2013-12-05 Binky Moon, LLC foundation // fox : 2015-09-11 FOX Registry, LLC fox -// free : 2015-12-10 Amazon EU S.à r.l. +// free : 2015-12-10 Amazon Registry Services, Inc. free // fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH @@ -8104,25 +8261,25 @@ ftr // fujitsu : 2015-07-30 Fujitsu Limited fujitsu -// fujixerox : 2015-07-23 Xerox DNHC LLC -fujixerox +// fun : 2016-01-14 Radix FZC +fun -// fund : 2014-03-20 John Castle, LLC +// fund : 2014-03-20 Binky Moon, LLC fund -// furniture : 2014-03-20 Lone Fields, LLC +// furniture : 2014-03-20 Binky Moon, LLC furniture -// futbol : 2013-09-20 +// futbol : 2013-09-20 Dog Beach, LLC futbol -// fyi : 2015-04-02 Silver Tigers, LLC +// fyi : 2015-04-02 Binky Moon, LLC fyi // gal : 2013-11-07 Asociación puntoGAL gal -// gallery : 2013-09-13 Sugar House, LLC +// gallery : 2013-09-13 Binky Moon, LLC gallery // gallo : 2015-06-11 Gallo Vineyards, Inc. @@ -8131,18 +8288,21 @@ gallo // gallup : 2015-02-19 Gallup, Inc. gallup -// game : 2015-05-28 Uniregistry, Corp. +// game : 2015-05-28 UNR Corp. game -// games : 2015-05-28 Foggy Beach, LLC +// games : 2015-05-28 Dog Beach, LLC games // gap : 2015-07-31 The Gap, Inc. gap -// garden : 2014-06-26 Top Level Domain Holdings Limited +// garden : 2014-06-26 Registry Services, LLC garden +// gay : 2019-05-23 Top Level Design, LLC +gay + // gbiz : 2014-07-17 Charleston Road Registry Inc. gbiz @@ -8152,7 +8312,7 @@ gdn // gea : 2014-12-04 GEA Group Aktiengesellschaft gea -// gent : 2014-01-23 COMBELL GROUP NV/SA +// gent : 2014-01-23 COMBELL NV gent // genting : 2015-03-12 Resorts World Inc Pte. Ltd. @@ -8164,28 +8324,25 @@ george // ggee : 2014-01-09 GMO Internet, Inc. ggee -// gift : 2013-10-17 Uniregistry, Corp. +// gift : 2013-10-17 DotGift, LLC gift -// gifts : 2014-07-03 Goose Sky, LLC +// gifts : 2014-07-03 Binky Moon, LLC gifts -// gives : 2014-03-06 United TLD Holdco Ltd. +// gives : 2014-03-06 Dog Beach, LLC gives // giving : 2014-11-13 Giving Limited giving -// glade : 2015-07-23 Johnson Shareholdings, Inc. -glade - -// glass : 2013-11-07 Black Cover, LLC +// glass : 2013-11-07 Binky Moon, LLC glass // gle : 2014-07-24 Charleston Road Registry Inc. gle -// global : 2014-04-17 Dot GLOBAL AS +// global : 2014-04-17 Dot Global Domain Registry Limited global // globo : 2013-12-19 Globo Comunicação e Participações S.A @@ -8194,6 +8351,9 @@ globo // gmail : 2014-05-01 Charleston Road Registry Inc. gmail +// gmbh : 2016-01-29 Binky Moon, LLC +gmbh + // gmo : 2014-01-09 GMO Internet, Inc. gmo @@ -8203,21 +8363,18 @@ gmx // godaddy : 2015-07-23 Go Daddy East, LLC godaddy -// gold : 2015-01-22 June Edge, LLC +// gold : 2015-01-22 Binky Moon, LLC gold // goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD. goldpoint -// golf : 2014-12-18 Lone falls, LLC +// golf : 2014-12-18 Binky Moon, LLC golf // goo : 2014-12-18 NTT Resonant Inc. goo -// goodhands : 2015-07-31 Allstate Fire and Casualty Insurance Company -goodhands - // goodyear : 2015-07-02 The Goodyear Tire & Rubber Company goodyear @@ -8230,28 +8387,28 @@ google // gop : 2014-01-16 Republican State Leadership Committee, Inc. gop -// got : 2014-12-18 Amazon EU S.à r.l. +// got : 2014-12-18 Amazon Registry Services, Inc. got -// gotv : 2015-03-12 MultiChoice (Proprietary) Limited -gotv - // grainger : 2015-05-07 Grainger Registry Services, LLC grainger -// graphics : 2013-09-13 Over Madison, LLC +// graphics : 2013-09-13 Binky Moon, LLC graphics -// gratis : 2014-03-20 Pioneer Tigers, LLC +// gratis : 2014-03-20 Binky Moon, LLC gratis // green : 2014-05-08 Afilias Limited green -// gripe : 2014-03-06 Corn Sunset, LLC +// gripe : 2014-03-06 Binky Moon, LLC gripe -// group : 2014-08-15 Romeo Town, LLC +// grocery : 2016-06-16 Wal-Mart Stores, Inc. +grocery + +// group : 2014-08-15 Binky Moon, LLC group // guardian : 2015-07-30 The Guardian Life Insurance Company of America @@ -8263,16 +8420,16 @@ gucci // guge : 2014-08-28 Charleston Road Registry Inc. guge -// guide : 2013-09-13 Snow Moon, LLC +// guide : 2013-09-13 Binky Moon, LLC guide -// guitars : 2013-11-14 Uniregistry, Corp. +// guitars : 2013-11-14 UNR Corp. guitars -// guru : 2013-08-27 Pioneer Cypress, LLC +// guru : 2013-08-27 Binky Moon, LLC guru -// hair : 2015-12-03 L'Oréal +// hair : 2015-12-03 XYZ.COM LLC hair // hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH @@ -8281,7 +8438,7 @@ hamburg // hangout : 2014-11-13 Charleston Road Registry Inc. hangout -// haus : 2013-12-05 +// haus : 2013-12-05 Dog Beach, LLC haus // hbo : 2015-07-30 HBO Registry Services, Inc. @@ -8296,10 +8453,10 @@ hdfcbank // health : 2015-02-11 DotHealth, LLC health -// healthcare : 2014-06-12 Silver Glen, LLC +// healthcare : 2014-06-12 Binky Moon, LLC healthcare -// help : 2014-06-26 Uniregistry, Corp. +// help : 2014-06-26 UNR Corp. help // helsinki : 2015-02-05 City of Helsinki @@ -8314,7 +8471,7 @@ hermes // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv -// hiphop : 2014-03-06 Uniregistry, Corp. +// hiphop : 2014-03-06 UNR Corp. hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. @@ -8323,28 +8480,28 @@ hisamitsu // hitachi : 2014-10-31 Hitachi, Ltd. hitachi -// hiv : 2014-03-13 +// hiv : 2014-03-13 UNR Corp. hiv // hkt : 2015-05-14 PCCW-HKT DataCom Services Limited hkt -// hockey : 2015-03-19 Half Willow, LLC +// hockey : 2015-03-19 Binky Moon, LLC hockey -// holdings : 2013-08-27 John Madison, LLC +// holdings : 2013-08-27 Binky Moon, LLC holdings -// holiday : 2013-11-07 Goose Woods, LLC +// holiday : 2013-11-07 Binky Moon, LLC holiday -// homedepot : 2015-04-02 Homer TLC, Inc. +// homedepot : 2015-04-02 Home Depot Product Authority, LLC homedepot // homegoods : 2015-07-16 The TJX Companies, Inc. homegoods -// homes : 2014-01-09 DERHomes, LLC +// homes : 2014-01-09 XYZ.COM LLC homes // homesense : 2015-07-16 The TJX Companies, Inc. @@ -8353,39 +8510,39 @@ homesense // honda : 2014-12-18 Honda Motor Co., Ltd. honda -// honeywell : 2015-07-23 Honeywell GTLD LLC -honeywell - -// horse : 2013-11-21 Top Level Domain Holdings Limited +// horse : 2013-11-21 Registry Services, LLC horse -// host : 2014-04-17 DotHost Inc. +// hospital : 2016-10-20 Binky Moon, LLC +hospital + +// host : 2014-04-17 Radix FZC host -// hosting : 2014-05-29 Uniregistry, Corp. +// hosting : 2014-05-29 UNR Corp. hosting -// hot : 2015-08-27 Amazon EU S.à r.l. +// hot : 2015-08-27 Amazon Registry Services, Inc. hot // hoteles : 2015-03-05 Travel Reservations SRL hoteles +// hotels : 2016-04-07 Booking.com B.V. +hotels + // hotmail : 2014-12-18 Microsoft Corporation hotmail -// house : 2013-11-07 Sugar Park, LLC +// house : 2013-11-07 Binky Moon, LLC house // how : 2014-01-23 Charleston Road Registry Inc. how -// hsbc : 2014-10-24 HSBC Holdings PLC +// hsbc : 2014-10-24 HSBC Global Services (UK) Limited hsbc -// htc : 2015-04-02 HTC corporation -htc - // hughes : 2015-07-30 Hughes Satellite Systems Corporation hughes @@ -8404,7 +8561,7 @@ icbc // ice : 2014-10-30 IntercontinentalExchange, Inc. ice -// icu : 2015-01-08 One.com A/S +// icu : 2015-01-08 ShortDot SA icu // ieee : 2015-07-23 IEEE Global LLC @@ -8413,25 +8570,25 @@ ieee // ifm : 2014-01-30 ifm electronic gmbh ifm -// iinet : 2014-07-03 Connect West Pty. Ltd. -iinet - // ikano : 2015-07-09 Ikano S.A. ikano // imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) imamat -// imdb : 2015-06-25 Amazon EU S.à r.l. +// imdb : 2015-06-25 Amazon Registry Services, Inc. imdb -// immo : 2014-07-10 Auburn Bloom, LLC +// immo : 2014-07-10 Binky Moon, LLC immo -// immobilien : 2013-11-07 United TLD Holdco Ltd. +// immobilien : 2013-11-07 Dog Beach, LLC immobilien -// industries : 2013-12-05 Outer House, LLC +// inc : 2018-03-10 Intercap Registry Inc. +inc + +// industries : 2013-12-05 Binky Moon, LLC industries // infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. @@ -8443,36 +8600,30 @@ ing // ink : 2013-12-05 Top Level Design, LLC ink -// institute : 2013-11-07 Outer Maple, LLC +// institute : 2013-11-07 Binky Moon, LLC institute // insurance : 2015-02-19 fTLD Registry Services LLC insurance -// insure : 2014-03-20 Pioneer Willow, LLC +// insure : 2014-03-20 Binky Moon, LLC insure -// intel : 2015-08-06 Intel Corporation -intel - -// international : 2013-11-07 Wild Way, LLC +// international : 2013-11-07 Binky Moon, LLC international // intuit : 2015-07-30 Intuit Administrative Services, Inc. intuit -// investments : 2014-03-20 Holly Glen, LLC +// investments : 2014-03-20 Binky Moon, LLC investments // ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. ipiranga -// irish : 2014-08-07 Dot-Irish LLC +// irish : 2014-08-07 Binky Moon, LLC irish -// iselect : 2015-02-11 iSelect Ltd -iselect - // ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) ismaili @@ -8488,12 +8639,6 @@ itau // itv : 2015-07-09 ITV Services Limited itv -// iveco : 2015-09-03 CNH Industrial N.V. -iveco - -// iwc : 2014-06-23 Richemont DNS Inc. -iwc - // jaguar : 2014-11-13 Jaguar Land Rover Ltd jaguar @@ -8503,24 +8648,18 @@ java // jcb : 2014-11-20 JCB Co., Ltd. jcb -// jcp : 2015-04-23 JCP Media, Inc. -jcp - // jeep : 2015-07-30 FCA US LLC. jeep -// jetzt : 2014-01-09 New TLD Company AB +// jetzt : 2014-01-09 Binky Moon, LLC jetzt -// jewelry : 2015-03-05 Wild Bloom, LLC +// jewelry : 2015-03-05 Binky Moon, LLC jewelry -// jio : 2015-04-02 Affinity Names, Inc. +// jio : 2015-04-02 Reliance Industries Limited jio -// jlc : 2014-12-04 Richemont DNS Inc. -jlc - // jll : 2015-04-02 Jones Lang LaSalle Incorporated jll @@ -8533,25 +8672,25 @@ jnj // joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry joburg -// jot : 2014-12-18 Amazon EU S.à r.l. +// jot : 2014-12-18 Amazon Registry Services, Inc. jot -// joy : 2014-12-18 Amazon EU S.à r.l. +// joy : 2014-12-18 Amazon Registry Services, Inc. joy -// jpmorgan : 2015-04-30 JPMorgan Chase & Co. +// jpmorgan : 2015-04-30 JPMorgan Chase Bank, National Association jpmorgan // jprs : 2014-09-18 Japan Registry Services Co., Ltd. jprs -// juegos : 2014-03-20 Uniregistry, Corp. +// juegos : 2014-03-20 UNR Corp. juegos // juniper : 2015-07-30 JUNIPER NETWORKS, INC. juniper -// kaufen : 2013-11-07 United TLD Holdco Ltd. +// kaufen : 2013-11-07 Dog Beach, LLC kaufen // kddi : 2014-09-12 KDDI CORPORATION @@ -8572,22 +8711,25 @@ kfh // kia : 2015-07-09 KIA MOTORS CORPORATION kia +// kids : 2021-08-13 DotKids Foundation Limited +kids + // kim : 2013-09-23 Afilias Limited kim // kinder : 2014-11-07 Ferrero Trading Lux S.A. kinder -// kindle : 2015-06-25 Amazon EU S.à r.l. +// kindle : 2015-06-25 Amazon Registry Services, Inc. kindle -// kitchen : 2013-09-20 Just Goodbye, LLC +// kitchen : 2013-09-20 Binky Moon, LLC kitchen // kiwi : 2013-09-20 DOT KIWI LIMITED kiwi -// koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH +// koeln : 2014-01-09 dotKoeln GmbH koeln // komatsu : 2015-01-08 Komatsu Ltd. @@ -8611,18 +8753,12 @@ kred // kuokgroup : 2015-04-09 Kerry Trading Co. Limited kuokgroup -// kyknet : 2015-03-05 Electronic Media Network (Pty) Ltd -kyknet - // kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen kyoto -// lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA +// lacaixa : 2014-01-09 Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa” lacaixa -// ladbrokes : 2015-08-06 LADBROKES INTERNATIONAL PLC -ladbrokes - // lamborghini : 2015-06-04 Automobili Lamborghini S.p.A. lamborghini @@ -8635,10 +8771,7 @@ lancaster // lancia : 2015-07-31 Fiat Chrysler Automobiles N.V. lancia -// lancome : 2015-07-23 L'Oréal -lancome - -// land : 2013-09-10 Pine Moon, LLC +// land : 2013-09-10 Binky Moon, LLC land // landrover : 2014-11-13 Jaguar Land Rover Ltd @@ -8659,16 +8792,16 @@ latino // latrobe : 2014-06-16 La Trobe University latrobe -// law : 2015-01-22 Minds + Machines Group Limited +// law : 2015-01-22 Registry Services, LLC law -// lawyer : 2014-03-20 +// lawyer : 2014-03-20 Dog Beach, LLC lawyer -// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +// lds : 2014-03-20 IRI Domain Management, LLC lds -// lease : 2014-03-06 Victor Trail, LLC +// lease : 2014-03-06 Binky Moon, LLC lease // leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc @@ -8677,7 +8810,7 @@ leclerc // lefrak : 2015-07-16 LeFrak Organization, Inc. lefrak -// legal : 2014-10-16 Blue Falls, LLC +// legal : 2014-10-16 Binky Moon, LLC legal // lego : 2015-07-16 LEGO Juris A/S @@ -8689,13 +8822,10 @@ lexus // lgbt : 2014-05-08 Afilias Limited lgbt -// liaison : 2014-10-02 Liaison Technologies, Incorporated -liaison - // lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG lidl -// life : 2014-02-06 Trixy Oaks, LLC +// life : 2014-02-06 Binky Moon, LLC life // lifeinsurance : 2015-01-15 American Council of Life Insurers @@ -8704,19 +8834,19 @@ lifeinsurance // lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc. lifestyle -// lighting : 2013-08-27 John McCook, LLC +// lighting : 2013-08-27 Binky Moon, LLC lighting -// like : 2014-12-18 Amazon EU S.à r.l. +// like : 2014-12-18 Amazon Registry Services, Inc. like // lilly : 2015-07-31 Eli Lilly and Company lilly -// limited : 2014-03-06 Big Fest, LLC +// limited : 2014-03-06 Binky Moon, LLC limited -// limo : 2013-10-17 Hidden Frostbite, LLC +// limo : 2013-10-17 Binky Moon, LLC limo // lincoln : 2014-11-13 Ford Motor Company @@ -8725,25 +8855,28 @@ lincoln // linde : 2014-12-04 Linde Aktiengesellschaft linde -// link : 2013-11-14 Uniregistry, Corp. +// link : 2013-11-14 UNR Corp. link // lipsy : 2015-06-25 Lipsy Ltd lipsy -// live : 2014-12-04 +// live : 2014-12-04 Dog Beach, LLC live // living : 2015-07-30 Lifestyle Domain Holdings, Inc. living -// lixil : 2015-03-19 LIXIL Group Corporation -lixil +// llc : 2017-12-14 Afilias Limited +llc + +// llp : 2019-08-26 UNR Corp. +llp // loan : 2014-11-20 dot Loan Limited loan -// loans : 2014-03-20 June Woods, LLC +// loans : 2014-03-20 Binky Moon, LLC loans // locker : 2015-06-04 Dish DBS Corporation @@ -8755,7 +8888,7 @@ locus // loft : 2015-07-30 Annco, Inc. loft -// lol : 2015-01-30 Uniregistry, Corp. +// lol : 2015-01-30 UNR Corp. lol // london : 2013-11-14 Dot London Domains Limited @@ -8776,19 +8909,16 @@ lpl // lplfinancial : 2015-07-30 LPL Holdings, Inc. lplfinancial -// ltd : 2014-09-25 Over Corner, LLC +// ltd : 2014-09-25 Binky Moon, LLC ltd -// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA +// ltda : 2014-04-17 InterNetX, Corp ltda // lundbeck : 2015-08-06 H. Lundbeck A/S lundbeck -// lupin : 2014-11-07 LUPIN LIMITED -lupin - -// luxe : 2014-01-09 Top Level Domain Holdings Limited +// luxe : 2014-01-09 Registry Services, LLC luxe // luxury : 2013-10-17 Luxury Partners, LLC @@ -8803,28 +8933,31 @@ madrid // maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) maif -// maison : 2013-12-05 Victor Frostbite, LLC +// maison : 2013-12-05 Binky Moon, LLC maison -// makeup : 2015-01-15 L'Oréal +// makeup : 2015-01-15 XYZ.COM LLC makeup // man : 2014-12-04 MAN SE man -// management : 2013-11-07 John Goodbye, LLC +// management : 2013-11-07 Binky Moon, LLC management // mango : 2013-10-24 PUNTO FA S.L. mango -// market : 2014-03-06 +// map : 2016-06-09 Charleston Road Registry Inc. +map + +// market : 2014-03-06 Dog Beach, LLC market -// marketing : 2013-11-07 Fern Pass, LLC +// marketing : 2013-11-07 Binky Moon, LLC marketing -// markets : 2014-12-11 IG Group Holdings PLC +// markets : 2014-12-11 Dog Beach, LLC markets // marriott : 2014-10-09 Marriott Worldwide Corporation @@ -8839,25 +8972,19 @@ maserati // mattel : 2015-08-06 Mattel Sites, Inc. mattel -// mba : 2015-04-02 Lone Hollow, LLC +// mba : 2015-04-02 Binky Moon, LLC mba -// mcd : 2015-07-30 McDonald’s Corporation -mcd - -// mcdonalds : 2015-07-30 McDonald’s Corporation -mcdonalds - // mckinsey : 2015-07-31 McKinsey Holdings, Inc. mckinsey // med : 2015-08-06 Medistry LLC med -// media : 2014-03-06 Grand Glen, LLC +// media : 2014-03-06 Binky Moon, LLC media -// meet : 2014-01-16 +// meet : 2014-01-16 Charleston Road Registry Inc. meet // melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation @@ -8872,16 +8999,13 @@ memorial // men : 2015-02-26 Exclusive Registry Limited men -// menu : 2013-09-11 Wedding TLD2, LLC +// menu : 2013-09-11 Dot Menu Registry, LLC menu -// meo : 2014-11-07 PT Comunicacoes S.A. -meo +// merckmsd : 2016-07-14 MSD Registry Holdings, Inc. +merckmsd -// metlife : 2015-05-07 MetLife Services and Solutions, LLC -metlife - -// miami : 2013-12-19 Top Level Domain Holdings Limited +// miami : 2013-12-19 Registry Services, LLC miami // microsoft : 2014-12-18 Microsoft Corporation @@ -8908,106 +9032,76 @@ mls // mma : 2014-11-07 MMA IARD mma -// mnet : 2015-03-05 Electronic Media Network (Pty) Ltd -mnet - -// mobily : 2014-12-18 GreenTech Consultancy Company W.L.L. -mobily +// mobile : 2016-06-02 Dish DBS Corporation +mobile -// moda : 2013-11-07 United TLD Holdco Ltd. +// moda : 2013-11-07 Dog Beach, LLC moda // moe : 2013-11-13 Interlink Co., Ltd. moe -// moi : 2014-12-18 Amazon EU S.à r.l. +// moi : 2014-12-18 Amazon Registry Services, Inc. moi -// mom : 2015-04-16 Uniregistry, Corp. +// mom : 2015-04-16 UNR Corp. mom // monash : 2013-09-30 Monash University monash -// money : 2014-10-16 Outer McCook, LLC +// money : 2014-10-16 Binky Moon, LLC money -// monster : 2015-09-11 Monster Worldwide, Inc. +// monster : 2015-09-11 XYZ.COM LLC monster -// montblanc : 2014-06-23 Richemont DNS Inc. -montblanc - -// mopar : 2015-07-30 FCA US LLC. -mopar - -// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +// mormon : 2013-12-05 IRI Domain Management, LLC mormon -// mortgage : 2014-03-20 +// mortgage : 2014-03-20 Dog Beach, LLC mortgage // moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) moscow -// moto : 2015-06-04 Charleston Road Registry Inc. +// moto : 2015-06-04 Motorola Trademark Holdings, LLC moto -// motorcycles : 2014-01-09 DERMotorcycles, LLC +// motorcycles : 2014-01-09 XYZ.COM LLC motorcycles // mov : 2014-01-30 Charleston Road Registry Inc. mov -// movie : 2015-02-05 New Frostbite, LLC +// movie : 2015-02-05 Binky Moon, LLC movie -// movistar : 2014-10-16 Telefónica S.A. -movistar - // msd : 2015-07-23 MSD Registry Holdings, Inc. msd // mtn : 2014-12-04 MTN Dubai Limited mtn -// mtpc : 2014-11-20 Mitsubishi Tanabe Pharma Corporation -mtpc - // mtr : 2015-03-12 MTR Corporation Limited mtr -// multichoice : 2015-03-12 MultiChoice (Proprietary) Limited -multichoice +// music : 2021-05-04 DotMusic Limited +music // mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC mutual -// mutuelle : 2015-06-18 Fédération Nationale de la Mutualité Française -mutuelle - -// mzansimagic : 2015-03-05 Electronic Media Network (Pty) Ltd -mzansimagic - // nab : 2015-08-20 National Australia Bank Limited nab -// nadex : 2014-12-11 IG Group Holdings PLC -nadex - // nagoya : 2013-10-24 GMO Registry, Inc. nagoya -// naspers : 2015-02-12 Intelprop (Proprietary) Limited -naspers - -// nationwide : 2015-07-23 Nationwide Mutual Insurance Company -nationwide - // natura : 2015-03-12 NATURA COSMÉTICOS S.A. natura -// navy : 2014-03-06 United TLD Holdco Ltd. +// navy : 2014-03-06 Dog Beach, LLC navy // nba : 2015-07-31 NBA REGISTRY, LLC @@ -9022,7 +9116,7 @@ netbank // netflix : 2015-06-18 Netflix, Inc. netflix -// network : 2013-11-14 Trixy Manor, LLC +// network : 2013-11-14 Binky Moon, LLC network // neustar : 2013-12-05 NeuStar, Inc. @@ -9031,10 +9125,7 @@ neustar // new : 2014-01-30 Charleston Road Registry Inc. new -// newholland : 2015-09-03 CNH Industrial N.V. -newholland - -// news : 2014-12-18 +// news : 2014-12-18 Dog Beach, LLC news // next : 2015-06-18 Next plc @@ -9064,7 +9155,7 @@ nike // nikon : 2015-05-21 NIKON CORPORATION nikon -// ninja : 2013-11-07 United TLD Holdco Ltd. +// ninja : 2013-11-07 Dog Beach, LLC ninja // nissan : 2014-03-27 NISSAN MOTOR CO., LTD. @@ -9079,10 +9170,10 @@ nokia // northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC northwesternmutual -// norton : 2014-12-04 Symantec Corporation +// norton : 2014-12-04 NortonLifeLock Inc. norton -// now : 2015-06-25 Amazon EU S.à r.l. +// now : 2015-06-25 Amazon Registry Services, Inc. now // nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. @@ -9106,16 +9197,13 @@ nyc // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA obi -// observer : 2015-04-30 Guardian News and Media Limited +// observer : 2015-04-30 Dog Beach, LLC observer -// off : 2015-07-23 Johnson Shareholdings, Inc. -off - // office : 2015-03-12 Microsoft Corporation office -// okinawa : 2013-12-05 BusinessRalliart Inc. +// okinawa : 2013-12-05 BRregistry, Inc. okinawa // olayan : 2015-05-14 Crescent Holding GmbH @@ -9139,16 +9227,13 @@ one // ong : 2014-03-06 Public Interest Registry ong -// onl : 2013-09-16 I-Registry Ltd. +// onl : 2013-09-16 iRegistry GmbH onl -// online : 2015-01-15 DotOnline Inc. +// online : 2015-01-15 Radix FZC online -// onyourside : 2015-07-23 Nationwide Mutual Insurance Company -onyourside - -// ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED +// ooo : 2014-01-09 INFIBEAM AVENUES LIMITED ooo // open : 2015-07-31 American Express Travel Related Services Company, Inc. @@ -9163,13 +9248,10 @@ orange // organic : 2014-03-27 Afilias Limited organic -// orientexpress : 2015-02-05 Belmond Ltd. -orientexpress - // origins : 2015-10-01 The Estée Lauder Companies Inc. origins -// osaka : 2014-09-04 Interlink Co., Ltd. +// osaka : 2014-09-04 Osaka Registry Co., Ltd. osaka // otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. @@ -9178,31 +9260,25 @@ otsuka // ott : 2015-06-04 Dish DBS Corporation ott -// ovh : 2014-01-16 OVH SAS +// ovh : 2014-01-16 MédiaBC ovh // page : 2014-12-04 Charleston Road Registry Inc. page -// pamperedchef : 2015-02-05 The Pampered Chef, Ltd. -pamperedchef - // panasonic : 2015-07-30 Panasonic Corporation panasonic -// panerai : 2014-11-07 Richemont DNS Inc. -panerai - // paris : 2014-01-30 City of Paris paris // pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. pars -// partners : 2013-12-05 Magic Glen, LLC +// partners : 2013-12-05 Binky Moon, LLC partners -// parts : 2013-12-05 Sea Goodbye, LLC +// parts : 2013-12-05 Binky Moon, LLC parts // party : 2014-09-11 Blue Sky Registry Limited @@ -9211,16 +9287,13 @@ party // passagens : 2015-03-05 Travel Reservations SRL passagens -// pay : 2015-08-27 Amazon EU S.à r.l. +// pay : 2015-08-27 Amazon Registry Services, Inc. pay -// payu : 2015-02-12 MIH PayU B.V. -payu - // pccw : 2015-05-14 PCCW Enterprises Limited pccw -// pet : 2015-05-07 Afilias plc +// pet : 2015-05-07 Afilias Limited pet // pfizer : 2015-09-11 Pfizer Inc. @@ -9229,37 +9302,40 @@ pfizer // pharmacy : 2014-06-19 National Association of Boards of Pharmacy pharmacy +// phd : 2016-07-28 Charleston Road Registry Inc. +phd + // philips : 2014-11-07 Koninklijke Philips N.V. philips -// photo : 2013-11-14 Uniregistry, Corp. +// phone : 2016-06-02 Dish DBS Corporation +phone + +// photo : 2013-11-14 UNR Corp. photo -// photography : 2013-09-20 Sugar Glen, LLC +// photography : 2013-09-20 Binky Moon, LLC photography -// photos : 2013-10-17 Sea Corner, LLC +// photos : 2013-10-17 Binky Moon, LLC photos // physio : 2014-05-01 PhysBiz Pty Ltd physio -// piaget : 2014-10-16 Richemont DNS Inc. -piaget - -// pics : 2013-11-14 Uniregistry, Corp. +// pics : 2013-11-14 UNR Corp. pics // pictet : 2014-06-26 Pictet Europe S.A. pictet -// pictures : 2014-03-06 Foggy Sky, LLC +// pictures : 2014-03-06 Binky Moon, LLC pictures // pid : 2015-01-08 Top Level Spectrum, Inc. pid -// pin : 2014-12-18 Amazon EU S.à r.l. +// pin : 2014-12-18 Amazon Registry Services, Inc. pin // ping : 2015-06-11 Ping Registry Provider, Inc. @@ -9271,22 +9347,22 @@ pink // pioneer : 2015-07-16 Pioneer Corporation pioneer -// pizza : 2014-06-26 Foggy Moon, LLC +// pizza : 2014-06-26 Binky Moon, LLC pizza -// place : 2014-04-24 Snow Galley, LLC +// place : 2014-04-24 Binky Moon, LLC place // play : 2015-03-05 Charleston Road Registry Inc. play -// playstation : 2015-07-02 Sony Computer Entertainment Inc. +// playstation : 2015-07-02 Sony Interactive Entertainment Inc. playstation -// plumbing : 2013-09-10 Spring Tigers, LLC +// plumbing : 2013-09-10 Binky Moon, LLC plumbing -// plus : 2015-02-05 Sugar Mill, LLC +// plus : 2015-02-05 Binky Moon, LLC plus // pnc : 2015-07-02 PNC Domain Co., LLC @@ -9295,7 +9371,7 @@ pnc // pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG pohl -// poker : 2014-07-03 Afilias Domains No. 5 Limited +// poker : 2014-07-03 Afilias Limited poker // politie : 2015-08-20 Politie Nederland @@ -9310,16 +9386,16 @@ pramerica // praxi : 2013-12-05 Praxi S.p.A. praxi -// press : 2014-04-03 DotPress Inc. +// press : 2014-04-03 Radix FZC press -// prime : 2015-06-25 Amazon EU S.à r.l. +// prime : 2015-06-25 Amazon Registry Services, Inc. prime // prod : 2014-01-23 Charleston Road Registry Inc. prod -// productions : 2013-12-05 Magic Birch, LLC +// productions : 2013-12-05 Binky Moon, LLC productions // prof : 2014-07-24 Charleston Road Registry Inc. @@ -9328,16 +9404,16 @@ prof // progressive : 2015-07-23 Progressive Casualty Insurance Company progressive -// promo : 2014-12-18 +// promo : 2014-12-18 Afilias Limited promo -// properties : 2013-12-05 Big Pass, LLC +// properties : 2013-12-05 Binky Moon, LLC properties -// property : 2014-05-22 Uniregistry, Corp. +// property : 2014-05-22 UNR Corp. property -// protection : 2015-04-23 +// protection : 2015-04-23 XYZ.COM LLC protection // pru : 2015-07-30 Prudential Financial, Inc. @@ -9346,7 +9422,7 @@ pru // prudential : 2015-07-30 Prudential Financial, Inc. prudential -// pub : 2013-12-12 United TLD Holdco Ltd. +// pub : 2013-12-12 Dog Beach, LLC pub // pwc : 2015-10-29 PricewaterhouseCoopers LLP @@ -9358,19 +9434,16 @@ qpon // quebec : 2013-12-19 PointQuébec Inc quebec -// quest : 2015-03-26 Quest ION Limited +// quest : 2015-03-26 XYZ.COM LLC quest -// qvc : 2015-07-30 QVC, Inc. -qvc - // racing : 2014-12-04 Premier Registry Limited racing -// raid : 2015-07-23 Johnson Shareholdings, Inc. -raid +// radio : 2016-07-21 European Broadcasting Union (EBU) +radio -// read : 2014-12-18 Amazon EU S.à r.l. +// read : 2014-12-18 Amazon Registry Services, Inc. read // realestate : 2015-09-11 dotRealEstate LLC @@ -9379,10 +9452,10 @@ realestate // realtor : 2014-05-29 Real Estate Domains LLC realtor -// realty : 2015-03-19 Fegistry, LLC +// realty : 2015-03-19 Dog Beach, LLC realty -// recipes : 2013-10-17 Grand Island, LLC +// recipes : 2013-10-17 Binky Moon, LLC recipes // red : 2013-11-07 Afilias Limited @@ -9394,13 +9467,13 @@ redstone // redumbrella : 2015-03-26 Travelers TLD, LLC redumbrella -// rehab : 2014-03-06 United TLD Holdco Ltd. +// rehab : 2014-03-06 Dog Beach, LLC rehab -// reise : 2014-03-13 +// reise : 2014-03-13 Binky Moon, LLC reise -// reisen : 2014-03-06 New Cypress, LLC +// reisen : 2014-03-06 Binky Moon, LLC reisen // reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. @@ -9409,40 +9482,40 @@ reit // reliance : 2015-04-02 Reliance Industries Limited reliance -// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. +// ren : 2013-12-12 ZDNS International Limited ren -// rent : 2014-12-04 DERRent, LLC +// rent : 2014-12-04 XYZ.COM LLC rent -// rentals : 2013-12-05 Big Hollow,LLC +// rentals : 2013-12-05 Binky Moon, LLC rentals -// repair : 2013-11-07 Lone Sunset, LLC +// repair : 2013-11-07 Binky Moon, LLC repair -// report : 2013-12-05 Binky Glen, LLC +// report : 2013-12-05 Binky Moon, LLC report -// republican : 2014-03-20 United TLD Holdco Ltd. +// republican : 2014-03-20 Dog Beach, LLC republican // rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable rest -// restaurant : 2014-07-03 Snow Avenue, LLC +// restaurant : 2014-07-03 Binky Moon, LLC restaurant // review : 2014-11-20 dot Review Limited review -// reviews : 2013-09-13 +// reviews : 2013-09-13 Dog Beach, LLC reviews // rexroth : 2015-06-18 Robert Bosch GMBH rexroth -// rich : 2013-11-21 I-Registry Ltd. +// rich : 2013-11-21 iRegistry GmbH rich // richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited @@ -9451,55 +9524,52 @@ richardli // ricoh : 2014-11-20 Ricoh Company, Ltd. ricoh -// rightathome : 2015-07-23 Johnson Shareholdings, Inc. -rightathome - // ril : 2015-04-02 Reliance Industries Limited ril // rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO rio -// rip : 2014-07-10 United TLD Holdco Ltd. +// rip : 2014-07-10 Dog Beach, LLC rip -// rmit : 2015-11-19 Royal Melbourne Institute of Technology -rmit - // rocher : 2014-12-18 Ferrero Trading Lux S.A. rocher -// rocks : 2013-11-14 +// rocks : 2013-11-14 Dog Beach, LLC rocks -// rodeo : 2013-12-19 Top Level Domain Holdings Limited +// rodeo : 2013-12-19 Registry Services, LLC rodeo -// rogers : 2015-08-06 Rogers Communications Partnership +// rogers : 2015-08-06 Rogers Communications Canada Inc. rogers -// room : 2014-12-18 Amazon EU S.à r.l. +// room : 2014-12-18 Amazon Registry Services, Inc. room // rsvp : 2014-05-08 Charleston Road Registry Inc. rsvp +// rugby : 2016-12-15 World Rugby Strategic Developments Limited +rugby + // ruhr : 2013-10-02 regiodot GmbH & Co. KG ruhr -// run : 2015-03-19 Snow Park, LLC +// run : 2015-03-19 Binky Moon, LLC run // rwe : 2015-04-02 RWE AG rwe -// ryukyu : 2014-01-09 BusinessRalliart Inc. +// ryukyu : 2014-01-09 BRregistry, Inc. ryukyu // saarland : 2013-12-12 dotSaarland GmbH saarland -// safe : 2014-12-18 Amazon EU S.à r.l. +// safe : 2014-12-18 Amazon Registry Services, Inc. safe // safety : 2015-01-08 Safety Registry Services, LLC. @@ -9508,10 +9578,10 @@ safety // sakura : 2014-12-18 SAKURA Internet Inc. sakura -// sale : 2014-10-16 +// sale : 2014-10-16 Dog Beach, LLC sale -// salon : 2014-12-11 Outer Orchard, LLC +// salon : 2014-12-11 Binky Moon, LLC salon // samsclub : 2015-07-31 Wal-Mart Stores, Inc. @@ -9532,16 +9602,13 @@ sanofi // sap : 2014-03-27 SAP AG sap -// sapo : 2014-11-07 PT Comunicacoes S.A. -sapo - -// sarl : 2014-07-03 Delta Orchard, LLC +// sarl : 2014-07-03 Binky Moon, LLC sarl // sas : 2015-04-02 Research IP LLC sas -// save : 2015-06-25 Amazon EU S.à r.l. +// save : 2015-06-25 Amazon Registry Services, Inc. save // saxo : 2014-10-31 Saxo Bank A/S @@ -9550,7 +9617,7 @@ saxo // sbi : 2015-03-12 STATE BANK OF INDIA sbi -// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +// sbs : 2014-11-07 ShortDot SA sbs // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) @@ -9562,16 +9629,16 @@ scb // schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG schaeffler -// schmidt : 2014-04-03 SALM S.A.S. +// schmidt : 2014-04-03 SCHMIDT GROUPE S.A.S. schmidt // scholarships : 2014-04-24 Scholarships.com, LLC scholarships -// school : 2014-12-18 Little Galley, LLC +// school : 2014-12-18 Binky Moon, LLC school -// schule : 2014-03-06 Outer Moon, LLC +// schule : 2014-03-06 Binky Moon, LLC schule // schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG @@ -9580,34 +9647,31 @@ schwarz // science : 2014-09-11 dot Science Limited science -// scjohnson : 2015-07-23 Johnson Shareholdings, Inc. -scjohnson - -// scor : 2014-10-31 SCOR SE -scor - // scot : 2014-01-23 Dot Scot Registry Limited scot +// search : 2016-06-09 Charleston Road Registry Inc. +search + // seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) seat -// secure : 2015-08-27 Amazon EU S.à r.l. +// secure : 2015-08-27 Amazon Registry Services, Inc. secure -// security : 2015-05-14 +// security : 2015-05-14 XYZ.COM LLC security // seek : 2014-12-04 Seek Limited seek -// select : 2015-10-08 iSelect Ltd +// select : 2015-10-08 Registry Services, LLC select // sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. sener -// services : 2014-02-27 Fox Castle, LLC +// services : 2014-02-27 Binky Moon, LLC services // ses : 2015-07-23 SES @@ -9622,7 +9686,7 @@ sew // sex : 2014-11-13 ICM Registry SX LLC sex -// sexy : 2013-09-11 Uniregistry, Corp. +// sexy : 2013-09-11 UNR Corp. sexy // sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR @@ -9646,79 +9710,82 @@ shia // shiksha : 2013-11-14 Afilias Limited shiksha -// shoes : 2013-10-02 Binky Galley, LLC +// shoes : 2013-10-02 Binky Moon, LLC shoes -// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// shop : 2016-04-08 GMO Registry, Inc. +shop + +// shopping : 2016-03-31 Binky Moon, LLC +shopping + +// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd. shouji -// show : 2015-03-05 Snow Beach, LLC +// show : 2015-03-05 Binky Moon, LLC show // showtime : 2015-08-06 CBS Domains Inc. showtime -// shriram : 2014-01-23 Shriram Capital Ltd. -shriram - -// silk : 2015-06-25 Amazon EU S.à r.l. +// silk : 2015-06-25 Amazon Registry Services, Inc. silk // sina : 2015-03-12 Sina Corporation sina -// singles : 2013-08-27 Fern Madison, LLC +// singles : 2013-08-27 Binky Moon, LLC singles -// site : 2015-01-15 DotSite Inc. +// site : 2015-01-15 Radix FZC site -// ski : 2015-04-09 STARTING DOT LIMITED +// ski : 2015-04-09 Afilias Limited ski -// skin : 2015-01-15 L'Oréal +// skin : 2015-01-15 XYZ.COM LLC skin -// sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch +// sky : 2014-06-19 Sky International AG sky // skype : 2014-12-18 Microsoft Corporation skype -// sling : 2015-07-30 Hughes Satellite Systems Corporation +// sling : 2015-07-30 DISH Technologies L.L.C. sling // smart : 2015-07-09 Smart Communications, Inc. (SMART) smart -// smile : 2014-12-18 Amazon EU S.à r.l. +// smile : 2014-12-18 Amazon Registry Services, Inc. smile // sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F sncf -// soccer : 2015-03-26 Foggy Shadow, LLC +// soccer : 2015-03-26 Binky Moon, LLC soccer -// social : 2013-11-07 United TLD Holdco Ltd. +// social : 2013-11-07 Dog Beach, LLC social -// softbank : 2015-07-02 SoftBank Corp. +// softbank : 2015-07-02 SoftBank Group Corp. softbank -// software : 2014-03-20 +// software : 2014-03-20 Dog Beach, LLC software // sohu : 2013-12-19 Sohu.com Limited sohu -// solar : 2013-11-07 Ruby Town, LLC +// solar : 2013-11-07 Binky Moon, LLC solar -// solutions : 2013-11-07 Silver Cover, LLC +// solutions : 2013-11-07 Binky Moon, LLC solutions -// song : 2015-02-26 Amazon EU S.à r.l. +// song : 2015-02-26 Amazon Registry Services, Inc. song // sony : 2015-01-08 Sony Corporation @@ -9727,24 +9794,21 @@ sony // soy : 2014-01-23 Charleston Road Registry Inc. soy -// space : 2014-04-03 DotSpace Inc. +// spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited +spa + +// space : 2014-04-03 Radix FZC space -// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG -spiegel +// sport : 2017-11-16 Global Association of International Sports Federations (GAISF) +sport -// spot : 2015-02-26 Amazon EU S.à r.l. +// spot : 2015-02-26 Amazon Registry Services, Inc. spot -// spreadbetting : 2014-12-11 IG Group Holdings PLC -spreadbetting - -// srl : 2015-05-07 mySRL GmbH +// srl : 2015-05-07 InterNetX, Corp srl -// srt : 2015-07-30 FCA US LLC. -srt - // stada : 2014-11-13 STADA Arzneimittel AG stada @@ -9754,18 +9818,12 @@ staples // star : 2015-01-08 Star India Private Limited star -// starhub : 2015-02-05 StarHub Ltd -starhub - // statebank : 2015-03-12 STATE BANK OF INDIA statebank // statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company statefarm -// statoil : 2014-12-04 Statoil ASA -statoil - // stc : 2014-10-09 Saudi Telecom Company stc @@ -9775,13 +9833,16 @@ stcgroup // stockholm : 2014-12-18 Stockholms kommun stockholm -// storage : 2014-12-22 Self Storage Company LLC +// storage : 2014-12-22 XYZ.COM LLC storage -// store : 2015-04-09 DotStore Inc. +// store : 2015-04-09 Radix FZC store -// studio : 2015-02-11 +// stream : 2016-01-08 dot Stream Limited +stream + +// studio : 2015-02-11 Dog Beach, LLC studio // study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD @@ -9790,25 +9851,22 @@ study // style : 2014-12-04 Binky Moon, LLC style -// sucks : 2014-12-22 Vox Populi Registry Inc. +// sucks : 2014-12-22 Vox Populi Registry Ltd. sucks -// supersport : 2015-03-05 SuperSport International Holdings Proprietary Limited -supersport - -// supplies : 2013-12-19 Atomic Fields, LLC +// supplies : 2013-12-19 Binky Moon, LLC supplies -// supply : 2013-12-19 Half Falls, LLC +// supply : 2013-12-19 Binky Moon, LLC supply -// support : 2013-10-24 Grand Orchard, LLC +// support : 2013-10-24 Binky Moon, LLC support -// surf : 2014-01-09 Top Level Domain Holdings Limited +// surf : 2014-01-09 Registry Services, LLC surf -// surgery : 2014-03-20 Tin Avenue, LLC +// surgery : 2014-03-20 Binky Moon, LLC surgery // suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION @@ -9817,19 +9875,13 @@ suzuki // swatch : 2015-01-08 The Swatch Group Ltd swatch -// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited -swiftcover - // swiss : 2014-10-16 Swiss Confederation swiss // sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet sydney -// symantec : 2014-12-04 Symantec Corporation -symantec - -// systems : 2013-11-07 Dash Cypress, LLC +// systems : 2013-11-07 Binky Moon, LLC systems // tab : 2014-12-04 Tabcorp Holdings Limited @@ -9838,7 +9890,7 @@ tab // taipei : 2014-07-10 Taipei City Government taipei -// talk : 2015-04-09 Amazon EU S.à r.l. +// talk : 2015-04-09 Amazon Registry Services, Inc. talk // taobao : 2015-01-15 Alibaba Group Holding Limited @@ -9853,13 +9905,13 @@ tatamotors // tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" tatar -// tattoo : 2013-08-30 Uniregistry, Corp. +// tattoo : 2013-08-30 UNR Corp. tattoo -// tax : 2014-03-20 Storm Orchard, LLC +// tax : 2014-03-20 Binky Moon, LLC tax -// taxi : 2015-03-19 Pine Falls, LLC +// taxi : 2015-03-19 Binky Moon, LLC taxi // tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. @@ -9868,58 +9920,49 @@ tci // tdk : 2015-06-11 TDK Corporation tdk -// team : 2015-03-05 Atomic Lake, LLC +// team : 2015-03-05 Binky Moon, LLC team -// tech : 2015-01-30 Dot Tech LLC +// tech : 2015-01-30 Radix FZC tech -// technology : 2013-09-13 Auburn Falls +// technology : 2013-09-13 Binky Moon, LLC technology -// telecity : 2015-02-19 TelecityGroup International Limited -telecity - -// telefonica : 2014-10-16 Telefónica S.A. -telefonica - // temasek : 2014-08-07 Temasek Holdings (Private) Limited temasek -// tennis : 2014-12-04 Cotton Bloom, LLC +// tennis : 2014-12-04 Binky Moon, LLC tennis // teva : 2015-07-02 Teva Pharmaceutical Industries Limited teva -// thd : 2015-04-02 Homer TLC, Inc. +// thd : 2015-04-02 Home Depot Product Authority, LLC thd -// theater : 2015-03-19 Blue Tigers, LLC +// theater : 2015-03-19 Binky Moon, LLC theater -// theatre : 2015-05-07 +// theatre : 2015-05-07 XYZ.COM LLC theatre -// theguardian : 2015-04-30 Guardian News and Media Limited -theguardian - // tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America tiaa -// tickets : 2015-02-05 Accent Media Limited +// tickets : 2015-02-05 XYZ.COM LLC tickets -// tienda : 2013-11-14 Victor Manor, LLC +// tienda : 2013-11-14 Binky Moon, LLC tienda // tiffany : 2015-01-30 Tiffany and Company tiffany -// tips : 2013-09-20 Corn Willow, LLC +// tips : 2013-09-20 Binky Moon, LLC tips -// tires : 2014-11-07 Dog Edge, LLC +// tires : 2014-11-07 Binky Moon, LLC tires // tirol : 2014-04-24 punkt Tirol GmbH @@ -9937,16 +9980,16 @@ tkmaxx // tmall : 2015-01-15 Alibaba Group Holding Limited tmall -// today : 2013-09-20 Pearl Woods, LLC +// today : 2013-09-20 Binky Moon, LLC today // tokyo : 2013-11-13 GMO Registry, Inc. tokyo -// tools : 2013-11-21 Pioneer North, LLC +// tools : 2013-11-21 Binky Moon, LLC tools -// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. +// top : 2014-03-20 .TOP Registry top // toray : 2014-12-18 Toray Industries, Inc. @@ -9958,27 +10001,30 @@ toshiba // total : 2015-08-06 Total SA total -// tours : 2015-01-22 Sugar Station, LLC +// tours : 2015-01-22 Binky Moon, LLC tours -// town : 2014-03-06 Koko Moon, LLC +// town : 2014-03-06 Binky Moon, LLC town // toyota : 2015-04-23 TOYOTA MOTOR CORPORATION toyota -// toys : 2014-03-06 Pioneer Orchard, LLC +// toys : 2014-03-06 Binky Moon, LLC toys // trade : 2014-01-23 Elite Registry Limited trade -// trading : 2014-12-11 IG Group Holdings PLC +// trading : 2014-12-11 Dog Beach, LLC trading -// training : 2013-11-07 Wild Willow, LLC +// training : 2013-11-07 Binky Moon, LLC training +// travel : 2015-10-09 Dog Beach, LLC +travel + // travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. travelchannel @@ -9988,7 +10034,7 @@ travelers // travelersinsurance : 2015-03-26 Travelers TLD, LLC travelersinsurance -// trust : 2014-10-16 +// trust : 2014-10-16 UNR Corp. trust // trv : 2015-03-26 Travelers TLD, LLC @@ -10000,10 +10046,10 @@ tube // tui : 2014-07-03 TUI AG tui -// tunes : 2015-02-26 Amazon EU S.à r.l. +// tunes : 2015-02-26 Amazon Registry Services, Inc. tunes -// tushu : 2014-12-18 Amazon EU S.à r.l. +// tushu : 2014-12-18 Amazon Registry Services, Inc. tushu // tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED @@ -10015,16 +10061,13 @@ ubank // ubs : 2014-12-11 UBS AG ubs -// uconnect : 2015-07-30 FCA US LLC. -uconnect - // unicom : 2015-10-15 China United Network Communications Corporation Limited unicom -// university : 2014-03-06 Little Station, LLC +// university : 2014-03-06 Binky Moon, LLC university -// uno : 2013-09-11 Dot Latin LLC +// uno : 2013-09-11 Radix FZC uno // uol : 2014-05-01 UBN INTERNET LTDA. @@ -10033,7 +10076,7 @@ uol // ups : 2015-06-25 UPS Market Driver, Inc. ups -// vacations : 2013-12-05 Atomic Tigers, LLC +// vacations : 2013-12-05 Binky Moon, LLC vacations // vana : 2014-12-11 Lifestyle Domain Holdings, Inc. @@ -10045,22 +10088,22 @@ vanguard // vegas : 2014-01-16 Dot Vegas, Inc. vegas -// ventures : 2013-08-27 Binky Lake, LLC +// ventures : 2013-08-27 Binky Moon, LLC ventures // verisign : 2015-08-13 VeriSign, Inc. verisign -// versicherung : 2014-03-20 dotversicherung-registry GmbH +// versicherung : 2014-03-20 tldbox GmbH versicherung -// vet : 2014-03-06 +// vet : 2014-03-06 Dog Beach, LLC vet -// viajes : 2013-10-17 Black Madison, LLC +// viajes : 2013-10-17 Binky Moon, LLC viajes -// video : 2014-10-16 +// video : 2014-10-16 Dog Beach, LLC video // vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe @@ -10069,13 +10112,13 @@ vig // viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd. viking -// villas : 2013-12-05 New Sky, LLC +// villas : 2013-12-05 Binky Moon, LLC villas -// vin : 2015-06-18 Holly Shadow, LLC +// vin : 2015-06-18 Binky Moon, LLC vin -// vip : 2015-01-22 Minds + Machines Group Limited +// vip : 2015-01-22 Registry Services, LLC vip // virgin : 2014-09-25 Virgin Enterprises Limited @@ -10084,15 +10127,9 @@ virgin // visa : 2015-07-30 Visa Worldwide Pte. Limited visa -// vision : 2013-12-05 Koko Station, LLC +// vision : 2013-12-05 Binky Moon, LLC vision -// vista : 2014-09-18 Vistaprint Limited -vista - -// vistaprint : 2014-09-18 Vistaprint Limited -vistaprint - // viva : 2014-11-07 Saudi Telecom Company viva @@ -10102,7 +10139,7 @@ vivo // vlaanderen : 2014-02-06 DNS.be vzw vlaanderen -// vodka : 2013-12-19 Top Level Domain Holdings Limited +// vodka : 2013-12-19 Registry Services, LLC vodka // volkswagen : 2015-05-14 Volkswagen Group of America Inc. @@ -10120,7 +10157,7 @@ voting // voto : 2013-11-21 Monolith Registry LLC voto -// voyage : 2013-08-27 Ruby House, LLC +// voyage : 2013-08-27 Binky Moon, LLC voyage // vuelos : 2015-03-05 Travel Reservations SRL @@ -10135,25 +10172,22 @@ walmart // walter : 2014-11-13 Sandvik AB walter -// wang : 2013-10-24 Zodiac Leo Limited +// wang : 2013-10-24 Zodiac Wang Limited wang -// wanggou : 2014-12-18 Amazon EU S.à r.l. +// wanggou : 2014-12-18 Amazon Registry Services, Inc. wanggou -// warman : 2015-06-18 Weir Group IP Limited -warman - -// watch : 2013-11-14 Sand Shadow, LLC +// watch : 2013-11-14 Binky Moon, LLC watch -// watches : 2014-12-22 Richemont DNS Inc. +// watches : 2014-12-22 Afilias Limited watches -// weather : 2015-01-08 The Weather Channel, LLC +// weather : 2015-01-08 International Business Machines Corporation weather -// weatherchannel : 2015-03-12 The Weather Channel, LLC +// weatherchannel : 2015-03-12 International Business Machines Corporation weatherchannel // webcam : 2014-01-23 dot Webcam Limited @@ -10162,13 +10196,10 @@ webcam // weber : 2015-06-04 Saint-Gobain Weber SA weber -// website : 2014-04-03 DotWebsite Inc. +// website : 2014-04-03 Radix FZC website -// wed : 2013-10-01 Atgron, Inc. -wed - -// wedding : 2014-04-24 Top Level Domain Holdings Limited +// wedding : 2014-04-24 Registry Services, LLC wedding // weibo : 2015-03-05 Sina Corporation @@ -10195,7 +10226,7 @@ win // windows : 2014-12-18 Microsoft Corporation windows -// wine : 2015-06-18 June Station, LLC +// wine : 2015-06-18 Binky Moon, LLC wine // winners : 2015-07-16 The TJX Companies, Inc. @@ -10210,22 +10241,22 @@ wolterskluwer // woodside : 2015-07-09 Woodside Petroleum Limited woodside -// work : 2013-12-19 Top Level Domain Holdings Limited +// work : 2013-12-19 Registry Services, LLC work -// works : 2013-11-14 Little Dynamite, LLC +// works : 2013-11-14 Binky Moon, LLC works -// world : 2014-06-12 Bitter Fields, LLC +// world : 2014-06-12 Binky Moon, LLC world -// wow : 2015-10-08 Amazon EU S.à r.l. +// wow : 2015-10-08 Amazon Registry Services, Inc. wow // wtc : 2013-12-19 World Trade Centers Association, Inc. wtc -// wtf : 2014-03-06 Hidden Way, LLC +// wtf : 2014-03-06 Binky Moon, LLC wtf // xbox : 2014-12-18 Microsoft Corporation @@ -10237,7 +10268,7 @@ xerox // xfinity : 2015-07-09 Comcast IP Holdings I, LLC xfinity -// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd. xihuan // xin : 2014-12-11 Elegant Leader Limited @@ -10246,7 +10277,7 @@ xin // xn--11b4c3d : 2015-01-15 VeriSign Sarl कॉम -// xn--1ck2e1b : 2015-02-26 Amazon EU S.à r.l. +// xn--1ck2e1b : 2015-02-26 Amazon Registry Services, Inc. セール // xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. @@ -10258,31 +10289,25 @@ xin // xn--3bst00m : 2013-09-13 Eagle Horizon Limited 集团 -// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED +// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY 在线 -// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. -大众汽车 - // xn--3pxu8k : 2015-01-15 VeriSign Sarl 点看 // xn--42c2d9a : 2015-01-15 VeriSign Sarl คอม -// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited +// xn--45q11c : 2013-11-21 Zodiac Gemini Ltd 八卦 -// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment +// xn--4gbrim : 2013-10-04 Helium TLDs Ltd موقع -// xn--4gq48lf9j : 2015-07-31 Wal-Mart Stores, Inc. -一号店 - // xn--55qw42g : 2013-11-08 China Organizational Name Administration Center 公益 -// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +// xn--55qx5d : 2013-11-14 China Internet Network Information Center (CNNIC) 公司 // xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited @@ -10324,7 +10349,7 @@ xin // xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited 淡马锡 -// xn--bck1b9a5dre4c : 2015-02-26 Amazon EU S.à r.l. +// xn--bck1b9a5dre4c : 2015-02-26 Amazon Registry Services, Inc. ファッション // xn--c1avg : 2013-11-14 Public Interest Registry @@ -10333,46 +10358,46 @@ xin // xn--c2br7g : 2015-01-15 VeriSign Sarl नेट -// xn--cck2b3b : 2015-02-26 Amazon EU S.à r.l. +// xn--cck2b3b : 2015-02-26 Amazon Registry Services, Inc. ストア +// xn--cckwcxetd : 2019-12-19 Amazon Registry Services, Inc. +アマゾン + // xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD 삼성 -// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED +// xn--czr694b : 2014-01-16 Internet DotTrademark Organisation Limited 商标 -// xn--czrs0t : 2013-12-19 Wild Island, LLC +// xn--czrs0t : 2013-12-19 Binky Moon, LLC 商店 -// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited +// xn--czru2d : 2013-11-21 Zodiac Aquarius Limited 商城 // xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” дети -// xn--eckvdtc9d : 2014-12-18 Amazon EU S.à r.l. +// xn--eckvdtc9d : 2014-12-18 Amazon Registry Services, Inc. ポイント -// xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 +// xn--efvy88h : 2014-08-22 Guangzhou YU Wei Information Technology Co., Ltd. 新闻 -// xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited -工行 - -// xn--fct429k : 2015-04-09 Amazon EU S.à r.l. +// xn--fct429k : 2015-04-09 Amazon Registry Services, Inc. 家電 // xn--fhbei : 2015-01-15 VeriSign Sarl كوم -// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED +// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED OY 中文网 // xn--fiq64b : 2013-10-14 CITIC Group Corporation 中信 -// xn--fjq720a : 2014-05-22 Will Bloom, LLC +// xn--fjq720a : 2014-05-22 Binky Moon, LLC 娱乐 // xn--flw351e : 2014-07-31 Charleston Road Registry Inc. @@ -10381,42 +10406,42 @@ xin // xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited 電訊盈科 -// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD. 购物 -// xn--gckr3f0f : 2015-02-26 Amazon EU S.à r.l. +// xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc. クラウド -// xn--gk3at1e : 2015-10-08 Amazon EU S.à r.l. +// xn--gk3at1e : 2015-10-08 Amazon Registry Services, Inc. 通販 -// xn--hxt814e : 2014-05-15 Zodiac Libra Limited +// xn--hxt814e : 2014-05-15 Zodiac Taurus Limited 网店 // xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry संगठन -// xn--imr513n : 2014-12-11 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED +// xn--imr513n : 2014-12-11 Internet DotTrademark Organisation Limited 餐厅 -// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +// xn--io0a7i : 2013-11-14 China Internet Network Information Center (CNNIC) 网络 // xn--j1aef : 2015-01-15 VeriSign Sarl ком +// xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc. +亚马逊 + // xn--jlq61u9w7b : 2015-01-08 Nokia Corporation 诺基亚 -// xn--jvr189m : 2015-02-26 Amazon EU S.à r.l. +// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc. 食品 // xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. 飞利浦 -// xn--kpu716f : 2014-12-22 Richemont DNS Inc. -手表 - // xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd 手机 @@ -10432,9 +10457,6 @@ xin // xn--mgbab2bd : 2013-10-31 CORE Association بازار -// xn--mgbb9fbpob : 2014-12-18 GreenTech Consultancy Company W.L.L. -موبايلي - // xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre ابوظبي @@ -10468,12 +10490,12 @@ xin // xn--nyqy26a : 2014-11-07 Stable Tone Limited 健康 +// xn--otu796d : 2017-08-06 Jiang Yu Liang Cai Technology Company Limited +招聘 + // xn--p1acf : 2013-12-12 Rusnames Limited рус -// xn--pbt977c : 2014-12-22 Richemont DNS Inc. -珠宝 - // xn--pssy2u : 2015-01-15 VeriSign Sarl 大拿 @@ -10486,10 +10508,10 @@ xin // xn--rhqv96g : 2013-09-11 Stable Tone Limited 世界 -// xn--rovu88b : 2015-02-26 Amazon EU S.à r.l. +// xn--rovu88b : 2015-02-26 Amazon Registry Services, Inc. 書籍 -// xn--ses554g : 2014-01-16 +// xn--ses554g : 2014-01-16 KNET Co., Ltd. 网址 // xn--t60b56a : 2015-01-15 VeriSign Sarl @@ -10501,7 +10523,7 @@ xin // xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) 天主教 -// xn--unup4y : 2013-07-14 Spring Fields, LLC +// xn--unup4y : 2013-07-14 Binky Moon, LLC 游戏 // xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG @@ -10510,7 +10532,7 @@ vermögensberater // xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG vermögensberatung -// xn--vhquv : 2013-08-27 Dash McCook, LLC +// xn--vhquv : 2013-08-27 Binky Moon, LLC 企业 // xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. @@ -10528,58 +10550,52 @@ vermögensberatung // xn--zfr164b : 2013-11-08 China Organizational Name Administration Center 政务 -// xperia : 2015-05-14 Sony Mobile Communications AB -xperia - // xyz : 2013-12-05 XYZ.COM LLC xyz -// yachts : 2014-01-09 DERYachts, LLC +// yachts : 2014-01-09 XYZ.COM LLC yachts -// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +// yahoo : 2015-04-02 Oath Inc. yahoo -// yamaxun : 2014-12-18 Amazon EU S.à r.l. +// yamaxun : 2014-12-18 Amazon Registry Services, Inc. yamaxun -// yandex : 2014-04-10 YANDEX, LLC +// yandex : 2014-04-10 Yandex Europe B.V. yandex // yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. yodobashi -// yoga : 2014-05-29 Top Level Domain Holdings Limited +// yoga : 2014-05-29 Registry Services, LLC yoga // yokohama : 2013-12-12 GMO Registry, Inc. yokohama -// you : 2015-04-09 Amazon EU S.à r.l. +// you : 2015-04-09 Amazon Registry Services, Inc. you // youtube : 2014-05-01 Charleston Road Registry Inc. youtube -// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd. yun -// zappos : 2015-06-25 Amazon EU S.à r.l. +// zappos : 2015-06-25 Amazon Registry Services, Inc. zappos // zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.) zara -// zero : 2014-12-18 Amazon EU S.à r.l. +// zero : 2014-12-18 Amazon Registry Services, Inc. zero // zip : 2014-05-08 Charleston Road Registry Inc. zip -// zippo : 2015-07-02 Zadco Company -zippo - -// zone : 2013-11-14 Outer Falls, LLC +// zone : 2013-11-14 Binky Moon, LLC zone // zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich) @@ -10590,90 +10606,372 @@ zuerich // ===BEGIN PRIVATE DOMAINS=== // (Note: these are in alphabetical order by company name) +// 1GB LLC : https://www.1gb.ua/ +// Submitted by 1GB LLC +cc.ua +inf.ua +ltd.ua + +// 611coin : https://611project.org/ +611.to + +// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za +// Submitted by Aaron Marais +graphox.us + +// accesso Technology Group, plc. : https://accesso.com/ +// Submitted by accesso Team +*.devcdnaccesso.com + +// Adobe : https://www.adobe.com/ +// Submitted by Ian Boston and Lars Trieloff +adobeaemcloud.com +*.dev.adobeaemcloud.com +hlx.live +adobeaemcloud.net +hlx.page +hlx3.page + +// Agnat sp. z o.o. : https://domena.pl +// Submitted by Przemyslaw Plewa +beep.pl + +// alboto.ca : http://alboto.ca +// Submitted by Anton Avramov +barsy.ca + +// Alces Software Ltd : http://alces-software.com +// Submitted by Mark J. Titorenko +*.compute.estate +*.alces.network + +// all-inkl.com : https://all-inkl.com +// Submitted by Werner Kaltofen +kasserver.com + +// Altervista: https://www.altervista.org +// Submitted by Carlo Cannas +altervista.org + +// alwaysdata : https://www.alwaysdata.com +// Submitted by Cyril +alwaysdata.net + // Amazon CloudFront : https://aws.amazon.com/cloudfront/ // Submitted by Donavan Miller cloudfront.net -// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ -// Submitted by Osman Surkatty -ap-northeast-1.compute.amazonaws.com -ap-southeast-1.compute.amazonaws.com -ap-southeast-2.compute.amazonaws.com -cn-north-1.compute.amazonaws.cn -compute.amazonaws.cn -compute.amazonaws.com -compute-1.amazonaws.com -eu-west-1.compute.amazonaws.com -eu-central-1.compute.amazonaws.com -sa-east-1.compute.amazonaws.com +// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/ +// Submitted by Luke Wells +*.compute.amazonaws.com +*.compute-1.amazonaws.com +*.compute.amazonaws.com.cn us-east-1.amazonaws.com -us-gov-west-1.compute.amazonaws.com -us-west-1.compute.amazonaws.com -us-west-2.compute.amazonaws.com -z-1.compute-1.amazonaws.com -z-2.compute-1.amazonaws.com // Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ -// Submitted by Adam Stein +// Submitted by Luke Wells +cn-north-1.eb.amazonaws.com.cn +cn-northwest-1.eb.amazonaws.com.cn elasticbeanstalk.com +ap-northeast-1.elasticbeanstalk.com +ap-northeast-2.elasticbeanstalk.com +ap-northeast-3.elasticbeanstalk.com +ap-south-1.elasticbeanstalk.com +ap-southeast-1.elasticbeanstalk.com +ap-southeast-2.elasticbeanstalk.com +ca-central-1.elasticbeanstalk.com +eu-central-1.elasticbeanstalk.com +eu-west-1.elasticbeanstalk.com +eu-west-2.elasticbeanstalk.com +eu-west-3.elasticbeanstalk.com +sa-east-1.elasticbeanstalk.com +us-east-1.elasticbeanstalk.com +us-east-2.elasticbeanstalk.com +us-gov-west-1.elasticbeanstalk.com +us-west-1.elasticbeanstalk.com +us-west-2.elasticbeanstalk.com // Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ -// Submitted by Scott Vidmar -elb.amazonaws.com +// Submitted by Luke Wells +*.elb.amazonaws.com +*.elb.amazonaws.com.cn + +// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/ +// Submitted by Daniel Massaguer +awsglobalaccelerator.com // Amazon S3 : https://aws.amazon.com/s3/ -// Submitted by Eric Kinolik +// Submitted by Luke Wells s3.amazonaws.com s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-south-1.amazonaws.com s3-ap-southeast-1.amazonaws.com s3-ap-southeast-2.amazonaws.com -s3-external-1.amazonaws.com -s3-external-2.amazonaws.com -s3-fips-us-gov-west-1.amazonaws.com +s3-ca-central-1.amazonaws.com s3-eu-central-1.amazonaws.com s3-eu-west-1.amazonaws.com +s3-eu-west-2.amazonaws.com +s3-eu-west-3.amazonaws.com +s3-external-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com s3-sa-east-1.amazonaws.com s3-us-gov-west-1.amazonaws.com +s3-us-east-2.amazonaws.com s3-us-west-1.amazonaws.com s3-us-west-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3.ap-south-1.amazonaws.com s3.cn-north-1.amazonaws.com.cn +s3.ca-central-1.amazonaws.com s3.eu-central-1.amazonaws.com +s3.eu-west-2.amazonaws.com +s3.eu-west-3.amazonaws.com +s3.us-east-2.amazonaws.com +s3.dualstack.ap-northeast-1.amazonaws.com +s3.dualstack.ap-northeast-2.amazonaws.com +s3.dualstack.ap-south-1.amazonaws.com +s3.dualstack.ap-southeast-1.amazonaws.com +s3.dualstack.ap-southeast-2.amazonaws.com +s3.dualstack.ca-central-1.amazonaws.com +s3.dualstack.eu-central-1.amazonaws.com +s3.dualstack.eu-west-1.amazonaws.com +s3.dualstack.eu-west-2.amazonaws.com +s3.dualstack.eu-west-3.amazonaws.com +s3.dualstack.sa-east-1.amazonaws.com +s3.dualstack.us-east-1.amazonaws.com +s3.dualstack.us-east-2.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website.ap-northeast-2.amazonaws.com +s3-website.ap-south-1.amazonaws.com +s3-website.ca-central-1.amazonaws.com +s3-website.eu-central-1.amazonaws.com +s3-website.eu-west-2.amazonaws.com +s3-website.eu-west-3.amazonaws.com +s3-website.us-east-2.amazonaws.com + +// Amune : https://amune.org/ +// Submitted by Team Amune +t3l3p0rt.net +tele.amune.org + +// Apigee : https://apigee.com/ +// Submitted by Apigee Security Team +apigee.io + +// Apphud : https://apphud.com +// Submitted by Alexander Selivanov +siiites.com + +// Appspace : https://www.appspace.com +// Submitted by Appspace Security Team +appspacehosted.com +appspaceusercontent.com + +// Appudo UG (haftungsbeschränkt) : https://www.appudo.com +// Submitted by Alexander Hochbaum +appudo.net + +// Aptible : https://www.aptible.com/ +// Submitted by Thomas Orozco +on-aptible.com + +// ASEINet : https://www.aseinet.com/ +// Submitted by Asei SEKIGUCHI +user.aseinet.ne.jp +gv.vc +d.gv.vc + +// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/ +// Submitted by Hector Martin +user.party.eus + +// Association potager.org : https://potager.org/ +// Submitted by Lunar +pimienta.org +poivron.org +potager.org +sweetpepper.org + +// ASUSTOR Inc. : http://www.asustor.com +// Submitted by Vincent Tseng +myasustor.com + +// Atlassian : https://atlassian.com +// Submitted by Sam Smyth +cdn.prod.atlassian-dev.net + +// AVM : https://avm.de +// Submitted by Andreas Weise +myfritz.net + +// AVStack Pte. Ltd. : https://avstack.io +// Submitted by Jasper Hugo +onavstack.net + +// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com +// Submitted by James Kennedy +*.awdev.ca +*.advisor.ws + +// AZ.pl sp. z.o.o: https://az.pl +// Submited by Krzysztof Wolski +ecommerce-shop.pl + +// b-data GmbH : https://www.b-data.io +// Submitted by Olivier Benz +b-data.io + +// backplane : https://www.backplane.io +// Submitted by Anthony Voutas +backplaneapp.io + +// Balena : https://www.balena.io +// Submitted by Petros Angelatos +balena-devices.com + +// University of Banja Luka : https://unibl.org +// Domains for Republic of Srpska administrative entity. +// Submitted by Marko Ivanovic +rs.ba + +// Banzai Cloud +// Submitted by Janos Matyas +*.banzai.cloud +app.banzaicloud.io +*.backyards.banzaicloud.io + +// BASE, Inc. : https://binc.jp +// Submitted by Yuya NAGASAWA +base.ec +official.ec +buyshop.jp +fashionstore.jp +handcrafted.jp +kawaiishop.jp +supersale.jp +theshop.jp +shopselect.net +base.shop + +// Beget Ltd +// Submitted by Lev Nekrasov +*.beget.app // BetaInABox // Submitted by Adrian betainabox.com +// BinaryLane : http://www.binarylane.com +// Submitted by Nathan O'Sullivan +bnr.la + +// Bitbucket : http://bitbucket.org +// Submitted by Andy Ortlieb +bitbucket.io + +// Blackbaud, Inc. : https://www.blackbaud.com +// Submitted by Paul Crowder +blackbaudcdn.net + +// Blatech : http://www.blatech.net +// Submitted by Luke Bratch +of.je + +// Blue Bite, LLC : https://bluebite.com +// Submitted by Joshua Weiss +bluebite.io + +// Boomla : https://boomla.com +// Submitted by Tibor Halter +boomla.net + +// Boutir : https://www.boutir.com +// Submitted by Eric Ng Ka Ka +boutir.com + +// Boxfuse : https://boxfuse.com +// Submitted by Axel Fontaine +boxfuse.io + +// bplaced : https://www.bplaced.net/ +// Submitted by Miroslav Bozic +square7.ch +bplaced.com +bplaced.de +square7.de +bplaced.net +square7.net + +// Brendly : https://brendly.rs +// Submitted by Dusan Radovanovic +shop.brendly.rs + +// BrowserSafetyMark +// Submitted by Dave Tharp +browsersafetymark.io + +// Bytemark Hosting : https://www.bytemark.co.uk +// Submitted by Paul Cammish +uk0.bigv.io +dh.bytemark.co.uk +vm.bytemark.co.uk + +// Caf.js Labs LLC : https://www.cafjs.com +// Submitted by Antonio Lain +cafjs.com + +// callidomus : https://www.callidomus.com/ +// Submitted by Marcus Popp +mycd.eu + +// Carrd : https://carrd.co +// Submitted by AJ +drr.ac +uwu.ai +carrd.co +crd.co +ju.mp + // CentralNic : http://www.centralnic.com/names/domains // Submitted by registry ae.org -ar.com br.com cn.com com.de com.se de.com eu.com -gb.com gb.net -hu.com hu.net jp.net jpn.com -kr.com mex.com -no.com -qc.com ru.com sa.com -se.com se.net uk.com uk.net us.com -uy.com za.bz za.com +// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators +// Submitted by Gavin Brown +ar.com +hu.com +kr.com +no.com +qc.com +uy.com + // Africa.com Web Solutions Ltd : https://registry.africa.com // Submitted by Gavin Brown africa.com @@ -10685,6 +10983,7 @@ gr.com // Radix FZC : http://domains.in.net // Submitted by Gavin Brown in.net +web.in // US REGISTRY LLC : http://us.org // Submitted by Gavin Brown @@ -10694,17 +10993,89 @@ us.org // Submitted by Gavin Brown co.com +// Roar Domains LLC : https://roar.basketball/ +// Submitted by Gavin Brown +aus.basketball +nz.basketball + +// BRS Media : https://brsmedia.com/ +// Submitted by Gavin Brown +radio.am +radio.fm + // c.la : http://www.c.la/ c.la +// certmgr.org : https://certmgr.org +// Submitted by B. Blechschmidt +certmgr.org + +// Cityhost LLC : https://cityhost.ua +// Submitted by Maksym Rivtin +cx.ua + +// Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ +// Submitted by Rishabh Nambiar & Michael Brown +discourse.group +discourse.team + +// Clever Cloud : https://www.clever-cloud.com/ +// Submitted by Quentin Adam +cleverapps.io + +// Clerk : https://www.clerk.dev +// Submitted by Colin Sidoti +clerk.app +clerkstage.app +*.lcl.dev +*.lclstage.dev +*.stg.dev +*.stgstage.dev + +// ClickRising : https://clickrising.com/ +// Submitted by Umut Gumeli +clickrising.net + +// Cloud66 : https://www.cloud66.com/ +// Submitted by Khash Sajadi +c66.me +cloud66.ws +cloud66.zone + +// CloudAccess.net : https://www.cloudaccess.net/ +// Submitted by Pawel Panek +jdevcloud.com +wpdevcloud.com +cloudaccess.host +freesite.host +cloudaccess.net + // cloudControl : https://www.cloudcontrol.com/ // Submitted by Tobias Wilken cloudcontrolled.com cloudcontrolapp.com +// Cloudera, Inc. : https://www.cloudera.com/ +// Submitted by Kedarnath Waikar +*.cloudera.site + +// Cloudflare, Inc. : https://www.cloudflare.com/ +// Submitted by Cloudflare Team +pages.dev +trycloudflare.com +workers.dev + +// Clovyr : https://clovyr.io +// Submitted by Patrick Nielsen +wnext.app + // co.ca : http://registry.co.ca/ co.ca +// Co & Co : https://co-co.nl/ +// Submitted by Govert Versluis +*.otap.co + // i-registry s.r.o. : http://www.i-registry.cz/ // Submitted by Martin Semrad co.cz @@ -10717,18 +11088,180 @@ r.cdn77.net rsc.cdn77.org ssl.origin.cdn77-secure.org +// Cloud DNS Ltd : http://www.cloudns.net +// Submitted by Aleksander Hristov +cloudns.asia +cloudns.biz +cloudns.club +cloudns.cc +cloudns.eu +cloudns.in +cloudns.info +cloudns.org +cloudns.pro +cloudns.pw +cloudns.us + +// CNPY : https://cnpy.gdn +// Submitted by Angelo Gladding +cnpy.gdn + +// Codeberg e. V. : https://codeberg.org +// Submitted by Moritz Marquardt +codeberg.page + // CoDNS B.V. co.nl co.no -// Commerce Guys, SAS -// Submitted by Damien Tournoud -*.platform.sh +// Combell.com : https://www.combell.com +// Submitted by Thomas Wouters +webhosting.be +hosting-cluster.nl + +// Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/ +// Submitted by George Georgievsky +ac.ru +edu.ru +gov.ru +int.ru +mil.ru +test.ru + +// COSIMO GmbH : http://www.cosimo.de +// Submitted by Rene Marticke +dyn.cosidns.de +dynamisches-dns.de +dnsupdater.de +internet-dns.de +l-o-g-i-n.de +dynamic-dns.info +feste-ip.net +knx-server.net +static-access.net + +// Craynic, s.r.o. : http://www.craynic.com/ +// Submitted by Ales Krajnik +realm.cz + +// Cryptonomic : https://cryptonomic.net/ +// Submitted by Andrew Cady +*.cryptonomic.net // Cupcake : https://cupcake.io/ // Submitted by Jonathan Rudenberg cupcake.is +// Curv UG : https://curv-labs.de/ +// Submitted by Marvin Wiesner +curv.dev + +// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/ +// Submitted by Gregory Drake +// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label +*.customer-oci.com +*.oci.customer-oci.com +*.ocp.customer-oci.com +*.ocs.customer-oci.com + +// cyon GmbH : https://www.cyon.ch/ +// Submitted by Dominic Luechinger +cyon.link +cyon.site + +// Danger Science Group: https://dangerscience.com/ +// Submitted by Skylar MacDonald +fnwk.site +folionetwork.site +platform0.app + +// Daplie, Inc : https://daplie.com +// Submitted by AJ ONeal +daplie.me +localhost.daplie.me + +// Datto, Inc. : https://www.datto.com/ +// Submitted by Philipp Heckel +dattolocal.com +dattorelay.com +dattoweb.com +mydatto.com +dattolocal.net +mydatto.net + +// Dansk.net : http://www.dansk.net/ +// Submitted by Anani Voule +biz.dk +co.dk +firm.dk +reg.dk +store.dk + +// dappnode.io : https://dappnode.io/ +// Submitted by Abel Boldu / DAppNode Team +dyndns.dappnode.io + +// dapps.earth : https://dapps.earth/ +// Submitted by Daniil Burdakov +*.dapps.earth +*.bzz.dapps.earth + +// Dark, Inc. : https://darklang.com +// Submitted by Paul Biggar +builtwithdark.com + +// DataDetect, LLC. : https://datadetect.com +// Submitted by Andrew Banchich +demo.datadetect.com +instance.datadetect.com + +// Datawire, Inc : https://www.datawire.io +// Submitted by Richard Li +edgestack.me + +// DDNS5 : https://ddns5.com +// Submitted by Cameron Elliott +ddns5.com + +// Debian : https://www.debian.org/ +// Submitted by Peter Palfrader / Debian Sysadmin Team +debian.net + +// Deno Land Inc : https://deno.com/ +// Submitted by Luca Casonato +deno.dev +deno-staging.dev + +// deSEC : https://desec.io/ +// Submitted by Peter Thomassen +dedyn.io + +// Diher Solutions : https://diher.solutions +// Submitted by Didi Hermawan +*.rss.my.id +*.diher.solutions + +// DNS Africa Ltd https://dns.business +// Submitted by Calvin Browne +jozi.biz + +// DNShome : https://www.dnshome.de/ +// Submitted by Norbert Auler +dnshome.de + +// DotArai : https://www.dotarai.com/ +// Submitted by Atsadawat Netcharadsang +online.th +shop.th + +// DrayTek Corp. : https://www.draytek.com/ +// Submitted by Paul Fang +drayddns.com + +// DreamCommerce : https://shoper.pl/ +// Submitted by Konrad Kotarba +shoparena.pl + // DreamHost : http://www.dreamhost.com/ // Submitted by Andrew Farmer dreamhosters.com @@ -10737,10 +11270,27 @@ dreamhosters.com // Submitted by Ricardo Padilha mydrobo.com +// Drud Holdings, LLC. : https://www.drud.com/ +// Submitted by Kevin Bridges +drud.io +drud.us + // DuckDNS : http://www.duckdns.org/ // Submitted by Richard Harper duckdns.org +// Bip : https://bip.sh +// Submitted by Joel Kennedy +bip.sh + +// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com +bitbridge.net + +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen +dy.fi +tunk.org + // DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ dyndns-at-home.com dyndns-at-work.com @@ -11022,6 +11572,91 @@ webhop.org worse-than.tv writesthisblog.com +// ddnss.de : https://www.ddnss.de/ +// Submitted by Robert Niedziela +ddnss.de +dyn.ddnss.de +dyndns.ddnss.de +dyndns1.de +dyn-ip24.de +home-webserver.de +dyn.home-webserver.de +myhome-server.de +ddnss.org + +// Definima : http://www.definima.com/ +// Submitted by Maxence Bitterli +definima.net +definima.io + +// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/ +// Submitted by Braxton Huggins +ondigitalocean.app + +// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/ +// Submitted by Robin H. Johnson +*.digitaloceanspaces.com + +// dnstrace.pro : https://dnstrace.pro/ +// Submitted by Chris Partridge +bci.dnstrace.pro + +// Dynu.com : https://www.dynu.com/ +// Submitted by Sue Ye +ddnsfree.com +ddnsgeek.com +giize.com +gleeze.com +kozow.com +loseyourip.com +ooguy.com +theworkpc.com +casacam.net +dynu.net +accesscam.org +camdvr.org +freeddns.org +mywire.org +webredirect.org +myddns.rocks +blogsite.xyz + +// dynv6 : https://dynv6.com +// Submitted by Dominik Menke +dynv6.net + +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr +e4.cz + +// eero : https://eero.com/ +// Submitted by Yue Kang +eero.online +eero-stage.online + +// Elementor : Elementor Ltd. +// Submitted by Anton Barkan +elementor.cloud +elementor.cool + +// En root‽ : https://en-root.org +// Submitted by Emmanuel Raviart +en-root.fr + +// Enalean SAS: https://www.enalean.com +// Submitted by Thomas Cottier +mytuleap.com +tuleap-partners.com + +// ECG Robotics, Inc: https://ecgrobotics.org +// Submitted by +onred.one +staging.onred.one + +// encoway GmbH : https://www.encoway.de +// Submitted by Marcel Daus +eu.encoway.cloud + // EU.org https://eu.org/ // Submitted by Pierre Beyssac eu.org @@ -11081,38 +11716,363 @@ tr.eu.org uk.eu.org us.eu.org -// Fastly Inc. http://www.fastly.com/ -// Submitted by Vladimir Vuksan +// Eurobyte : https://eurobyte.ru +// Submitted by Evgeniy Subbotin +eurodir.ru + +// Evennode : http://www.evennode.com/ +// Submitted by Michal Kralik +eu-1.evennode.com +eu-2.evennode.com +eu-3.evennode.com +eu-4.evennode.com +us-1.evennode.com +us-2.evennode.com +us-3.evennode.com +us-4.evennode.com + +// eDirect Corp. : https://hosting.url.com.tw/ +// Submitted by C.S. chang +twmail.cc +twmail.net +twmail.org +mymailer.com.tw +url.tw + +// Fabrica Technologies, Inc. : https://www.fabrica.dev/ +// Submitted by Eric Jiang +onfabrica.com + +// Facebook, Inc. +// Submitted by Peter Ruibal +apps.fbsbx.com + +// FAITID : https://faitid.org/ +// Submitted by Maxim Alzoba +// https://www.flexireg.net/stat_info +ru.net +adygeya.ru +bashkiria.ru +bir.ru +cbg.ru +com.ru +dagestan.ru +grozny.ru +kalmykia.ru +kustanai.ru +marine.ru +mordovia.ru +msk.ru +mytis.ru +nalchik.ru +nov.ru +pyatigorsk.ru +spb.ru +vladikavkaz.ru +vladimir.ru +abkhazia.su +adygeya.su +aktyubinsk.su +arkhangelsk.su +armenia.su +ashgabad.su +azerbaijan.su +balashov.su +bashkiria.su +bryansk.su +bukhara.su +chimkent.su +dagestan.su +east-kazakhstan.su +exnet.su +georgia.su +grozny.su +ivanovo.su +jambyl.su +kalmykia.su +kaluga.su +karacol.su +karaganda.su +karelia.su +khakassia.su +krasnodar.su +kurgan.su +kustanai.su +lenug.su +mangyshlak.su +mordovia.su +msk.su +murmansk.su +nalchik.su +navoi.su +north-kazakhstan.su +nov.su +obninsk.su +penza.su +pokrovsk.su +sochi.su +spb.su +tashkent.su +termez.su +togliatti.su +troitsk.su +tselinograd.su +tula.su +tuva.su +vladikavkaz.su +vladimir.su +vologda.su + +// Fancy Bits, LLC : http://getchannels.com +// Submitted by Aman Gupta +channelsdvr.net +u.channelsdvr.net + +// Fastly Inc. : http://www.fastly.com/ +// Submitted by Fastly Security +edgecompute.app +fastly-terrarium.com +fastlylb.net +map.fastlylb.net +freetls.fastly.net +map.fastly.net +a.prod.fastly.net +global.prod.fastly.net a.ssl.fastly.net b.ssl.fastly.net global.ssl.fastly.net -a.prod.fastly.net -global.prod.fastly.net + +// FASTVPS EESTI OU : https://fastvps.ru/ +// Submitted by Likhachev Vasiliy +fastvps-server.com +fastvps.host +myfast.host +fastvps.site +myfast.space + +// Fedora : https://fedoraproject.org/ +// submitted by Patrick Uiterwijk +fedorainfracloud.org +fedorapeople.org +cloud.fedoraproject.org +app.os.fedoraproject.org +app.os.stg.fedoraproject.org + +// FearWorks Media Ltd. : https://fearworksmedia.co.uk +// submitted by Keith Fairley +couk.me +ukco.me +conn.uk +copro.uk +hosp.uk + +// Fermax : https://fermax.com/ +// submitted by Koen Van Isterdael +mydobiss.com + +// FH Muenster : https://www.fh-muenster.de +// Submitted by Robin Naundorf +fh-muenster.io + +// Filegear Inc. : https://www.filegear.com +// Submitted by Jason Zhu +filegear.me +filegear-au.me +filegear-de.me +filegear-gb.me +filegear-ie.me +filegear-jp.me +filegear-sg.me // Firebase, Inc. // Submitted by Chris Raynor firebaseapp.com +// Firewebkit : https://www.firewebkit.com +// Submitted by Majid Qureshi +fireweb.app + +// FLAP : https://www.flap.cloud +// Submitted by Louis Chemineau +flap.id + +// FlashDrive : https://flashdrive.io +// Submitted by Eric Chan +onflashdrive.app +fldrv.com + +// fly.io: https://fly.io +// Submitted by Kurt Mackey +fly.dev +edgeapp.net +shw.io + // Flynn : https://flynn.io // Submitted by Jonathan Rudenberg -flynnhub.com - -// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains -// Submitted by David Illsley +flynnhosting.net + +// Forgerock : https://www.forgerock.com +// Submitted by Roderick Parr +forgeblocks.com +id.forgerock.io + +// Framer : https://www.framer.com +// Submitted by Koen Rouwhorst +framer.app +framercanvas.com + +// Frusky MEDIA&PR : https://www.frusky.de +// Submitted by Victor Pupynin +*.frusky.de + +// RavPage : https://www.ravpage.co.il +// Submitted by Roni Horowitz +ravpage.co.il + +// Frederik Braun https://frederik-braun.com +// Submitted by Frederik Braun +0e.vc + +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + +// freedesktop.org : https://www.freedesktop.org +// Submitted by Daniel Stone +freedesktop.org + +// freemyip.com : https://freemyip.com +// Submitted by Cadence +freemyip.com + +// FunkFeuer - Verein zur Förderung freier Netze : https://www.funkfeuer.at +// Submitted by Daniel A. Maierhofer +wien.funkfeuer.at + +// Futureweb OG : http://www.futureweb.at +// Submitted by Andreas Schnederle-Wagner +*.futurecms.at +*.ex.futurecms.at +*.in.futurecms.at +futurehosting.at +futuremailing.at +*.ex.ortsinfo.at +*.kunden.ortsinfo.at +*.statics.cloud + +// GDS : https://www.gov.uk/service-manual/technology/managing-domain-names +// Submitted by Stephen Ford +independent-commission.uk +independent-inquest.uk +independent-inquiry.uk +independent-panel.uk +independent-review.uk +public-inquiry.uk +royal-commission.uk service.gov.uk +// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk +// Submitted by Jamie Tanna +api.gov.uk + +// Gehirn Inc. : https://www.gehirn.co.jp/ +// Submitted by Kohei YOSHIDA +gehirn.ne.jp +usercontent.jp + +// Gentlent, Inc. : https://www.gentlent.com +// Submitted by Tom Klein +gentapps.com +gentlentapis.com +lab.ms +cdn-edges.net + +// Ghost Foundation : https://ghost.org +// Submitted by Matt Hanley +ghost.io + +// GignoSystemJapan: http://gsj.bz +// Submitted by GignoSystemJapan +gsj.bz + // GitHub, Inc. -// Submitted by Ben Toews -github.io +// Submitted by Patrick Toomey githubusercontent.com +githubpreview.dev +github.io + +// GitLab, Inc. +// Submitted by Alex Hanselka +gitlab.io + +// Gitplac.si - https://gitplac.si +// Submitted by Aljaž Starc +gitapp.si +gitpage.si + +// Glitch, Inc : https://glitch.com +// Submitted by Mads Hartmann +glitch.me + +// Global NOG Alliance : https://nogalliance.org/ +// Submitted by Sander Steffann +nog.community + +// Globe Hosting SRL : https://www.globehosting.com/ +// Submitted by Gavin Brown +co.ro +shop.ro + +// GMO Pepabo, Inc. : https://pepabo.com/ +// Submitted by dojineko +lolipop.io + +// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ +// Submitted by Tom Whitwell +cloudapps.digital +london.cloudapps.digital + +// GOV.UK Pay : https://www.payments.service.gov.uk/ +// Submitted by Richard Baker +pymnt.uk + +// UKHomeOffice : https://www.gov.uk/government/organisations/home-office +// Submitted by Jon Shanks +homeoffice.gov.uk // GlobeHosting, Inc. // Submitted by Zoltan Egresi -ro.com +ro.im + +// GoIP DNS Services : http://www.goip.de +// Submitted by Christian Poulter +goip.de // Google, Inc. // Submitted by Eduardo Vela +run.app +a.run.app +web.app +*.0emm.com appspot.com +*.r.appspot.com +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com +*.gateway.dev +cloud.goog +translate.goog +*.usercontent.goog +cloudfunctions.net blogspot.ae blogspot.al blogspot.am @@ -11187,43 +12147,601 @@ blogspot.td blogspot.tw blogspot.ug blogspot.vn -cloudfunctions.net -codespot.com -googleapis.com -googlecode.com -pagespeedmobilizer.com -withgoogle.com -withyoutube.com + +// Goupile : https://goupile.fr +// Submitted by Niels Martignene +goupile.fr + +// Group 53, LLC : https://www.group53.com +// Submitted by Tyler Todd +awsmppl.com + +// GünstigBestellen : https://günstigbestellen.de +// Submitted by Furkan Akkoc +günstigbestellen.de +günstigliefern.de + +// Hakaran group: http://hakaran.cz +// Submited by Arseniy Sokolov +fin.ci +free.hr +caa.li +ua.rs +conf.se + +// Handshake : https://handshake.org +// Submitted by Mike Damm +hs.zone +hs.run // Hashbang : https://hashbang.sh hashbang.sh +// Hasura : https://hasura.io +// Submitted by Shahidh K Muhammed +hasura.app +hasura-app.io + +// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de +// Submitted by Richard Zowalla +pages.it.hs-heilbronn.de + +// Hepforge : https://www.hepforge.org +// Submitted by David Grellscheid +hepforge.org + // Heroku : https://www.heroku.com/ // Submitted by Tom Maher herokuapp.com herokussl.com +// Hibernating Rhinos +// Submitted by Oren Eini +ravendb.cloud +myravendb.com +ravendb.community +ravendb.me +development.run +ravendb.run + +// home.pl S.A.: https://home.pl +// Submited by Krzysztof Wolski +homesklep.pl + +// Hong Kong Productivity Council: https://www.hkpc.org/ +// Submitted by SECaaS Team +secaas.hk + +// Hoplix : https://www.hoplix.com +// Submitted by Danilo De Franco +hoplix.shop + + +// HOSTBIP REGISTRY : https://www.hostbip.com/ +// Submitted by Atanunu Igbunuroghene +orx.biz +biz.gl +col.ng +firm.ng +gen.ng +ltd.ng +ngo.ng +edu.scot +sch.so +org.yt + +// HostyHosting (hostyhosting.com) +hostyhosting.io + +// Häkkinen.fi +// Submitted by Eero Häkkinen +häkkinen.fi + +// Ici la Lune : http://www.icilalune.com/ +// Submitted by Simon Morvan +*.moonscale.io +moonscale.net + // iki.fi // Submitted by Hannu Aronsson iki.fi +// Impertrix Solutions : +// Submitted by Zhixiang Zhao +impertrixcdn.com +impertrix.com + +// Incsub, LLC: https://incsub.com/ +// Submitted by Aaron Edwards +smushcdn.com +wphostedmail.com +wpmucdn.com +tempurl.host +wpmudev.host + +// Individual Network Berlin e.V. : https://www.in-berlin.de/ +// Submitted by Christian Seitz +dyn-berlin.de +in-berlin.de +in-brb.de +in-butter.de +in-dsl.de +in-dsl.net +in-dsl.org +in-vpn.de +in-vpn.net +in-vpn.org + // info.at : http://www.info.at/ biz.at info.at +// info.cx : http://info.cx +// Submitted by Jacob Slater +info.cx + +// Interlegis : http://www.interlegis.leg.br +// Submitted by Gabriel Ferreira +ac.leg.br +al.leg.br +am.leg.br +ap.leg.br +ba.leg.br +ce.leg.br +df.leg.br +es.leg.br +go.leg.br +ma.leg.br +mg.leg.br +ms.leg.br +mt.leg.br +pa.leg.br +pb.leg.br +pe.leg.br +pi.leg.br +pr.leg.br +rj.leg.br +rn.leg.br +ro.leg.br +rr.leg.br +rs.leg.br +sc.leg.br +se.leg.br +sp.leg.br +to.leg.br + +// intermetrics GmbH : https://pixolino.com/ +// Submitted by Wolfgang Schwarz +pixolino.com + +// Internet-Pro, LLP: https://netangels.ru/ +// Submited by Vasiliy Sheredeko +na4u.ru + +// iopsys software solutions AB : https://iopsys.eu/ +// Submitted by Roman Azarenko +iopsys.se + +// IPiFony Systems, Inc. : https://www.ipifony.com/ +// Submitted by Matthew Hardeman +ipifony.net + +// IServ GmbH : https://iserv.eu +// Submitted by Kim-Alexander Brodowski +mein-iserv.de +schulserver.de +test-iserv.de +iserv.dev + +// I-O DATA DEVICE, INC. : http://www.iodata.com/ +// Submitted by Yuji Minagawa +iobb.net + +// Jelastic, Inc. : https://jelastic.com/ +// Submited by Ihor Kolodyuk +mel.cloudlets.com.au +cloud.interhostsolutions.be +users.scale.virtualcloud.com.br +mycloud.by +alp1.ae.flow.ch +appengine.flow.ch +es-1.axarnet.cloud +diadem.cloud +vip.jelastic.cloud +jele.cloud +it1.eur.aruba.jenv-aruba.cloud +it1.jenv-aruba.cloud +keliweb.cloud +cs.keliweb.cloud +oxa.cloud +tn.oxa.cloud +uk.oxa.cloud +primetel.cloud +uk.primetel.cloud +ca.reclaim.cloud +uk.reclaim.cloud +us.reclaim.cloud +ch.trendhosting.cloud +de.trendhosting.cloud +jele.club +amscompute.com +clicketcloud.com +dopaas.com +hidora.com +paas.hosted-by-previder.com +rag-cloud.hosteur.com +rag-cloud-ch.hosteur.com +jcloud.ik-server.com +jcloud-ver-jpc.ik-server.com +demo.jelastic.com +kilatiron.com +paas.massivegrid.com +jed.wafaicloud.com +lon.wafaicloud.com +ryd.wafaicloud.com +j.scaleforce.com.cy +jelastic.dogado.eu +fi.cloudplatform.fi +demo.datacenter.fi +paas.datacenter.fi +jele.host +mircloud.host +paas.beebyte.io +sekd1.beebyteapp.io +jele.io +cloud-fr1.unispace.io +jc.neen.it +cloud.jelastic.open.tim.it +jcloud.kz +upaas.kazteleport.kz +cloudjiffy.net +fra1-de.cloudjiffy.net +west1-us.cloudjiffy.net +jls-sto1.elastx.net +jls-sto2.elastx.net +jls-sto3.elastx.net +faststacks.net +fr-1.paas.massivegrid.net +lon-1.paas.massivegrid.net +lon-2.paas.massivegrid.net +ny-1.paas.massivegrid.net +ny-2.paas.massivegrid.net +sg-1.paas.massivegrid.net +jelastic.saveincloud.net +nordeste-idc.saveincloud.net +j.scaleforce.net +jelastic.tsukaeru.net +sdscloud.pl +unicloud.pl +mircloud.ru +jelastic.regruhosting.ru +enscaled.sg +jele.site +jelastic.team +orangecloud.tn +j.layershift.co.uk +phx.enscaled.us +mircloud.us + +// Jino : https://www.jino.ru +// Submitted by Sergey Ulyashin +myjino.ru +*.hosting.myjino.ru +*.landing.myjino.ru +*.spectrum.myjino.ru +*.vps.myjino.ru + +// Jotelulu S.L. : https://jotelulu.com +// Submitted by Daniel Fariña +jotelulu.cloud + +// Joyent : https://www.joyent.com/ +// Submitted by Brian Bennett +*.triton.zone +*.cns.joyent.com + +// JS.ORG : http://dns.js.org +// Submitted by Stefan Keim +js.org + +// KaasHosting : http://www.kaashosting.nl/ +// Submitted by Wouter Bakker +kaas.gg +khplay.nl + +// Keyweb AG : https://www.keyweb.de +// Submitted by Martin Dannehl +keymachine.de + +// KingHost : https://king.host +// Submitted by Felipe Keller Braz +kinghost.net +uni5.net + +// KnightPoint Systems, LLC : http://www.knightpoint.com/ +// Submitted by Roy Keene +knightpoint.systems + +// KoobinEvent, SL: https://www.koobin.com +// Submitted by Iván Oliva +koobin.events + +// KUROKU LTD : https://kuroku.ltd/ +// Submitted by DisposaBoy +oya.to + +// Katholieke Universiteit Leuven: https://www.kuleuven.be +// Submitted by Abuse KU Leuven +kuleuven.cloud +ezproxy.kuleuven.be + +// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf +co.krd +edu.krd + +// Krellian Ltd. : https://krellian.com +// Submitted by Ben Francis +krellian.net +webthings.io + +// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de +// Submitted by Lars Laehn +git-repos.de +lcube-server.de +svn-repos.de + +// Leadpages : https://www.leadpages.net +// Submitted by Greg Dallavalle +leadpages.co +lpages.co +lpusercontent.com + +// Lelux.fi : https://lelux.fi/ +// Submitted by Lelux Admin +lelux.site + +// Lifetime Hosting : https://Lifetime.Hosting/ +// Submitted by Mike Fillator +co.business +co.education +co.events +co.financial +co.network +co.place +co.technology + +// Lightmaker Property Manager, Inc. : https://app.lmpm.com/ +// Submitted by Greg Holland +app.lmpm.com + +// linkyard ldt: https://www.linkyard.ch/ +// Submitted by Mario Siegenthaler +linkyard.cloud +linkyard-cloud.ch + +// Linode : https://linode.com +// Submitted by +members.linode.com +*.nodebalancer.linode.com +*.linodeobjects.com +ip.linodeusercontent.com + +// LiquidNet Ltd : http://www.liquidnetlimited.com/ +// Submitted by Victor Velchev +we.bs + +// localzone.xyz +// Submitted by Kenny Niehage +localzone.xyz + +// Log'in Line : https://www.loginline.com/ +// Submitted by Rémi Mach +loginline.app +loginline.dev +loginline.io +loginline.services +loginline.site + +// Lokalized : https://lokalized.nl +// Submitted by Noah Taheij +servers.run + +// Lõhmus Family, The +// Submitted by Heiki Lõhmus +lohmus.me + +// LubMAN UMCS Sp. z o.o : https://lubman.pl/ +// Submitted by Ireneusz Maliszewski +krasnik.pl +leczna.pl +lubartow.pl +lublin.pl +poniatowa.pl +swidnik.pl + +// Lug.org.uk : https://lug.org.uk +// Submitted by Jon Spriggs +glug.org.uk +lug.org.uk +lugs.org.uk + +// Lukanet Ltd : https://lukanet.com +// Submitted by Anton Avramov +barsy.bg +barsy.co.uk +barsyonline.co.uk +barsycenter.com +barsyonline.com +barsy.club +barsy.de +barsy.eu +barsy.in +barsy.info +barsy.io +barsy.me +barsy.menu +barsy.mobi +barsy.net +barsy.online +barsy.org +barsy.pro +barsy.pub +barsy.ro +barsy.shop +barsy.site +barsy.support +barsy.uk + +// Magento Commerce +// Submitted by Damien Tournoud +*.magentosite.cloud + +// May First - People Link : https://mayfirst.org/ +// Submitted by Jamie McClelland +mayfirst.info +mayfirst.org + +// Mail.Ru Group : https://hb.cldmail.ru +// Submitted by Ilya Zaretskiy +hb.cldmail.ru + +// Mail Transfer Platform : https://www.neupeer.com +// Submitted by Li Hui +cn.vu + +// Maze Play: https://www.mazeplay.com +// Submitted by Adam Humpherys +mazeplay.com + +// mcpe.me : https://mcpe.me +// Submitted by Noa Heyl +mcpe.me + +// McHost : https://mchost.ru +// Submitted by Evgeniy Subbotin +mcdir.me +mcdir.ru +mcpre.ru +vps.mcdir.ru + +// Mediatech : https://mediatech.by +// Submitted by Evgeniy Kozhuhovskiy +mediatech.by +mediatech.dev + +// Medicom Health : https://medicomhealth.com +// Submitted by Michael Olson +hra.health + +// Memset hosting : https://www.memset.com +// Submitted by Tom Whitwell +miniserver.com +memset.net + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Zdeněk Šustr +*.cloud.metacentrum.cz +custom.metacentrum.cz + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Radim Janča +flt.cloud.muni.cz +usr.cloud.muni.cz + +// Meteor Development Group : https://www.meteor.com/hosting +// Submitted by Pierre Carrier +meteorapp.com +eu.meteorapp.com + // Michau Enterprises Limited : http://www.co.pl/ co.pl -// Microsoft : http://microsoft.com -// Submitted by Barry Dorrans +// Microsoft Corporation : http://microsoft.com +// Submitted by Mitch Webster +*.azurecontainer.io azurewebsites.net azure-mobile.net cloudapp.net +azurestaticapps.net +centralus.azurestaticapps.net +eastasia.azurestaticapps.net +eastus2.azurestaticapps.net +westeurope.azurestaticapps.net +westus2.azurestaticapps.net + +// minion.systems : http://minion.systems +// Submitted by Robert Böttinger +csx.cc + +// Mintere : https://mintere.com/ +// Submitted by Ben Aubin +mintere.site + +// MobileEducation, LLC : https://joinforte.com +// Submitted by Grayson Martin +forte.id + +// Mozilla Corporation : https://mozilla.com +// Submitted by Ben Francis +mozilla-iot.org // Mozilla Foundation : https://mozilla.org/ // Submitted by glob bmoattachments.org +// MSK-IX : https://www.msk-ix.ru/ +// Submitted by Khannanov Roman +net.ru +org.ru +pp.ru + +// Mythic Beasts : https://www.mythic-beasts.com +// Submitted by Paul Cammish +hostedpi.com +customer.mythic-beasts.com +caracal.mythic-beasts.com +fentiger.mythic-beasts.com +lynx.mythic-beasts.com +ocelot.mythic-beasts.com +oncilla.mythic-beasts.com +onza.mythic-beasts.com +sphinx.mythic-beasts.com +vs.mythic-beasts.com +x.mythic-beasts.com +yali.mythic-beasts.com +cust.retrosnub.co.uk + +// Nabu Casa : https://www.nabucasa.com +// Submitted by Paulus Schoutsen +ui.nabu.casa + +// Names.of.London : https://names.of.london/ +// Submitted by James Stevens or +pony.club +of.fashion +in.london +of.london +from.marketing +with.marketing +for.men +repair.men +and.mom +for.mom +for.one +under.one +for.sale +that.win +from.work +to.work + +// Net at Work Gmbh : https://www.netatwork.de +// Submitted by Jan Jaeschke +cloud.nospamproxy.com + +// Netlify : https://www.netlify.com +// Submitted by Jessica Parsons +netlify.app + // Neustar Inc. // Submitted by Trung Tran 4u.com @@ -11232,30 +12750,260 @@ bmoattachments.org // Submitted by Alan Shreve ngrok.io +// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ +// Submitted by Nicholas Ford +nh-serv.co.uk + // NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ // Submitted by Jeff Wheelhouse nfshost.com +// Noop : https://noop.app +// Submitted by Nathaniel Schweinberg +*.developer.app +noop.app + +// Northflank Ltd. : https://northflank.com/ +// Submitted by Marco Suter +*.northflank.app +*.code.run + +// Noticeable : https://noticeable.io +// Submitted by Laurent Pellegrino +noticeable.news + +// Now-DNS : https://now-dns.com +// Submitted by Steve Russell +dnsking.ch +mypi.co +n4t.co +001www.com +ddnslive.com +myiphost.com +forumz.info +16-b.it +32-b.it +64-b.it +soundcast.me +tcp4.me +dnsup.net +hicam.net +now-dns.net +ownip.net +vpndns.net +dynserv.org +now-dns.org +x443.pw +now-dns.top +ntdll.top +freeddns.us +crafting.xyz +zapto.xyz + +// nsupdate.info : https://www.nsupdate.info/ +// Submitted by Thomas Waldmann +nsupdate.info +nerdpol.ovh + +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + +// NodeArt : https://nodeart.io +// Submitted by Konstantin Nosov +stage.nodeart.io + +// Nucleos Inc. : https://nucleos.com +// Submitted by Piotr Zduniak +pcloud.host + // NYC.mn : http://www.information.nyc.mn // Submitted by Matthew Brown nyc.mn +// Observable, Inc. : https://observablehq.com +// Submitted by Mike Bostock +static.observableusercontent.com + +// Octopodal Solutions, LLC. : https://ulterius.io/ +// Submitted by Andrew Sampson +cya.gg + +// OMG.LOL : +// Submitted by Adam Newbold +omg.lol + +// Omnibond Systems, LLC. : https://www.omnibond.com +// Submitted by Cole Estep +cloudycluster.net + +// OmniWe Limited: https://omniwe.com +// Submitted by Vicary Archangel +omniwe.site + +// One.com: https://www.one.com/ +// Submitted by Jacob Bunk Nielsen +service.one + // One Fold Media : http://www.onefoldmedia.com/ // Submitted by Eddie Jones nid.io +// Open Social : https://www.getopensocial.com/ +// Submitted by Alexander Varwijk +opensocial.site + +// OpenCraft GmbH : http://opencraft.com/ +// Submitted by Sven Marnach +opencraft.hosting + +// OpenResearch GmbH: https://openresearch.com/ +// Submitted by Philipp Schmid +orsites.com + // Opera Software, A.S.A. // Submitted by Yngve Pettersen operaunite.com +// Oursky Limited : https://authgear.com/, https://skygear.io/ +// Submited by Authgear Team , Skygear Developer +authgear-staging.com +authgearapps.com +skygearapp.com + // OutSystems // Submitted by Duarte Santos outsystemscloud.com +// OVHcloud: https://ovhcloud.com +// Submitted by Vincent Cassé +*.webpaas.ovh.net +*.hosting.ovh.net + +// OwnProvider GmbH: http://www.ownprovider.com +// Submitted by Jan Moennich +ownprovider.com +own.pm + +// OwO : https://whats-th.is/ +// Submitted by Dean Sheather +*.owo.codes + +// OX : http://www.ox.rs +// Submitted by Adam Grand +ox.rs + +// oy.lc +// Submitted by Charly Coste +oy.lc + +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers +pgfog.com + // Pagefront : https://www.pagefronthq.com/ // Submitted by Jason Kriss pagefrontapp.com +// PageXL : https://pagexl.com +// Submitted by Yann Guichard +pagexl.com + +// Paywhirl, Inc : https://paywhirl.com/ +// Submitted by Daniel Netzer +*.paywhirl.com + +// pcarrier.ca Software Inc: https://pcarrier.ca/ +// Submitted by Pierre Carrier +bar0.net +bar1.net +bar2.net +rdv.to + // .pl domains (grandfathered) art.pl gliwice.pl @@ -11266,9 +13014,65 @@ zakopane.pl // Pantheon Systems, Inc. : https://pantheon.io/ // Submitted by Gary Dylina -pantheon.io +pantheonsite.io gotpantheon.com +// Peplink | Pepwave : http://peplink.com/ +// Submitted by Steve Leung +mypep.link + +// Perspecta : https://perspecta.com/ +// Submitted by Kenneth Van Alstyne +perspecta.cloud + +// PE Ulyanov Kirill Sergeevich : https://airy.host +// Submitted by Kirill Ulyanov +lk3.ru + +// Planet-Work : https://www.planet-work.com/ +// Submitted by Frédéric VANNIÈRE +on-web.fr + +// Platform.sh : https://platform.sh +// Submitted by Nikola Kotur +bc.platform.sh +ent.platform.sh +eu.platform.sh +us.platform.sh +*.platformsh.site +*.tst.site + +// Platter: https://platter.dev +// Submitted by Patrick Flor +platter-app.com +platter-app.dev +platterp.us + +// Plesk : https://www.plesk.com/ +// Submitted by Anton Akhtyamov +pdns.page +plesk.page +pleskns.com + +// Port53 : https://port53.io/ +// Submitted by Maximilian Schieder +dyn53.io + +// Positive Codes Technology Company : http://co.bn/faq.html +// Submitted by Zulfais +co.bn + +// Postman, Inc : https://postman.com +// Submitted by Rahul Dhawan +postman-echo.com +pstmn.io +mock.pstmn.io +httpbin.org + +//prequalifyme.today : https://prequalifyme.today +//Submitted by DeepakTiwari deepak@ivylead.io +prequalifyme.today + // prgmr.com : https://prgmr.com/ // Submitted by Sarah Newman xen.prgmr.com @@ -11277,34 +13081,381 @@ xen.prgmr.com // Submitted by registry priv.at +// privacytools.io : https://www.privacytools.io/ +// Submitted by Jonah Aragon +prvcy.page + +// Protocol Labs : https://protocol.ai/ +// Submitted by Michael Burns +*.dweb.link + +// Protonet GmbH : http://protonet.io +// Submitted by Martin Meier +protonet.io + +// Publication Presse Communication SARL : https://ppcom.fr +// Submitted by Yaacov Akiba Slama +chirurgiens-dentistes-en-france.fr +byen.site + +// pubtls.org: https://www.pubtls.org +// Submitted by Kor Nielsen +pubtls.org + +// PythonAnywhere LLP: https://www.pythonanywhere.com +// Submitted by Giles Thomas +pythonanywhere.com +eu.pythonanywhere.com + +// QOTO, Org. +// Submitted by Jeffrey Phillips Freeman +qoto.io + +// Qualifio : https://qualifio.com/ +// Submitted by Xavier De Cock +qualifioapp.com + +// QuickBackend: https://www.quickbackend.com +// Submitted by Dani Biro +qbuser.com + +// Rad Web Hosting: https://radwebhosting.com +// Submitted by Scott Claeys +cloudsite.builders + +// Redgate Software: https://red-gate.com +// Submitted by Andrew Farries +instances.spawn.cc + +// Redstar Consultants : https://www.redstarconsultants.com/ +// Submitted by Jons Slemmer +instantcloud.cn + +// Russian Academy of Sciences +// Submitted by Tech Support +ras.ru + // QA2 // Submitted by Daniel Dent (https://www.danieldent.com/) qa2.com +// QCX +// Submitted by Cassandra Beelen +qcx.io +*.sys.qcx.io + +// QNAP System Inc : https://www.qnap.com +// Submitted by Nick Chang +dev-myqnapcloud.com +alpha-myqnapcloud.com +myqnapcloud.com + +// Quip : https://quip.com +// Submitted by Patrick Linehan +*.quipelements.com + +// Qutheory LLC : http://qutheory.io +// Submitted by Jonas Schwartz +vapor.cloud +vaporcloud.io + // Rackmaze LLC : https://www.rackmaze.com // Submitted by Kirill Pertsev rackmaze.com rackmaze.net +// Rakuten Games, Inc : https://dev.viberplay.io +// Submitted by Joshua Zhang +g.vbrplsbx.io + +// Rancher Labs, Inc : https://rancher.com +// Submitted by Vincent Fiduccia +*.on-k3s.io +*.on-rancher.cloud +*.on-rio.io + +// Read The Docs, Inc : https://www.readthedocs.org +// Submitted by David Fischer +readthedocs.io + // Red Hat, Inc. OpenShift : https://openshift.redhat.com/ // Submitted by Tim Kramer rhcloud.com +// Render : https://render.com +// Submitted by Anurag Goel +app.render.com +onrender.com + +// Repl.it : https://repl.it +// Submitted by Mason Clayton +repl.co +id.repl.co +repl.run + +// Resin.io : https://resin.io +// Submitted by Tim Perry +resindevice.io +devices.resinstaging.io + +// RethinkDB : https://www.rethinkdb.com/ +// Submitted by Chris Kastorff +hzc.io + +// Revitalised Limited : http://www.revitalised.co.uk +// Submitted by Jack Price +wellbeingzone.eu +wellbeingzone.co.uk + +// Rico Developments Limited : https://adimo.co +// Submitted by Colin Brown +adimo.co.uk + +// Riseup Networks : https://riseup.net +// Submitted by Micah Anderson +itcouldbewor.se + +// Rochester Institute of Technology : http://www.rit.edu/ +// Submitted by Jennifer Herting +git-pages.rit.edu + +// Rusnames Limited: http://rusnames.ru/ +// Submitted by Sergey Zotov +биз.рус +ком.рус +крым.рус +мир.рус +мск.рус +орг.рус +самара.рус +сочи.рус +спб.рус +я.рус + // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia sandcats.io +// SBE network solutions GmbH : https://www.sbe.de/ +// Submitted by Norman Meilick +logoip.de +logoip.com + +// schokokeks.org GbR : https://schokokeks.org/ +// Submitted by Hanno Böck +schokokeks.net + +// Scottish Government: https://www.gov.scot +// Submitted by Martin Ellis +gov.scot +service.gov.scot + +// Scry Security : http://www.scrysec.com +// Submitted by Shante Adam +scrysec.com + +// Securepoint GmbH : https://www.securepoint.de +// Submitted by Erik Anders +firewall-gateway.com +firewall-gateway.de +my-gateway.de +my-router.de +spdns.de +spdns.eu +firewall-gateway.net +my-firewall.org +myfirewall.org +spdns.org + +// Seidat : https://www.seidat.com +// Submitted by Artem Kondratev +seidat.net + +// Sellfy : https://sellfy.com +// Submitted by Yuriy Romadin +sellfy.store + +// Senseering GmbH : https://www.senseering.de +// Submitted by Felix Mönckemeyer +senseering.net + +// Sendmsg: https://www.sendmsg.co.il +// Submitted by Assaf Stern +minisite.ms + +// Service Magnet : https://myservicemagnet.com +// Submitted by Dave Sanders +magnet.page + // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh biz.ua co.ua pp.ua +// Shift Crypto AG : https://shiftcrypto.ch +// Submitted by alex +shiftcrypto.dev +shiftcrypto.io + +// ShiftEdit : https://shiftedit.net/ +// Submitted by Adam Jimenez +shiftedit.io + +// Shopblocks : http://www.shopblocks.com/ +// Submitted by Alex Bowers +myshopblocks.com + +// Shopify : https://www.shopify.com +// Submitted by Alex Richter +myshopify.com + +// Shopit : https://www.shopitcommerce.com/ +// Submitted by Craig McMahon +shopitsite.com + +// shopware AG : https://shopware.com +// Submitted by Jens Küper +shopware.store + +// Siemens Mobility GmbH +// Submitted by Oliver Graebner +mo-siemens.io + // SinaAppEngine : http://sae.sina.com.cn/ // Submitted by SinaAppEngine +1kapp.com +appchizi.com +applinzi.com sinaapp.com vipsinaapp.com -1kapp.com + +// Siteleaf : https://www.siteleaf.com/ +// Submitted by Skylar Challand +siteleaf.net + +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// Small Technology Foundation : https://small-tech.org +// Submitted by Aral Balkan +small-web.org + +// Smoove.io : https://www.smoove.io/ +// Submitted by Dan Kozak +vp4.me + +// Snowplow Analytics : https://snowplowanalytics.com/ +// Submitted by Ian Streeter +try-snowplow.com + +// SourceHut : https://sourcehut.org +// Submitted by Drew DeVault +srht.site + +// Stackhero : https://www.stackhero.io +// Submitted by Adrien Gillon +stackhero-network.com + +// Staclar : https://staclar.com +// Submitted by Matthias Merkel +novecore.site + +// staticland : https://static.land +// Submitted by Seth Vincent +static.land +dev.static.land +sites.static.land + +// Storebase : https://www.storebase.io +// Submitted by Tony Schirmer +storebase.store + +// Strategic System Consulting (eApps Hosting): https://www.eapps.com/ +// Submitted by Alex Oancea +vps-host.net +atl.jelastic.vps-host.net +njs.jelastic.vps-host.net +ric.jelastic.vps-host.net + +// Sony Interactive Entertainment LLC : https://sie.com/ +// Submitted by David Coles +playstation-cloud.com + +// SourceLair PC : https://www.sourcelair.com +// Submitted by Antonis Kalipetis +apps.lair.io +*.stolos.io + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan +spacekit.io + +// SpeedPartner GmbH: https://www.speedpartner.de/ +// Submitted by Stefan Neufeind +customer.speedpartner.de + +// Spreadshop (sprd.net AG) : https://www.spreadshop.com/ +// Submitted by Martin Breest +myspreadshop.at +myspreadshop.com.au +myspreadshop.be +myspreadshop.ca +myspreadshop.ch +myspreadshop.com +myspreadshop.de +myspreadshop.dk +myspreadshop.es +myspreadshop.fi +myspreadshop.fr +myspreadshop.ie +myspreadshop.it +myspreadshop.net +myspreadshop.nl +myspreadshop.no +myspreadshop.pl +myspreadshop.se +myspreadshop.co.uk + +// Standard Library : https://stdlib.com +// Submitted by Jacob Lee +api.stdlib.com + +// Storj Labs Inc. : https://storj.io/ +// Submitted by Philip Hutchins +storj.farm + +// Studenten Net Twente : http://www.snt.utwente.nl/ +// Submitted by Silke Hofstra +utwente.io + +// Student-Run Computing Facility : https://www.srcf.net/ +// Submitted by Edwin Balani +soc.srcf.net +user.srcf.net + +// Sub 6 Limited: http://www.sub6.com +// Submitted by Dan Miller +temp-dns.com + +// Supabase : https://supabase.io +// Submitted by Inian Parameshwaran +supabase.co +supabase.in +supabase.net +su.paba.se + +// Symfony, SAS : https://symfony.com/ +// Submitted by Fabien Potencier +*.s5y.io +*.sensiosite.cloud + +// Syncloud : https://syncloud.org +// Submitted by Boris Rybalkin +syncloud.it // Synology, Inc. : https://www.synology.com/ // Submitted by Rony Weng @@ -11321,6 +13472,21 @@ familyds.org i234.me myds.me synology.me +vpnplus.to +direct.quickconnect.to + +// Tabit Technologies Ltd. : https://tabit.cloud/ +// Submitted by Oren Agiv +tabitorder.co.il + +// TAIFUN Software AG : http://taifun-software.de +// Submitted by Bjoern Henke +taifun-dns.de + +// Tailscale Inc. : https://www.tailscale.com +// Submitted by David Anderson +beta.tailscale.net +ts.net // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl @@ -11329,6 +13495,120 @@ gdynia.pl med.pl sopot.pl +// team.blue https://team.blue +// Submitted by Cedric Dubois +site.tb-hosting.com + +// Teckids e.V. : https://www.teckids.org +// Submitted by Dominik George +edugit.io +s3.teckids.org + +// Telebit : https://telebit.cloud +// Submitted by AJ ONeal +telebit.app +telebit.io +*.telebit.xyz + +// The Gwiddle Foundation : https://gwiddlefoundation.org.uk +// Submitted by Joshua Bayfield +gwiddle.co.uk + +// Thingdust AG : https://thingdust.com/ +// Submitted by Adrian Imboden +*.firenet.ch +*.svc.firenet.ch +reservd.com +thingdustdata.com +cust.dev.thingdust.io +cust.disrec.thingdust.io +cust.prod.thingdust.io +cust.testing.thingdust.io +reservd.dev.thingdust.io +reservd.disrec.thingdust.io +reservd.testing.thingdust.io + +// ticket i/O GmbH : https://ticket.io +// Submitted by Christian Franke +tickets.io + +// Tlon.io : https://tlon.io +// Submitted by Mark Staarink +arvo.network +azimuth.network +tlon.network + +// Tor Project, Inc. : https://torproject.org +// Submitted by Antoine Beaupré +bloxcms.com +townnews-staging.com + +// TradableBits: https://tradablebits.com +// Submitted by Dmitry Khrisanov dmitry@tradablebits.com +tbits.me + +// TrafficPlex GmbH : https://www.trafficplex.de/ +// Submitted by Phillipp Röll +12hp.at +2ix.at +4lima.at +lima-city.at +12hp.ch +2ix.ch +4lima.ch +lima-city.ch +trafficplex.cloud +de.cool +12hp.de +2ix.de +4lima.de +lima-city.de +1337.pictures +clan.rip +lima-city.rocks +webspace.rocks +lima.zone + +// TransIP : https://www.transip.nl +// Submitted by Rory Breuk +*.transurl.be +*.transurl.eu +*.transurl.nl + +// TuxFamily : http://tuxfamily.org +// Submitted by TuxFamily administrators +tuxfamily.org + +// TwoDNS : https://www.twodns.de/ +// Submitted by TwoDNS-Support +dd-dns.de +diskstation.eu +diskstation.org +dray-dns.de +draydns.de +dyn-vpn.de +dynvpn.de +mein-vigor.de +my-vigor.de +my-wan.de +syno-ds.de +synology-diskstation.de +synology-ds.de + +// Typeform : https://www.typeform.com +// Submitted by Sergi Ferriz +pro.typeform.com + +// Uberspace : https://uberspace.de +// Submitted by Moritz Werner +uber.space +*.uberspace.de + // UDR Limited : http://www.udr.hk.com // Submitted by registry hk.com @@ -11336,13 +13616,230 @@ hk.org ltd.hk inc.hk +// United Gameserver GmbH : https://united-gameserver.de +// Submitted by Stefan Schwarz +virtualuser.de +virtual-user.de + +// Upli : https://upli.io +// Submitted by Lenny Bakkalian +upli.io + +// urown.net : https://urown.net +// Submitted by Hostmaster +urown.cloud +dnsupdate.info + +// .US +// Submitted by Ed Moore +lib.de.us + +// VeryPositive SIA : http://very.lv +// Submitted by Danko Aleksejevs +2038.io + +// Vercel, Inc : https://vercel.com/ +// Submitted by Connor Davis +vercel.app +vercel.dev +now.sh + +// Viprinet Europe GmbH : http://www.viprinet.com +// Submitted by Simon Kissel +router.management + +// Virtual-Info : https://www.virtual-info.info/ +// Submitted by Adnan RIHAN +v-info.info + +// Voorloper.com: https://voorloper.com +// Submitted by Nathan van Bakel +voorloper.cloud + +// Voxel.sh DNS : https://voxel.sh/dns/ +// Submitted by Mia Rehlinger +neko.am +nyaa.am +be.ax +cat.ax +es.ax +eu.ax +gg.ax +mc.ax +us.ax +xy.ax +nl.ci +xx.gl +app.gp +blog.gt +de.gt +to.gt +be.gy +cc.hn +blog.kg +io.kg +jp.kg +tv.kg +uk.kg +us.kg +de.ls +at.md +de.md +jp.md +to.md +indie.porn +vxl.sh +ch.tc +me.tc +we.tc +nyan.to +at.vg +blog.vu +dev.vu +me.vu + +// V.UA Domain Administrator : https://domain.v.ua/ +// Submitted by Serhii Rostilo +v.ua + +// Vultr Objects : https://www.vultr.com/products/object-storage/ +// Submitted by Niels Maumenee +*.vultrobjects.com + +// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com +// Submitted by Masayuki Note +wafflecell.com + +// WapBlog.ID : https://www.wapblog.id +// Submitted by Fajar Sodik +idnblogger.com +indowapblog.com +bloger.id +wblog.id +wbq.me +fastblog.net + +// WebHare bv: https://www.webhare.com/ +// Submitted by Arnold Hendriks +*.webhare.dev + +// WebHotelier Technologies Ltd: https://www.webhotelier.net/ +// Submitted by Apostolos Tsakpinis +reserve-online.net +reserve-online.com +bookonline.app +hotelwithflight.com + +// WeDeploy by Liferay, Inc. : https://www.wedeploy.com +// Submitted by Henrique Vicente +wedeploy.io +wedeploy.me +wedeploy.sh + +// Western Digital Technologies, Inc : https://www.wdc.com +// Submitted by Jung Jin +remotewd.com + +// WIARD Enterprises : https://wiardweb.com +// Submitted by Kidd Hustle +pages.wiardweb.com + +// Wikimedia Labs : https://wikitech.wikimedia.org +// Submitted by Arturo Borrero Gonzalez +wmflabs.org +toolforge.org +wmcloud.org + +// WISP : https://wisp.gg +// Submitted by Stepan Fedotov +panel.gg +daemon.panel.gg + +// WoltLab GmbH : https://www.woltlab.com +// Submitted by Tim Düsterhus +woltlab-demo.com +myforum.community +community-pro.de +diskussionsbereich.de +community-pro.net +meinforum.net + +// Woods Valldata : https://www.woodsvalldata.co.uk/ +// Submitted by Chris Whittle +affinitylottery.org.uk +raffleentry.org.uk +weeklylottery.org.uk + +// WP Engine : https://wpengine.com/ +// Submitted by Michael Smith +// Submitted by Brandon DuRette +wpenginepowered.com +js.wpenginepowered.com + +// Wix.com, Inc. : https://www.wix.com +// Submitted by Shahar Talmi +wixsite.com +editorx.io + +// XenonCloud GbR: https://xenoncloud.net +// Submitted by Julian Uphoff +half.host + +// XnBay Technology : http://www.xnbay.com/ +// Submitted by XnBay Developer +xnbay.com +u2.xnbay.com +u2-local.xnbay.com + +// XS4ALL Internet bv : https://www.xs4all.nl/ +// Submitted by Daniel Mostertman +cistron.nl +demon.nl +xs4all.space + +// Yandex.Cloud LLC: https://cloud.yandex.com +// Submitted by Alexander Lodin +yandexcloud.net +storage.yandexcloud.net +website.yandexcloud.net + +// YesCourse Pty Ltd : https://yescourse.com +// Submitted by Atul Bhouraskar +official.academy + // Yola : https://www.yola.com/ // Submitted by Stefano Rivera yolasite.com +// Yombo : https://yombo.net +// Submitted by Mitch Schwenk +ybo.faith +yombo.me +homelink.one +ybo.party +ybo.review +ybo.science +ybo.trade + +// Yunohost : https://yunohost.org +// Submitted by Valentin Grimaud +ynh.fr +nohost.me +noho.st + // ZaNiC : http://www.za.net/ // Submitted by registry za.net za.org +// Zine EOOD : https://zine.bg/ +// Submitted by Martin Angelov +bss.design + +// Zitcom A/S : https://www.zitcom.dk +// Submitted by Emil Stahl +basicserver.io +virtualserver.io +enterprisecloud.nu + // ===END PRIVATE DOMAINS=== diff --git a/test_data/root_zones.dat b/test_data/root_zones.dat new file mode 100644 index 00000000..f5049fa1 --- /dev/null +++ b/test_data/root_zones.dat @@ -0,0 +1,16 @@ +# Version 2018082200, Last Updated Wed Aug 22 07:07:01 2018 UTC +AAA +AARP +ABARTH +ABB +ABBOTT +ABBVIE +ABC +ABLE +ABOGADO +ABUDHABI +AC +ACADEMY +ACCENTURE +ACCOUNTANT +ACCOUNTANTS \ No newline at end of file diff --git a/test_data/tlds-alpha-by-domain.txt b/test_data/tlds-alpha-by-domain.txt new file mode 100644 index 00000000..cd839403 --- /dev/null +++ b/test_data/tlds-alpha-by-domain.txt @@ -0,0 +1,1541 @@ +# Version 2018082300, Last Updated Thu Aug 23 07:07:01 2018 UTC +AAA +AARP +ABARTH +ABB +ABBOTT +ABBVIE +ABC +ABLE +ABOGADO +ABUDHABI +AC +ACADEMY +ACCENTURE +ACCOUNTANT +ACCOUNTANTS +ACO +ACTIVE +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 +BLANCO +BLOCKBUSTER +BLOG +BLOOMBERG +BLUE +BM +BMS +BMW +BN +BNL +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 +CARTIER +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 +CHRYSLER +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 +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 +DODGE +DOG +DOHA +DOMAINS +DOT +DOWNLOAD +DRIVE +DTV +DUBAI +DUCK +DUNLOP +DUNS +DUPONT +DURBAN +DVAG +DVR +DZ +EARTH +EAT +EC +ECO +EDEKA +EDU +EDUCATION +EE +EG +EMAIL +EMERCK +ENERGY +ENGINEER +ENGINEERING +ENTERPRISES +EPOST +EPSON +EQUIPMENT +ER +ERICSSON +ERNI +ES +ESQ +ESTATE +ESURANCE +ET +ETISALAT +EU +EUROVISION +EUS +EVENTS +EVERBANK +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 +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 +GOODHANDS +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 +HONEYWELL +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 +ISELECT +ISMAILI +IST +ISTANBUL +IT +ITAU +ITV +IVECO +JAGUAR +JAVA +JCB +JCP +JE +JEEP +JETZT +JEWELRY +JIO +JLC +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 +LADBROKES +LAMBORGHINI +LAMER +LANCASTER +LANCIA +LANCOME +LAND +LANDROVER +LANXESS +LASALLE +LAT +LATINO +LATROBE +LAW +LAWYER +LB +LC +LDS +LEASE +LECLERC +LEFRAK +LEGAL +LEGO +LEXUS +LGBT +LI +LIAISON +LIDL +LIFE +LIFEINSURANCE +LIFESTYLE +LIGHTING +LIKE +LILLY +LIMITED +LIMO +LINCOLN +LINDE +LINK +LIPSY +LIVE +LIVING +LIXIL +LK +LLC +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 +MOBILY +MODA +MOE +MOI +MOM +MONASH +MONEY +MONSTER +MOPAR +MORMON +MORTGAGE +MOSCOW +MOTO +MOTORCYCLES +MOV +MOVIE +MOVISTAR +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 +PANERAI +PARIS +PARS +PARTNERS +PARTS +PARTY +PASSAGENS +PAY +PCCW +PE +PET +PF +PFIZER +PG +PH +PHARMACY +PHD +PHILIPS +PHONE +PHOTO +PHOTOGRAPHY +PHOTOS +PHYSIO +PIAGET +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 +SPIEGEL +SPORT +SPOT +SPREADBETTING +SR +SRL +SRT +ST +STADA +STAPLES +STAR +STARHUB +STATEBANK +STATEFARM +STATOIL +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 +TELEFONICA +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 +UCONNECT +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 +VISTA +VISTAPRINT +VIVA +VIVO +VLAANDEREN +VN +VODKA +VOLKSWAGEN +VOLVO +VOTE +VOTING +VOTO +VOYAGE +VU +VUELOS +WALES +WALMART +WALTER +WANG +WANGGOU +WARMAN +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--MGBAI9AZGQP6J +XN--MGBAYH7GPA +XN--MGBB9FBPOB +XN--MGBBH1A +XN--MGBBH1A71E +XN--MGBC0A9AZCG +XN--MGBCA7DZDO +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--Q9JYB4C +XN--QCKA1PMC +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 +ZIPPO +ZM +ZONE +ZUERICH +ZW diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 08520f06..00000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,9 +0,0 @@ -parser = new Parser(new PublicSuffixList($file)); - } - - protected function tearDown() - { - $this->parser = null; - } - - public function testPublicSuffixSpec() - { - // Test data from Rob Stradling at Comodo - // http://mxr.mozilla.org/mozilla-central/source/netwerk/test/unit/data/test_psl.txt?raw=1 - // Any copyright is dedicated to the Public Domain. - // http://creativecommons.org/publicdomain/zero/1.0/ - - // null input. - $this->checkPublicSuffix(null, null); - // Mixed case. - $this->checkPublicSuffix('COM', null); - $this->checkPublicSuffix('example.COM', 'example.com'); - $this->checkPublicSuffix('WwW.example.COM', 'example.com'); - // Leading dot. - $this->checkPublicSuffix('.com', null); - $this->checkPublicSuffix('.example', null); - $this->checkPublicSuffix('.example.com', null); - $this->checkPublicSuffix('.example.example', null); - // Unlisted TLD. - // Addresses algorithm rule #2: If no rules match, the prevailing rule is "*". - $this->checkPublicSuffix('example', null); - $this->checkPublicSuffix('example.example', 'example.example'); - $this->checkPublicSuffix('b.example.example', 'example.example'); - $this->checkPublicSuffix('a.b.example.example', 'example.example'); - // TLD with only 1 rule. - $this->checkPublicSuffix('biz', null); - $this->checkPublicSuffix('domain.biz', 'domain.biz'); - $this->checkPublicSuffix('b.domain.biz', 'domain.biz'); - $this->checkPublicSuffix('a.b.domain.biz', 'domain.biz'); - // TLD with some 2-level rules. - $this->checkPublicSuffix('com', null); - $this->checkPublicSuffix('example.com', 'example.com'); - $this->checkPublicSuffix('b.example.com', 'example.com'); - $this->checkPublicSuffix('a.b.example.com', 'example.com'); - $this->checkPublicSuffix('uk.com', null); - $this->checkPublicSuffix('example.uk.com', 'example.uk.com'); - $this->checkPublicSuffix('b.example.uk.com', 'example.uk.com'); - $this->checkPublicSuffix('a.b.example.uk.com', 'example.uk.com'); - $this->checkPublicSuffix('test.ac', 'test.ac'); - // TLD with only 1 (wildcard) rule. - $this->checkPublicSuffix('mm', null); - $this->checkPublicSuffix('c.mm', null); - $this->checkPublicSuffix('b.c.mm', 'b.c.mm'); - $this->checkPublicSuffix('a.b.c.mm', 'b.c.mm'); - // More complex TLD. - $this->checkPublicSuffix('jp', null); - $this->checkPublicSuffix('test.jp', 'test.jp'); - $this->checkPublicSuffix('www.test.jp', 'test.jp'); - $this->checkPublicSuffix('ac.jp', null); - $this->checkPublicSuffix('test.ac.jp', 'test.ac.jp'); - $this->checkPublicSuffix('www.test.ac.jp', 'test.ac.jp'); - $this->checkPublicSuffix('kyoto.jp', null); - $this->checkPublicSuffix('test.kyoto.jp', 'test.kyoto.jp'); - $this->checkPublicSuffix('ide.kyoto.jp', null); - $this->checkPublicSuffix('b.ide.kyoto.jp', 'b.ide.kyoto.jp'); - $this->checkPublicSuffix('a.b.ide.kyoto.jp', 'b.ide.kyoto.jp'); - $this->checkPublicSuffix('c.kobe.jp', null); - $this->checkPublicSuffix('b.c.kobe.jp', 'b.c.kobe.jp'); - $this->checkPublicSuffix('a.b.c.kobe.jp', 'b.c.kobe.jp'); - $this->checkPublicSuffix('city.kobe.jp', 'city.kobe.jp'); - $this->checkPublicSuffix('www.city.kobe.jp', 'city.kobe.jp'); - // TLD with a wildcard rule and exceptions. - $this->checkPublicSuffix('ck', null); - $this->checkPublicSuffix('test.ck', null); - $this->checkPublicSuffix('b.test.ck', 'b.test.ck'); - $this->checkPublicSuffix('a.b.test.ck', 'b.test.ck'); - $this->checkPublicSuffix('www.ck', 'www.ck'); - $this->checkPublicSuffix('www.www.ck', 'www.ck'); - // US K12. - $this->checkPublicSuffix('us', null); - $this->checkPublicSuffix('test.us', 'test.us'); - $this->checkPublicSuffix('www.test.us', 'test.us'); - $this->checkPublicSuffix('ak.us', null); - $this->checkPublicSuffix('test.ak.us', 'test.ak.us'); - $this->checkPublicSuffix('www.test.ak.us', 'test.ak.us'); - $this->checkPublicSuffix('k12.ak.us', null); - $this->checkPublicSuffix('test.k12.ak.us', 'test.k12.ak.us'); - $this->checkPublicSuffix('www.test.k12.ak.us', 'test.k12.ak.us'); - // IDN labels. - $this->checkPublicSuffix('食狮.com.cn', '食狮.com.cn'); - $this->checkPublicSuffix('食狮.公司.cn', '食狮.公司.cn'); - $this->checkPublicSuffix('www.食狮.公司.cn', '食狮.公司.cn'); - $this->checkPublicSuffix('shishi.公司.cn', 'shishi.公司.cn'); - $this->checkPublicSuffix('公司.cn', null); - $this->checkPublicSuffix('食狮.中国', '食狮.中国'); - $this->checkPublicSuffix('www.食狮.中国', '食狮.中国'); - $this->checkPublicSuffix('shishi.中国', 'shishi.中国'); - $this->checkPublicSuffix('中国', null); - // Same as above, but punycoded. - $this->checkPublicSuffix('xn--85x722f.com.cn', 'xn--85x722f.com.cn'); - $this->checkPublicSuffix('xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); - $this->checkPublicSuffix('www.xn--85x722f.xn--55qx5d.cn', 'xn--85x722f.xn--55qx5d.cn'); - $this->checkPublicSuffix('shishi.xn--55qx5d.cn', 'shishi.xn--55qx5d.cn'); - $this->checkPublicSuffix('xn--55qx5d.cn', null); - $this->checkPublicSuffix('xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); - $this->checkPublicSuffix('www.xn--85x722f.xn--fiqs8s', 'xn--85x722f.xn--fiqs8s'); - $this->checkPublicSuffix('shishi.xn--fiqs8s', 'shishi.xn--fiqs8s'); - $this->checkPublicSuffix('xn--fiqs8s', null); - } - - /** - * This is my version of the checkPublicSuffix function referred to in the - * test instructions at the Public Suffix List project. - * - * "You will need to define a checkPublicSuffix() function which takes as a - * parameter a domain name and the public suffix, runs your implementation - * on the domain name and checks the result is the public suffix expected." - * - * @link http://publicsuffix.org/list/ - * - * @param string $input Domain and public suffix - * @param string $expected Expected result - */ - public function checkPublicSuffix($input, $expected) - { - $this->assertSame($expected, $this->parser->getRegistrableDomain($input)); - } -} diff --git a/tests/src/Pdp/Exception/SeriouslyMalformedUrlExceptionTest.php b/tests/src/Pdp/Exception/SeriouslyMalformedUrlExceptionTest.php deleted file mode 100644 index 569a8806..00000000 --- a/tests/src/Pdp/Exception/SeriouslyMalformedUrlExceptionTest.php +++ /dev/null @@ -1,33 +0,0 @@ -assertInstanceOf( - 'Pdp\Exception\PdpException', - new SeriouslyMalformedUrlException() - ); - } - - public function testInstanceOfInvalidArgumentException() - { - $this->assertInstanceOf( - 'InvalidArgumentException', - new SeriouslyMalformedUrlException() - ); - } - - public function testMessage() - { - $url = 'http:///example.com'; - $this->setExpectedException( - 'Pdp\Exception\SeriouslyMalformedUrlException', - sprintf('"%s" is one seriously malformed url.', $url) - ); - - throw new SeriouslyMalformedUrlException($url); - } -} diff --git a/tests/src/Pdp/HttpAdapter/CurlHttpAdapterTest.php b/tests/src/Pdp/HttpAdapter/CurlHttpAdapterTest.php deleted file mode 100644 index fad2b634..00000000 --- a/tests/src/Pdp/HttpAdapter/CurlHttpAdapterTest.php +++ /dev/null @@ -1,35 +0,0 @@ -markTestSkipped('cURL has to be enabled.'); - } - - $this->adapter = new CurlHttpAdapter(); - } - - protected function tearDown() - { - $this->adapter = null; - } - - public function testGetContent() - { - $content = $this->adapter->getContent('http://www.google.com'); - $this->assertNotNull($content); - $this->assertContains('google', $content); - } -} diff --git a/tests/src/Pdp/ParserTest.php b/tests/src/Pdp/ParserTest.php deleted file mode 100644 index 5949c6f7..00000000 --- a/tests/src/Pdp/ParserTest.php +++ /dev/null @@ -1,308 +0,0 @@ -parser = new Parser( - new PublicSuffixList($file) - ); - } - - protected function tearDown() - { - $this->parser = null; - parent::tearDown(); - } - - /** - * @covers Pdp\Parser::isSuffixValid() - */ - public function testIsSuffixValidFalse() - { - $this->assertFalse($this->parser->isSuffixValid('www.example.faketld')); - $this->assertFalse($this->parser->isSuffixValid('example.example')); - } - - /** - * @covers Pdp\Parser::isSuffixValid() - */ - public function testIsSuffixValidTrue() - { - $this->assertTrue($this->parser->isSuffixValid('www.example.com')); - $this->assertTrue($this->parser->isSuffixValid('www.example.co.uk')); - $this->assertTrue($this->parser->isSuffixValid('www.example.рф')); - $this->assertTrue($this->parser->isSuffixValid('example.com.au')); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @covers ::pdp_parse_url - */ - public function testParseBadUrlThrowsInvalidArgumentException() - { - $url = 'http:///example.com'; - - $this->setExpectedException( - 'Pdp\Exception\SeriouslyMalformedUrlException', - sprintf('"%s" is one seriously malformed url.', $url) - ); - - $this->parser->parseUrl($url); - } - - /** - * If an empty string is passed to the parser then the hacky scheme from - * issue 49 should not appear in the Exception message. - * - * @group issue54 - * - * @see https://github.com/jeremykendall/php-domain-parser/issues/54 - * - * @covers Pdp\Parser::parseUrl() - * @covers ::pdp_parse_url - */ - public function testParseEmptyStringThrowsInvalidArgumentExceptionWithoutWackySchemeInMessage() - { - $this->setExpectedException( - 'Pdp\Exception\SeriouslyMalformedUrlException', - '"" is one seriously malformed url.' - ); - - $this->parser->parseUrl(''); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @dataProvider parseDataProvider - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testParseUrl($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $pdpUrl = $this->parser->parseUrl($url); - $this->assertInstanceOf('\Pdp\Uri\Url', $pdpUrl); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @covers Pdp\Parser::parseHost() - * @dataProvider parseDataProvider - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testParseHost($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $pdpUrl = $this->parser->parseUrl($url); - $this->assertEquals($hostPart, $pdpUrl->getHost()); - - $pdpHost = $this->parser->parseHost($hostPart); - $this->assertInstanceOf('\Pdp\Uri\Url\Host', $pdpHost); - $this->assertEquals($hostPart, $pdpHost->__toString()); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @covers Pdp\Parser::getPublicSuffix() - * @dataProvider parseDataProvider - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testGetPublicSuffix($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $pdpUrl = $this->parser->parseUrl($url); - $this->assertSame($publicSuffix, $pdpUrl->getHost()->getPublicSuffix()); - $this->assertSame($publicSuffix, $this->parser->getPublicSuffix($hostPart)); - } - - /** - * @covers Pdp\Parser::getPublicSuffix() - */ - public function testGetPublicSuffixHandlesWrongCaseProperly() - { - $publicSuffix = 'рф'; - $hostPart = 'Яндекс.РФ'; - - $this->assertSame($publicSuffix, $this->parser->getPublicSuffix($hostPart)); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @covers Pdp\Parser::getRegistrableDomain() - * @dataProvider parseDataProvider - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testGetRegistrableDomain($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $pdpUrl = $this->parser->parseUrl($url); - $this->assertSame($registrableDomain, $pdpUrl->getHost()->getRegistrableDomain()); - $this->assertSame($registrableDomain, $this->parser->getRegistrableDomain($hostPart)); - } - - /** - * @covers Pdp\Parser::parseUrl() - * @covers Pdp\Parser::getSubdomain() - * @dataProvider parseDataProvider - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testGetSubdomain($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $pdpUrl = $this->parser->parseUrl($url); - $this->assertSame($subdomain, $pdpUrl->getHost()->getSubdomain()); - $this->assertSame($subdomain, $this->parser->getSubdomain($hostPart)); - } - - /** - * @covers Pdp\Parser::getSubdomain() - */ - public function testGetSubdomainHandlesWrongCaseProperly() - { - $url = 'http://WWW.example.COM'; - $hostPart = 'WWW.example.com'; - $subdomain = 'www'; - $pdpUrl = $this->parser->parseUrl($url); - - $this->assertSame($subdomain, $pdpUrl->getHost()->getSubdomain()); - $this->assertSame($subdomain, $this->parser->getSubdomain($hostPart)); - } - - /** - * @dataProvider parseDataProvider - * @covers ::pdp_parse_url - * - * @param $url - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testpdp_parse_urlCanReturnCorrectHost($url, $publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $this->assertEquals( - $hostPart, - pdp_parse_url('http://' . $hostPart, PHP_URL_HOST) - ); - } - - /** - * @group issue46 - * @group issue49 - * - * Don't add a scheme to schemeless URLs - * - * @see https://github.com/jeremykendall/php-domain-parser/issues/46 - * @see https://github.com/jeremykendall/php-domain-parser/issues/49 - */ - public function testDoNotPrependSchemeToSchemelessUrls() - { - $schemeless = 'www.graphstory.com'; - $expected = 'www.graphstory.com'; - $url = $this->parser->parseUrl($schemeless); - $actual = $url->__toString(); - - $this->assertEquals($expected, $actual); - - $schemeless = '//www.graphstory.com'; - $expected = 'www.graphstory.com'; - $url = $this->parser->parseUrl($schemeless); - $actual = $url->__toString(); - - $this->assertEquals($expected, $actual); - } - - public function parseDataProvider() - { - return array( - // url, public suffix, registrable domain, subdomain, host part - array('http://www.waxaudio.com.au/audio/albums/the_mashening', 'com.au', 'waxaudio.com.au', 'www', 'www.waxaudio.com.au'), - array('example.COM', 'com', 'example.com', null, 'example.com'), - array('giant.yyyy', 'yyyy', 'giant.yyyy', null, 'giant.yyyy'), - array('cea-law.co.il', 'co.il', 'cea-law.co.il', null, 'cea-law.co.il'), - array('http://edition.cnn.com/WORLD/', 'com', 'cnn.com', 'edition', 'edition.cnn.com'), - array('http://en.wikipedia.org/', 'org', 'wikipedia.org', 'en', 'en.wikipedia.org'), - array('a.b.c.mm', 'c.mm', 'b.c.mm', 'a', 'a.b.c.mm'), - array('https://test.k12.ak.us', 'k12.ak.us', 'test.k12.ak.us', null, 'test.k12.ak.us'), - array('www.scottwills.co.uk', 'co.uk', 'scottwills.co.uk', 'www', 'www.scottwills.co.uk'), - array('b.ide.kyoto.jp', 'ide.kyoto.jp', 'b.ide.kyoto.jp', null, 'b.ide.kyoto.jp'), - array('a.b.example.uk.com', 'uk.com', 'example.uk.com', 'a.b', 'a.b.example.uk.com'), - array('test.nic.ar', 'ar', 'nic.ar', 'test', 'test.nic.ar'), - array('a.b.test.ck', 'test.ck', 'b.test.ck', 'a', 'a.b.test.ck'), - array('baez.songfest.om', 'om', 'songfest.om', 'baez', 'baez.songfest.om'), - array('politics.news.omanpost.om', 'om', 'omanpost.om', 'politics.news', 'politics.news.omanpost.om'), - // BEGIN https://github.com/jeremykendall/php-domain-parser/issues/16 - array('us.example.com', 'com', 'example.com', 'us', 'us.example.com'), - array('us.example.na', 'na', 'example.na', 'us', 'us.example.na'), - array('www.example.us.na', 'us.na', 'example.us.na', 'www', 'www.example.us.na'), - array('us.example.org', 'org', 'example.org', 'us', 'us.example.org'), - array('webhop.broken.biz', 'biz', 'broken.biz', 'webhop', 'webhop.broken.biz'), - array('www.broken.webhop.biz', 'webhop.biz', 'broken.webhop.biz', 'www', 'www.broken.webhop.biz'), - // END https://github.com/jeremykendall/php-domain-parser/issues/16 - // Test schemeless url - array('//www.broken.webhop.biz', 'webhop.biz', 'broken.webhop.biz', 'www', 'www.broken.webhop.biz'), - // Test ftp support - https://github.com/jeremykendall/php-domain-parser/issues/18 - array('ftp://www.waxaudio.com.au/audio/albums/the_mashening', 'com.au', 'waxaudio.com.au', 'www', 'www.waxaudio.com.au'), - array('ftps://test.k12.ak.us', 'k12.ak.us', 'test.k12.ak.us', null, 'test.k12.ak.us'), - // Test support for RFC 3986 compliant schemes - // https://github.com/jeremykendall/php-domain-parser/issues/46 - array('fake-scheme+RFC-3986.compliant://example.com', 'com', 'example.com', null, 'example.com'), - array('http://localhost', null, null, null, 'localhost'), - array('test.museum', 'museum', 'test.museum', null, 'test.museum'), - array('bob.smith.name', 'name', 'smith.name', 'bob', 'bob.smith.name'), - array('tons.of.info', 'info', 'of.info', 'tons', 'tons.of.info'), - // Test IDN parsing - // BEGIN https://github.com/jeremykendall/php-domain-parser/issues/29 - array('http://Яндекс.РФ', 'рф', 'яндекс.рф', null, 'яндекс.рф'), - // END https://github.com/jeremykendall/php-domain-parser/issues/29 - array('www.食狮.中国', '中国', '食狮.中国', 'www', 'www.食狮.中国'), - array('食狮.com.cn', 'com.cn', '食狮.com.cn', null, '食狮.com.cn'), - // Test punycode URLs - array('www.xn--85x722f.xn--fiqs8s', 'xn--fiqs8s', 'xn--85x722f.xn--fiqs8s', 'www', 'www.xn--85x722f.xn--fiqs8s'), - array('xn--85x722f.com.cn', 'com.cn', 'xn--85x722f.com.cn', null, 'xn--85x722f.com.cn'), - // Test ipv6 URL - array('http://[::1]/', null, null, null, '[::1]'), - array('http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/', null, null, null, '[2001:db8:85a3:8d3:1319:8a2e:370:7348]'), - array('https://[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443/', null, null, null, '[2001:db8:85a3:8d3:1319:8a2e:370:7348]'), - // Test IP address: Fixes #43 - array('http://192.168.1.2/', null, null, null, '192.168.1.2'), - array('http://127.0.0.1:443', null, null, null, '127.0.0.1'), - array('http://67.196.2.34/whois-archive/latest.php?page=2479', null, null, null, '67.196.2.34'), - // Link-local addresses and zone indices - array('http://[fe80::3%25eth0]', null, null, null, '[fe80::3%25eth0]'), - array('http://[fe80::1%2511]', null, null, null, '[fe80::1%2511]'), - array('http://www.example.dev', 'dev', 'example.dev', 'www', 'www.example.dev'), - array('http://example.faketld', 'faketld', 'example.faketld', null, 'example.faketld'), - // url, public suffix, registrable domain, subdomain, host part - ); - } -} diff --git a/tests/src/Pdp/PublicSuffixListManagerTest.php b/tests/src/Pdp/PublicSuffixListManagerTest.php deleted file mode 100644 index cd46102b..00000000 --- a/tests/src/Pdp/PublicSuffixListManagerTest.php +++ /dev/null @@ -1,217 +0,0 @@ -dataDir = realpath(dirname(__DIR__) . '/../../data'); - - $this->root = vfsStream::setup('pdp'); - vfsStream::create(array('cache' => array()), $this->root); - $this->cacheDir = vfsStream::url('pdp/cache'); - - $this->listManager = new PublicSuffixListManager($this->cacheDir); - - $this->httpAdapter = $this->getMock('\Pdp\HttpAdapter\HttpAdapterInterface'); - $this->listManager->setHttpAdapter($this->httpAdapter); - } - - protected function tearDown() - { - $this->cacheDir = null; - $this->root = null; - $this->httpAdapter = null; - $this->listManager = null; - - parent::tearDown(); - } - - public function testRefreshPublicSuffixList() - { - $content = file_get_contents( - $this->dataDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - - $this->httpAdapter->expects($this->once()) - ->method('getContent') - ->with($this->publicSuffixListUrl) - ->will($this->returnValue($content)); - - $this->assertFileNotExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - $this->assertFileNotExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - - $this->listManager->refreshPublicSuffixList(); - - $this->assertFileExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - $this->assertFileExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - } - - public function testFetchListFromSource() - { - $content = file_get_contents( - $this->dataDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - - $this->httpAdapter->expects($this->once()) - ->method('getContent') - ->with($this->publicSuffixListUrl) - ->will($this->returnValue($content)); - - $publicSuffixList = $this->listManager->fetchListFromSource(); - $this->assertGreaterThanOrEqual(100000, $publicSuffixList); - } - - public function testGetHttpAdapterReturnsDefaultCurlAdapterIfAdapterNotSet() - { - $listManager = new PublicSuffixListManager($this->cacheDir); - $this->assertInstanceOf( - '\Pdp\HttpAdapter\CurlHttpAdapter', - $listManager->getHttpAdapter() - ); - } - - public function testWritePhpCache() - { - $this->assertFileNotExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - $array = $this->listManager->parseListToArray( - $this->dataDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - $this->assertGreaterThanOrEqual(230000, $this->listManager->writePhpCache($array)); - $this->assertFileExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - $publicSuffixList = include $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE; - $this->assertInternalType('array', $publicSuffixList); - $this->assertGreaterThanOrEqual(300, count($publicSuffixList)); - $this->assertTrue(array_key_exists('stuff-4-sale', $publicSuffixList['org']) !== false); - $this->assertTrue(array_key_exists('net', $publicSuffixList['ac']) !== false); - } - - public function testWriteThrowsExceptionIfCanNotWrite() - { - $this->setExpectedException('\Exception', "Cannot write '/does/not/exist/public-suffix-list.php'"); - $manager = new PublicSuffixListManager('/does/not/exist'); - $manager->writePhpCache(array()); - } - - public function testParseListToArray() - { - $publicSuffixList = $this->listManager->parseListToArray( - $this->dataDir . '/' . PublicSuffixListManager::PDP_PSL_TEXT_FILE - ); - $this->assertInternalType('array', $publicSuffixList); - } - - public function testGetList() - { - copy( - $this->dataDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE, - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - $this->assertFileExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - $publicSuffixList = $this->listManager->getList(); - $this->assertInstanceOf('\Pdp\PublicSuffixList', $publicSuffixList); - $this->assertGreaterThanOrEqual(300, count($publicSuffixList)); - $this->assertTrue(array_key_exists('stuff-4-sale', $publicSuffixList['org']) !== false); - $this->assertTrue(array_key_exists('net', $publicSuffixList['ac']) !== false); - } - - public function testGetListWithoutCache() - { - $this->assertFileNotExists( - $this->cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - - /** @var PublicSuffixListManager $listManager */ - $listManager = $this->getMock( - '\Pdp\PublicSuffixListManager', - array('refreshPublicSuffixList'), - array($this->cacheDir) - ); - - $dataDir = $this->dataDir; - $cacheDir = $this->cacheDir; - - $listManager->expects($this->once()) - ->method('refreshPublicSuffixList') - ->will($this->returnCallback(function () use ($dataDir, $cacheDir) { - copy( - $dataDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE, - $cacheDir . '/' . PublicSuffixListManager::PDP_PSL_PHP_FILE - ); - })); - - $publicSuffixList = $listManager->getList(); - $this->assertInstanceOf('\Pdp\PublicSuffixList', $publicSuffixList); - } - - public function testGetProvidedListFromDefaultCacheDir() - { - // By not providing cache I'm forcing use of default cache dir - $listManager = new PublicSuffixListManager(); - $publicSuffixList = $listManager->getList(); - $this->assertInstanceOf('\Pdp\PublicSuffixList', $publicSuffixList); - $this->assertGreaterThanOrEqual(300, count($publicSuffixList)); - $this->assertTrue(array_key_exists('stuff-4-sale', $publicSuffixList['org']) !== false); - $this->assertTrue(array_key_exists('net', $publicSuffixList['ac']) !== false); - } -} diff --git a/tests/src/Pdp/Uri/Url/HostTest.php b/tests/src/Pdp/Uri/Url/HostTest.php deleted file mode 100644 index f2df8ea2..00000000 --- a/tests/src/Pdp/Uri/Url/HostTest.php +++ /dev/null @@ -1,77 +0,0 @@ -assertEquals($hostPart, $host->__toString()); - } - - public function test__toStringWhenHostPartIsNull() - { - $host = new Host( - 'www', - 'example.com', - 'com' - ); - - $this->assertEquals('www.example.com', $host->__toString()); - } - - /** - * @dataProvider hostDataProvider - * - * @param $publicSuffix - * @param $registrableDomain - * @param $subdomain - * @param $hostPart - */ - public function testToArray($publicSuffix, $registrableDomain, $subdomain, $hostPart) - { - $parts = array( - 'subdomain' => $subdomain, - 'registrableDomain' => $registrableDomain, - 'publicSuffix' => $publicSuffix, - 'host' => $hostPart, - ); - - $host = new Host( - $parts['subdomain'], - $parts['registrableDomain'], - $parts['publicSuffix'], - $parts['host'] - ); - - $this->assertEquals($parts, $host->toArray()); - } - - public function hostDataProvider() - { - // $publicSuffix, $registrableDomain, $subdomain, $hostPart - return array( - array('com.au', 'waxaudio.com.au', 'www', 'www.waxaudio.com.au'), - array('com', 'example.com', null, 'example.com'), - array('com', 'cnn.com', 'edition', 'edition.cnn.com'), - array('org', 'wikipedia.org', 'en', 'en.wikipedia.org'), - array('uk.com', 'example.uk.com', 'a.b', 'a.b.example.uk.com'), - array(null, null, null, 'localhost'), - ); - } -} diff --git a/tests/src/Pdp/Uri/UrlTest.php b/tests/src/Pdp/Uri/UrlTest.php deleted file mode 100644 index 8e48cf10..00000000 --- a/tests/src/Pdp/Uri/UrlTest.php +++ /dev/null @@ -1,175 +0,0 @@ -parser = new Parser($psl); - $this->url = $this->parser->parseUrl($this->spec); - } - - protected function tearDown() - { - parent::tearDown(); - } - - public function test__construct() - { - $url = new Url( - 'http', - 'anonymous', - 'guest', - new Host( - null, - 'example.com', - 'com' - ), - null, - '/path/to/index.php/foo/bar.xml', - 'baz=dib', - 'anchor' - ); - - $this->assertInstanceOf('Pdp\Uri\Url', $url); - } - - public function test__toString() - { - $this->assertEquals($this->spec, $this->url->__toString()); - } - - public function testGetSchemeless() - { - $schemeless = substr_replace($this->spec, '', 0, 5); - $this->assertEquals($schemeless, $this->url->getSchemeless()); - } - - public function testToArray() - { - $expected = array( - 'scheme' => 'http', - 'user' => 'anonymous', - 'pass' => 'guest', - 'host' => 'example.com', - 'subdomain' => null, - 'registrableDomain' => 'example.com', - 'publicSuffix' => 'com', - 'port' => 8080, - 'path' => '/path/to/index.php/foo/bar.xml', - 'query' => 'baz=dib', - 'fragment' => 'anchor', - ); - - $this->assertEquals($expected, $this->url->toArray()); - } - - /** - * @group issue18 - * - * @see https://github.com/jeremykendall/php-domain-parser/issues/18 - */ - public function testFtpUrlToString() - { - $ftpUrl = 'ftp://ftp.somewhere.com'; - $url = $this->parser->parseUrl($ftpUrl); - $this->assertEquals($ftpUrl, $url->__toString()); - } - - /** - * This test fixes #29. It has been updated due to a change suggested in #46. - * The original $expected value was 'http://яндекс.рф', as parsing would add - * 'http://' to URLs that did not have a scheme. That behavior has been removed. - * The new $expected result is 'яндекс.рф'. - * - * @group issue29 - * @group issue46 - * - * @see https://github.com/jeremykendall/php-domain-parser/issues/29 - * @see https://github.com/jeremykendall/php-domain-parser/issues/46 - */ - public function testIdnToAscii() - { - $idn = 'Яндекс.РФ'; - $expected = 'яндекс.рф'; - $url = $this->parser->parseUrl($idn); - $actual = $url->__toString(); - - $this->assertEquals($expected, $actual); - } - - /** - * Scheme should not be URL encoded. - * - * @group issue46 - * @group issue51 - * - * @see https://tools.ietf.org/html/rfc3986#section-3.1 - */ - public function test__toStringDoesNotUrlEncodeScheme() - { - // The '+' should not be URL encoded when output to string - $spec = 'fake-scheme+RFC-3986.compliant://www.graphstory.com'; - $expected = 'fake-scheme+rfc-3986.compliant://www.graphstory.com'; - $url = $this->parser->parseUrl($spec); - $this->assertEquals($expected, $url->__toString()); - } - - /** - * Scheme should be output in lowercase regardless of case of original arg. - * - * @group issue51 - * - * @see https://tools.ietf.org/html/rfc3986#section-3.1 - */ - public function testSchemeAlwaysConvertedToLowerCasePerRFC3986() - { - $spec = 'HttPS://www.google.com'; - $expected = 'https://www.google.com'; - $url = $this->parser->parseUrl($spec); - $this->assertEquals($expected, $url->__toString()); - } - - /** - * Scheme should return null when scheme is not provided. - * - * @group issue53 - * - * @see https://github.com/jeremykendall/php-domain-parser/issues/53 - */ - public function testSchemeReturnsNullIfNotProvidedToParser() - { - $spec = 'google.com'; - $url = $this->parser->parseUrl($spec); - $this->assertNull($url->getScheme()); - } -}