Tool Suggest Top-Level Domains - php

I am creating a tool for our customers to check if their domain name exists. I plan on using the gethostbyname($domain) function. But, I want to pre-program other TLD's that would be checked along with their preferred TLD (sent through a form). I don't really know where to start here so I included my example below for user suggestions.
// SUPPORTED TOP-LEVEL DOMAIN NAMES (TLDS)
$TLD['COMING_SOON'] = ".REALTY, .CONSTRUCTION";
$TLD['CURRENT'] = ".COM, .ORG, .US";
// RECEIVE FORM DATA AND STRIP TAGS
$SOURCE = $_SERVER['HTTP_REFERER'];
$DOMAIN = strip_tags($_POST['domain_name']);
$TLD = strip_tags($_POST['tld']);
$REQ = $DOMAIN.$TLD;
// CHECK CLIENT'S PREFERRED DOMAIN
if ( gethostbyname($REQ) != $REQ ) {
echo "DNS Record found";
} else {
echo "NO DNS Record found";
}
// TO DO: CHECK ALTERNATIVE TOP-LEVEL DOMAINS
// TO DO: SOMEHOW SEARCH THROUGH THE $TLD ARRAY, COMPARE, AND GIVE RESULT

gethostbyname($domain) will not be sufficient; it will only tell you if the domain is active, not whether it is available for purchase or not.
To find out whether it's actually available to buy, you will need to query the relevant WHOIS service for each domain type. But this will differ for each domain type, and parsing the resulting data can be a pain, so you would be better off using an API
The registrars that you're using to register the domains should also be able to provide you with an API that you can call. Contact them and find out what they have and how to use it. That's the best option.

Related

PHP: Get Domain (without subdomain) of any Address available as String

Recently a question has been asked, how to get the Domain of any URL available as a String.
Unfortunately the question has been closed, and the so far linked answers only pointed to solutions using Regex (which fails for special cases like .co.uk) and static solutions, considering those exceptions (which ofc. might change over time).
So, I was searching for a generic solution for this question, that will work at any time and found one. (At least a couple of tests are positive)
If you find a domain for which the attempted solution does not work, feel free to mention it, and I'll try to imrpove the snipped to cover that case as well.
To find the domain of any string given, a three-step solution seems to work best:
First, get the actual Hostname, using parse_url (http://php.net/manual/en/function.parse-url.php)
Second, query any DNS-Server for the "Top-Most" A-Record available. (I used checkdnsrr for this purpose: http://php.net/manual/en/function.checkdnsrr.php)
Last but not least: Perform some validations to make sure you are not running into some "default response".
I performed only some tests and it seems like the result is as expected. The method directly generates the output, but can be modified to return the domain name instead of generating output:
<?php
getDomain("http://www.stackoverflow.com");
getDomain("http://www.google.co.uk");
getDomain("http://books.google.co.uk");
getDomain("http://a.b.c.google.co.uk");
getDomain("http://www.nominet.org.uk/intelligence/statistics/registration/");
getDomain("http://invalid.fail.pooo");
getDomain("http://AnotherOneThatShouldFail.com");
function getDomain($url){
echo "Searching Domain for '".$url."': ";
//Step 1: Get the actual hostname
$url = parse_url($url);
$actualHostname = $url["host"];
//step 2: Top-Down approach: check DNS Records for the first valid A-record.
//Re-Assemble url step-by-step, i.e. for www.google.co.uk, check:
// - uk
// - co.uk
// - google.co.uk (will match here)
// - www.google.co.uk (will be skipped)
$domainParts = explode(".", $actualHostname);
for ($i= count($domainParts)-1; $i>=0; $i--){
$domain = "";
$currentCountry = null;
for ($j = count($domainParts)-1; $j>=$i; $j--){
$domain = $domainParts[$j] . "." . $domain;
if ($currentCountry == null){
$currentCountry = $domainParts[$j];
}
}
$domain = trim($domain, ".");
$validRecord = checkdnsrr($domain, "A"); //looking for Class A records
if ($validRecord){
//If the host can be resolved to an ip, it seems valid.
//if hostname is returned, its invalid.
$hostIp = gethostbyname($domain);
$validRecord &= ($hostIp != $domain);
if ($validRecord){
//last check: DNS server might answer with one of ISPs default server ips for invalid domains.
//perform a test on this by querying a domain of the same "country" that is invalid for sure to obtain an
//ip list of ISPs default servers. Then compare with the response of current $domain.
$validRecord &= !(in_array($hostIp, gethostbynamel("iiiiiiiiiiiiiiiiiinvaliddomain." . $currentCountry)));
}
}
//valid record?
if ($validRecord){
//return $domain;
echo $domain."<br />";
return;
}
}
//return null;
echo " not resolved.<br />";
}
?>
Output of the example above:
Searching Domain for 'http://www.stackoverflow.com': stackoverflow.com
Searching Domain for 'http://www.google.co.uk': google.co.uk
Searching Domain for 'http://books.google.co.uk': google.co.uk
Searching Domain for 'http://a.b.c.google.co.uk': google.co.uk
Searching Domain for 'http://www.nominet.org.uk/intelligence/statistics/registration/': nominet.org.uk
Searching Domain for 'http://invalid.fail.pooo': not resolved.
Searching Domain for 'http://AnotherOneThatShouldFail.com': not resolved.
This is only a very limited set of test-cases but I cannot imagine a case, where a domain has no A-record.
As a nice side-effect, this also validates urls and does not just rely on theoretically valid formats like the last examples are showing.
best,
dognose

domain checker how to do suggestions?

I have a basic domain checker that returns a 'this domain is free' or 'this domain is not available' message. But how do I make suggestions?
Lets say the visitor checks whether 'www.stackoverflow.com' is available. When it's available, there's no problem and the user can go order it. When it's not available, i want it to do suggestions for other extensions. Like:
www.stackoverflow.com is not available,
The following domains are available:
www.stackoverflow.net
www.stackoverflow.co.uk
www.stackoverflow.info
This is my current file:
<?php
if(isset($_POST['check'])) {
if (!empty($_POST['domain_name'])){
$domain = trim($_POST['domein_naam']).$_POST['domain_list'];
$result = #dns_get_record($domain, DNS_ALL);
if(empty($result)) {
echo "<H2 style='color:green;' >Domain $domain is available.</H2>";
} else {
echo "<H2 style='color:red;'>Domain $domain is not available.</H2>";
}
} else {
echo "<H2 style='color:red;'>Fout: Domein kan niet leeg zijn.</H2>";
}
}
?>
Without knowing all of your code structure it's hard to give you the best method.
But a simple idea:
Say the site the user entered ($_POST/$_GET/etc) is stored in $strUserSite variable.
Have an array ($aryFurtherChecks or whatever) with all extensions in (.com, .net, etc).
Loop the array checking if each domain for what user entered is avail or not, by appending your $strUserSite var to it.
If domain + extension from array is available, either echo it out (depending on your code setup/framework etc) or add to new array, then loop second array with "These are also available".
Which methods you use depend on if you're using procedural all-in-one-file code, or classes etc.
If the latter then setting a new array would be preferred, looping it in your view/template/whatever file and echoing out each one with your HTML and styling etc.
dns_get_record() cannot be used to determine whether a domain is available for registration, because not all registered domains have DNS records. For instance, example.info is registered, but has no DNS records.
Since it sounds as though you are planning to use this as part of a domain registration system, you presumably have access to a domain registration API. Most providers of such APIs have a call to generate suggestions - try using that. Failing that, you will need to remove the TLD from the domain input by the user and replace it successively with the alternatives you want to try.

PHP - allow domains, not subdomains

I would appreciate any help that can be provided with this matter.
I am creating a registration form, one field is for the users domain which I will verify is valid with FILTER_VALIDATE_URL and that it exists with dns_check_record.
However a problem I'm having is that using these two methods will also allow subdomains to be submitted to the form which I don't want.
Does anyone know a way to allow domains but not subdomains?
I've tested the following function, from http://syntax.cwarn23.net/PHP/Strip_URL_to_Domain:
function domain($domainb)
{
$bits = explode('/', $domainb);
if ($bits[0]=='http:' || $bits[0]=='https:')
{
$domainb= $bits[2];
} else {
$domainb= $bits[0];
}
unset($bits);
$bits = explode('.', $domainb);
$idz=count($bits);
$idz-=3;
if (strlen($bits[($idz+2)])==2) {
$url=$bits[$idz].'.'.$bits[($idz+1)].'.'.$bits[($idz+2)];
} else if (strlen($bits[($idz+2)])==0) {
$url=$bits[($idz)].'.'.$bits[($idz+1)];
} else {
$url=$bits[($idz+1)].'.'.$bits[($idz+2)];
}
return $url;
However this isn't perfect as any domains such as www.domain.uk.com will appear as uk.com (I know not a common domain extension).
Does anyone know a method better than the above function?
As pointed by Micheal Mior, you have to check for .co.uk, .com.br and many others.
Some browser vendors are maintaining a list of such non-TLD that are effectively TLD: http://publicsuffix.org/. The list is quite huge.
There is a library here that uses this effective TLD list to implement the function you are looking for (download are here). (Found via https://wiki.mozilla.org/Gecko:Effective_TLD_Service.)
Combine them.
dns_check_record will fail on '.co.uk', so you can split your string on the dots, check the domain you get when you combine the last two parts, and if that fails, use a third part too, if any.
You will do a double check for invalid domains, but I assume that won't be an issue.
first you could use parse_url() to get only the host name: http://www.stackoverflow.com -> $url['host'] = 'www.stackoverflow.com'
Second you could count the amount of points in the hostname: explode() --> count() or substr_count()
Has the host more than 1 point a subdomain could be exist.
Now you could use the solution mentioned by GolezTrol or arnaud576875.

How to track users location / region in PHP

I'm trying to get the country from which the user is browsing the website so I can work out what currency to show on the website. I have tried using the GET scripts available from: http://api.hostip.info but they just return XX when I test it.
If anyone knows any better methods please share.
Thanks.
I use this:
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
$ip = $_SESSION['ip'];
$try1 = "http://ipinfodb.com/ip_query.php?ip=".$ip."&output=xml";
$try2 = "http://backup.ipinfodb.com/ip_query.php?ip=".$ip."&output=xml";
$XML = #simplexml_load_file($try1,NULL,TRUE);
if(!$XML) { $XML = #simplexml_load_file($try2,NULL,TRUE); }
if(!$XML) { return false; }
//Retrieve location, set time
if($XML->City=="") { $loc = "Localhost / Unknown"; }
else { $loc = $XML->City.", ".$XML->RegionName.", ".$XML->CountryName; }
$_SESSION['loc'] = $loc;
Try these:
http://ip-to-country.webhosting.info/
http://www.ip2location.com/
Both are IP address-to-country databases, which allow you to look up the country of origin of a given IP address.
However it's important to note that these databases are not 100% accurate. They're a good guide, but you will get false results for a variety of reasons.
Many people use proxying to get around country-specific blocks and filters.
Many IP ranges are assigned to companies with large geographic spread; you'll just get the country where they're based, not where the actual machine is (this always used to be a big problem for tracking AOL users, because they were all apparently living in Virginia)
Control of IP ranges are sometimes transferred between countries, so you may get false results from that (especially for smaller/less well-connected countries)
Keeping your database up-to-date will mitigate some of these issues, but won't resolve them entirely (especially the proxying issue), so you should always allow for the fact that you will get false results.
You should use the geoip library.
Maxmind provides free databases and commercial databases, with a difference in the date of last update and precision, the commercial being of better quality.
See http://www.maxmind.com/app/geolitecountry for the free database.
I think it should be sufficient for basic needs.
You can use Geolocation to get the Coordinates and then some Service to get the Country from that, but the geolocation API is browser based so you can only access it via JavaScript and then have to pass theese Informations to PHP somehow, i wrote something on the JS Part once:
http://www.lautr.com/utilizing-html5-geolocation-api-and-yahoo-placefinder-example
When it comes to getting the Location via the IP, there are a bazillion Services out there who offer databases for that, some free, some for charge, some with a lot of IP's stored and much data, some with less, for example the one you mentioned, works just fine:
http://api.hostip.info/?ip=192.0.32.10
So You can ether go with the Geolocation API which is pretty neat, but requires the users permission, works via JS and doesnt work in IE (so far) or have to look for a IPÜ Location Service that fits your needs :)
Try these:
$key="9dcde915a1a065fbaf14165f00fcc0461b8d0a6b43889614e8acdb8343e2cf15";
$ip= "198.168.1230.122";
$url = "http://api.ipinfodb.com/v3/ip-city/?key=$key&ip=$ip&format=xml";
// load xml file
$xml = simplexml_load_file($url);
// print the name of the first element
echo $xml->getName() . "";
// create a loop to print the element name and data for each node
foreach($xml->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
}
There are many ways to do it as suggested by those earlier. But I suggest you take a look at the IP2 PHP library available at https://github.com/ip2iq/ip2-lib-php which we developed.
You can use it like below:
<?php
require_once("Ip2.php");
$ip2 = new \ip2iq\Ip2();
$country_code = $ip2->country('8.8.8.8');
//$country_code === 'US'
?>
It doesn't need any SQL or web service lookup just a local data file. It is faster than almost all other methods out there. The database is updated monthly you can download it for free.
The only thing you will need to do for now if you need the country name in your language is map it to an associative array from something like this https://gist.github.com/DHS/1340150

Determining the hostname/IP address from the MX record in PHP

have a basic email domain validation script that takes a user's email domain, resolves the IP address from that and then checks that against various published blacklists. Here is how I am determining the IP:
$domain = substr(strchr($email, '#'), 1);
$ip = gethostbyname($domain);
The problem is that some email address domains, such as soandso#alumni.example.net, use an MX record rather than an A record, so using gethostbyname('alumni.example.net') will fail to resolve. I know when a user's email is using an MX in the email itself by using the PHP checkdnsrr function, but once at that stage am a little stuck as to how to proceed.
In theory, I could parse out the 'root' domain, i.e. 'example.net' and check it, but I've not found reliable regex that can handle this task when the user could easily have an email the format of user#corp.example.co.uk...
So, any suggestions on how to best tackle this??
Instead of using gethostbyname, use dns_get_record, something like dns_get_record($domain,DNS_MX). See the docs for how the return values are structured.
$Arr = dns_get_record('ford.com' , DNS_MX);
$count = count($Arr);
for($i=0; $i<$count; $i++) {
echo $i.'-'.$Arr[$i]['target'].'-'.gethostbyname($Arr[$i]['target']).'-'.$Arr[$i]['ttl'].'<br/>';
}
I got the result with ip address as following order(Pref, host, ip, ttl).
0-cluster4a.us.messagelabs.com-85.158.139.103-453
1-cluster4.us.messagelabs.com-216.82.242.179-453
The easiest is probably
if (!getmxrr($host, $result)) {
$result=array($host);
}
Then loop over the results, calling gethostbyname() and checking that none are blacklisted (or you could pick the result with the lowest weight, but that could be easily used to circumvent the blacklist).
I'd question the usefulness of blacklisting a destination; DNS spam blacklists are usually made for blacklisting sources.
You cannot do source validation based solely on someone's e-mail address, because (in general) any party anywhere on the internet can send any e-mail with anyone else's e-mail address in it.
Using this function you can only check atleast one mx records is available for the given domain. Code is not tested with multiple domains.
function mxrecordValidate($email){
list($user, $domain) = explode('#', $email);
$arr= dns_get_record($domain,DNS_MX);
if($arr[0]['host']==$domain&&!empty($arr[0]['target'])){
return $arr[0]['target'];
}
}
$email= 'user#radiffmail.com';
if(mxrecordValidate($email)) {
echo('This MX records exists; I will accept this email as valid.');
}
else {
echo('No MX record exists; Invalid email.');
}
If find any improvement in this function, comments are appreciated.
Try:
$result = shell_exec ('host -t MX '.$domain);
var_dump ($result);
or
exec ('host -t MX '.$domain, $result = array ());
var_dump ($result);
You will get list of MX records, you can parse it and check each record with gethostbyname().
Edit
dns_get_record() mentioned by Ycros will be better.

Categories