Download the PHP package edulazaro/laradomains without Composer

On this page you can find all versions of the php package edulazaro/laradomains. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laradomains

Laradomains

Tests Latest Stable Version PHP Version License

Everything you can learn about a domain without visiting it: parsing with the Public Suffix List, registration data over RDAP, age, DNS over HTTPS and malware or adult screening. Every answer comes from a third party (the registry, a DNS resolver, the Wayback Machine), never from the domain itself, which matters when the domain was typed by a stranger and may be hostile.

Installation

Requires PHP 8.4+ with the intl extension and Laravel 12 or newer. Optionally publish the config:

Parsing

Domain::parse() takes what people paste and keeps the host, lower-cased, in both spellings:

The registrable domain follows the Public Suffix List, not a guess at "the last two labels", so gob.es, com.mx and wildcard rules are handled. Suffixes run by hosting platforms are opt-in:

www is kept, since it is a host of its own; withoutWww() drops it when you treat both as one site.

The host is read the way a browser reads it, which is what matters when deciding where a link really goes: a backslash ends the host as a slash does, so https://evil.example\@paypal.com/login is evil.example, not PayPal, and a web scheme without slashes (http:evil.example) still names its host.

Lookalikes

skeleton() gives the Latin reading of a name. imitates() checks it against the brands you care about, as a copy of the whole name (0/o and 1/l swaps included); impersonates() adds the usual phishing shapes, the brand as a label or a hyphenated part of someone else's domain:

typosquats() catches the typing slips: a letter added (paypall.com), dropped (payal.com), swapped with its neighbour (paypla.com), a lookalike letter (goog1e.com) or two letters that read as one (arnazon.com). Any other replaced letter does not count, since paypay.com is a real company one letter from PayPal, and brand names under five letters are skipped:

The kinds of slip do not weigh the same, and typosquat() says which one it was. A lookalike letter or a pair read as one (goog1e, arnazon) is rarely an accident; letters swapped (paypla) is a medium sign; a letter added or dropped (paypall, payal) is the weakest, and where ordinary words land, since no code knows without a dictionary that apples is a word:

Brand names under four letters only match impersonates() as full copies, since bbc or x turn up inside ordinary names. A brand that is also a common word will still match ordinary sites (apple.com matches apple-pie-recipes.com), so treat impersonates() as a reason to review a link, not to block it; imitates(), a copy of the whole name, is the stronger signal.

Keeping the lists current

The package ships a copy of the Public Suffix List and of the IANA RDAP bootstrap, so it works with no download and no cache. laradomains:update fetches fresh copies to storage/app/laradomains/, which win over the bundled ones, and compiles the suffix list to a PHP array that opcache keeps in memory. Schedule it monthly:

A download that does not look like the real list is discarded and the current copy kept.

Registration data (RDAP)

RDAP is the protocol that replaced WHOIS. There is no central database: each registry runs its own server, and IANA publishes which one serves each TLD. Laradomains reads that bootstrap from disk and asks the registry directly, for the registrable domain, so a lookup is a single request:

Three outcomes are kept apart, because a caller handles each one differently:

Meaning
supported === false The TLD has no RDAP service (.es, .de, .io and others).
registered === false The registry answered that nobody holds the name.
failed() The lookup did not complete; error says why. The only one worth retrying.

TLDs missing from the IANA bootstrap are sent to a relay, rdap.org by default. Set LARADOMAINS_RDAP_FALLBACK= empty to never use one.

Age

age() returns null both when there is no date to give and when a lookup failed. ageCheck() takes the same arguments and tells them apart:

Status Reason Meaning
found A date. failed may still list sources that did not answer.
none unsupported_tld The TLD's registry publishes no RDAP, and no fallback was asked for.
none not_registered The registry has no data for that name (an RDAP 404). Some registries implement RDAP badly, so this is not proof that the name is free.
none no_registration_date The registry answered, without a registration date.
none no_certificates, no_captures The fallbacks answered, with nothing. With both asked, the reason is the last one asked (no_captures).
unknown lookup_failed A source did not answer and none found a date. Worth asking again later.

Any date is found, even when another source failed: when RDAP is down and crt.sh answers, the result is a date from certificates with failed: ["rdap"]. A date from certificates or the Wayback Machine is a lower bound, so check failed before reading it as "registered on". The fallbacks are only asked when RDAP gives no date, so an empty failed with source rdap means nobody else needed asking, not that everyone was asked.

Several registries (.es, .de, .io, .it) publish no RDAP, so their domains have no registration date. Two lower bounds stand in for it, both opt-in, and with both asked the earliest date wins:

The Wayback fallback is off by default: its CDX server allows about a dozen requests a minute, which suits a queued job and not a request path. A refused request waits wayback.retry_delay milliseconds (5000 by default) before each of wayback.retries retries. A first capture is a lower bound, not a registration date.

To remember ages, set LARADOMAINS_AGE_CACHE_FOR to a number of seconds. Age belongs to the registrable domain, so a.spam.io and b.spam.io share one entry, and the whole check is kept (status, reason and failed sources). Complete answers (found or none with every source answering) are kept for cache_for; unknown, and found with a failed source, for age.retry_after seconds (300 by default), so a spam campaign repeating the same new domain costs one registry request, not one per message. Nothing is cached in an array or null store, which would not survive the request; LARADOMAINS_CACHE_STORE picks another store.

DNS

Over HTTPS by default (LARADOMAINS_DNS_DRIVER=doh), so answers do not depend on the resolver of the machine; system uses dns_get_record().

acceptsMail() decides the way a mail server does (RFC 5321 §5.1): an MX host accepts mail; a null MX (0 ., RFC 7505) refuses it; with no MX at all, mail goes to the domain's own A or AAAA address, and a domain with neither (or that does not exist) refuses it. When a lookup fails (timeout, HTTP error, SERVFAIL) the answer is null, never false: a disposable-address check must not reject a real domain because a resolver hiccuped. The other methods describe rather than decide, so a failed lookup there is an empty list.

Screening

Cloudflare's filtering resolvers answer 0.0.0.0 for names they block. Laradomains asks them over DNS, so nothing reaches the domain:

Both resolvers are asked in parallel, so the wait is the slower of the two. It fails closed: when a resolver cannot be asked (timeout, HTTP error, SERVFAIL) the answer is Screen::UNKNOWN, never CLEAN. "Could not look" and "found nothing" are different answers, and what UNKNOWN means (let through, hold for review, retry later) is the caller's decision. A name that does not exist (NXDOMAIN) is an answer, and clean.

Domains::verdict() keeps the two answers apart, so one resolver failing does not hide what the other settled:

The family resolver blocks malware as well as adult content, so its block alone means "malware or adult": decision() says adult only when the malware resolver has cleared the domain, and unknown otherwise. blocked() is true as soon as any resolver blocked it, for a caller that only needs to know whether to stop the link. Screen::isMalware() asks only the malware resolver and answers true, false, or null when it could not check.

To cache verdicts per host, set LARADOMAINS_SCREEN_CACHE_FOR in seconds: complete verdicts are kept that long, incomplete ones for screen.retry_after (60 by default), in a persistent store.

The adult category is broad (it also catches piracy, cannabis shops and the odd false positive): treat it as a flag for review rather than as proof.

Timeouts and retries

Each service has its own timeout and retries, so a request path is not held by the slowest one:

Every network call also takes its own timeout (seconds) and retries (tries after the first; null takes the config, 0 makes a single attempt): rdap(), age(), ageCheck(), screen(), verdict(), Screen::isMalware(), DnsClient::query(), queryEach(), acceptsMail(), DomainAge::firstCertificate() and firstCapture().

The timeout applies to each request, so the worst case of one request is (retries + 1) × timeout + retries × retry_delay. With the defaults:

Service Worst case per request
rdap 1 × 10 s = 10 s
dns 2 × 3 s + 0.2 s = 6.2 s (acceptsMail() can make three: MX, A, AAAA)
screen 1 × 2 s = 2 s (both resolvers in parallel)
certificates 2 × 20 s + 3 s = 43 s
wayback 2 × 20 s + 5 s = 45 s

ageCheck() adds up its sources: RDAP, then the fallbacks asked for. The defaults suit a queued job. In a web request, use a short timeout and no retries, and treat null or unknown as "check later":

Rate limits

Every request passes through a hook first, with the service name (rdap, dns, screen, wayback, certificates). It is the place for a rate limiter shared across workers:

Testing

Every call goes through Laravel's HTTP client, so Http::fake() covers the whole package:

Sponsors

Laradomains is supported by the following sponsors. Thank you for keeping it growing:

Kenodo     AndorraDev     Valor Web     ToxicFilter

Author

Created by Edu Lazaro

License

Laradomains is open-sourced software licensed under the Mozilla Public License 2.0.


All versions of laradomains with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4
ext-intl Version *
laravel/framework Version ^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package edulazaro/laradomains contains the following files

Loading the files please wait ...