How do I run a WHOIS lookup with PHP or Python? - php

So anyways, I'm working on a small PHP website/script, and as one of the features I'd like to be able to run a WHOIS lookup on the current domain the PHP script is running on.
Ideally, it would be one function that I could call and in the function it would run the WHOIS, and then echo the results to the screen. It would take in the URL of the site to run the WHOIS lookup on, or it would just run it on the current URL/Domain (which is what I want), although I can feed it a variable for the website domain if need be.
I don't know much about WHOIS lookups (well, I know what they do, I just don't know how to run them in PHP), but I'd also be fine with having to query another website (even one of my own if you can give me the code for it).
Whatever works, please just let me know! The main thing is that, I'd prefer it to fit all in one function, and it definitely must fit in one PHP file/document.

With php you can use shell_exec to execute the whois command.
<?php
$whois = shell_exec("whois domain.net");
echo '<pre>';
print_r($whois);
?>

This should do exactly what you want... http://www.phpwhois.org/
I've used this class before, doing exactly what you want!

To take Pavels answer one step further - this will break it down in to an array:
$whois = shell_exec("whois 45.118.135.255");
$result = explode("\n",$whois);
$out = array();
foreach ($result as $line){
if (substr($line,0,1) == '%' || substr($line,0,1) == '#'){ continue; }
$ps = explode(':',$line);
$out[trim($ps[0])] = trim($ps[1]);
}
print '<pre>'; print_r($out); print '</pre>';

There are some third party packages:
First one : io-developer/php-whois
composer require io-developer/php-whois
Usage:
// How to get summary about domain:
<?php
use Iodev\Whois\Factory;
// Creating default configured client
$whois = Factory::get()->createWhois();
// Checking availability
if ($whois->isDomainAvailable("google.com")) {
print "Bingo! Domain is available! :)";
}
// Supports Unicode (converts to punycode)
if ($whois->isDomainAvailable("почта.рф")) {
print "Bingo! Domain is available! :)";
}
// Getting raw-text lookup
$response = $whois->lookupDomain("google.com");
print $response->text;
// Getting parsed domain info
$info = $whois->loadDomainInfo("google.com");
print_r([
'Domain created' => date("Y-m-d", $info->creationDate),
'Domain expires' => date("Y-m-d", $info->expirationDate),
'Domain owner' => $info->owner,
]);
// Exceptions on domain lookup:
<?php
use Iodev\Whois\Factory;
use Iodev\Whois\Exceptions\ConnectionException;
use Iodev\Whois\Exceptions\ServerMismatchException;
use Iodev\Whois\Exceptions\WhoisException;
try {
$whois = Factory::get()->createWhois();
$info = $whois->loadDomainInfo("google.com");
if (!$info) {
print "Null if domain available";
exit;
}
print $info->domainName . " expires at: " . date("d.m.Y H:i:s", $info->expirationDate);
} catch (ConnectionException $e) {
print "Disconnect or connection timeout";
} catch (ServerMismatchException $e) {
print "TLD server (.com for google.com) not found in current server hosts";
} catch (WhoisException $e) {
print "Whois server responded with error '{$e->getMessage()}'";
}
If you are using Laravel : laravel-whois
composer require larva/laravel-whois -vv
php artisan migrate
Usage:
$info = \Larva\Whois\Whois::lookup('baidu.com', true);
$info = \Larva\Whois\Whois::lookupRaw('google.com');

Best thing to do would be to use pywhois. Though you say Python in the question title but don't mention it in the post. If you actually need PHP, I'm sure there's something equivalent for that.

I found it here: https://whoisfreaks.com/documentation/api/whois-api.html. You can get Whoislook up by using PHP thru this code snippet:
'https://api.whoisfreaks.com/v1.0/whois?whois=live&domainName=jfreaks.com&apikey=Your API_Key',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
I hope it'll work for you too.

Try the Function Which is available in github gist
https://gist.github.com/ManojKiranA/4b034659e85fa02308ad9bdcdd05629c
For the full list of TLDs/Whois servers see http://www.iana.org/domains/root/db/ and http://www.whois365.com/en/listtld/

Related

PHP script can't open certain URLs

I'm calling through Axios a PHP script checking whether a URL passed to it as a parameter can be embedded in an iframe. That PHP script starts with opening the URL with $_GET[].
Strangely, a page with cross-origin-opener-policy: same-origin (like https://twitter.com/) can be opened with $_GET[], whereas a page with Referrer Policy: strict-origin-when-cross-origin (like https://calia.order.liven.com.au/) cannot.
I don't understand why, and it's annoying because for the pages that cannot be opened with $_GET[] I'm unable to perform my checks on them - the script just fails (meaning I get no response and the Axios call runs the catch() block).
So basically there are 3 types of pages: (1) those who allow iframe embeddability, (2) those who don't, and (3) the annoying ones who not only don't but also can't even be opened to perform this check.
Is there a way to open any page with PHP, and if not, what can I do to prevent my script from failing after several seconds?
PHP script:
$source = $_GET['url'];
$response = true;
try {
$headers = get_headers($source, 1);
$headers = array_change_key_case($headers, CASE_LOWER);
if (isset($headers['content-security-policy'])) {
$response = false;
}
else if (isset($headers['x-frame-options']) &&
$headers['x-frame-options'] == 'DENY' ||
$headers['x-frame-options'] == 'SAMEORIGIN'
) {
$response = false;
}
} catch (Exception $ex) {
$response = $ex;
}
echo $response;
EDIT: below is the console error.
Access to XMLHttpRequest at 'https://path.to.cdn/iframeHeaderChecker?url=https://calia.order.liven.com.au/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CustomLink.vue?b495:61 Error: Network Error
at createError (createError.js?2d83:16)
at XMLHttpRequest.handleError (xhr.js?b50d:84)
VM4758:1 GET https://path.to.cdn/iframeHeaderChecker?url=https://calia.order.com.au/ net::ERR_FAILED
The error you have shown is coming from Javascript, not from PHP. get_headers() returns false on failure, it will not throw an exception - the catch() never happens. get_headers() just makes an http request, like your browser, or curl, and the only reason that would fail is if the URL is malformed, or the remote site is down, etc.
It is the access from http://localhost:3000 to https://path.to.cdn/iframeHeaderChecker with Javascript that has been blocked, not PHP access to the URLs you are passing as parameters in $_GET['url'].
What you're seeing is a standard CORS error when you try to access a different domain than the one the Javascript is running on. CORS means Javascript running on one host cannot make http requests to another host, unless that other host explicitly allows it. In this case, the Javascript running at http://localhost:3000 is making an http request to a remote site https://path.to.cdn/. That's a cross-origin request (localhost !== path.to.cdn), and the server/script receiving that request on path.to.cdn is not returning any specific CORS headers allowing that request, so the request is blocked.
Note though that if the request is classed as "simple", it will actually run. So your PHP is working already, always, but bcs the right headers aren't returned, the result is blocked from being displayed in your browser. This can lead to confusion bcs for eg you might notice a delay while it gets the headers from a slow site, whereas it is super fast for a fast site. Or maybe you have logging which you see is working all the time, despite nothing showing up in your browser.
My understanding is that https://path.to.cdn/iframeHeaderChecker is your PHP script, some of the code of which you have shown in your question? If so, you have 2 choices:
Update iframeHeaderChecker to return the appropriate CORS headers, so that your cross-origin JS request is allowed. As a quick, insecure hack to allow access from anyone and anywhere (not a good idea for the long term!) you could add:
header("Access-Control-Allow-Origin: *");
But it would be better to update that to more specifically restrict access to only your app, and not everyone else. You'll have to evaluate the best way to do that depending on the specifics of your application and infrastructure. There many questions here on SO about CORS/PHP/AJAX to check for reference. You could also configure this at the web server level, rather than the application level, eg here's how to configure Apache to return those headers.
If iframeHeaderChecker is part of the same application as the Javascript calling it, is it also available locally, on http://localhost:3000? If so, update your JS to use the local version, not the remote one on path.to.cdn, and you avoid the whole problem!
This is just my rough guess about what wrong with your code can be.
I noticed you do:
a comparison of values from $headers but without
ensuring they have the same CAPITAL CASE as the values you compare against. Applied: strtoupper().
check with isset() but not test if key_exist before
Applied: key_exist()
check with isset() but perhaps you should use !empty() instead of isset()
compare result:
$value = "";
var_dump(isset($value)); // (bool) true
var_dump(!empty($value)); // (bool) false
$value = "something";
var_dump(isset($value)); // (bool) true
var_dump(!empty($value)); // (bool) true
unset($value);
var_dump(isset($value)); // (bool) false
var_dump(!empty($value)); // (bool) false
The code with applied changes:
<?php
error_reporting(E_ALL);
declare(strict_types=1);
header('Access-Control-Allow-Origin: *');
ob_start();
try {
$response = true;
if (!key_exists('url', $_GET)) {
$msg = '$_GET does not have a key "url"';
throw new \RuntimeException($msg);
}
$source = $_GET['url'];
if ($source !== filter_var($source, \FILTER_SANITIZE_URL)) {
$msg = 'Passed url is invaid, url: ' . $source;
throw new \RuntimeException($msg);
}
if (filter_var($source, \FILTER_VALIDATE_URL) === FALSE) {
$msg = 'Passed url is invaid, url: ' . $source;
throw new \RuntimeException($msg);
}
$headers = get_headers($source, 1);
if (!is_array($headers)) {
$msg = 'Headers should be array but it is: ' . gettype($headers);
throw new \RuntimeException($msg);
}
$headers = array_change_key_case($headers, \CASE_LOWER);
if ( key_exists('content-security-policy', $headers) &&
isset($headers['content-security-policy'])
) {
$response = false;
}
elseif ( key_exists('x-frame-options', $headers) &&
(
strtoupper($headers['x-frame-options']) == 'DENY' ||
strtoupper($headers['x-frame-options']) == 'SAMEORIGIN'
)
) {
$response = false;
}
} catch (Exception $ex) {
$response = "Error: " . $ex->getMessage() . ' at: ' . $ex->getFile() . ':' . $ex->getLine();
}
$phpOutput = ob_get_clean();
if (!empty($phpOutput)) {
$response .= \PHP_EOL . 'PHP Output: ' . $phpOutput;
}
echo $response;
Using Throwable instead of Exception will also catch Errors in PHP7.
Keep in mind that:
$response = true;
echo $response; // prints "1"
but
$response = false;
echo $response; // prints ""
so for the $response = false you'll get an empty string, not 0
if you want to have 0 for false and 1 for true then change the $response = true; to $response = 1; for true and $response = false; to $response = 0; for false everywhere.
I hope that somehow helps

PHP Cross-Origin-Request blocked

I have a PHP-script which takes a POST-variable from a request, does something with it (in this case it's an memcached request for the specific key) and sends it back via JSON.
The complicated part is that I don't host this script on the same Server as I do with the script doing the request. So I tried to use CORS. My browser tells me that I haven't set the Access-Control-Allow-Origin-Header, but I did as you can see. So I guess that I set it wrong. But I haven't really dealt with headers in PHP so I have really no clue what do do. I already searched (also on Stackoverflow) but all I found is that I have to set this header, what I did...
Of ourse the memcache-part isn't really interesting for solving the problem but I thought it would be better to let you guys take a look at the complete code, so here you go:
<?php
header("Access-Control-Allow-Origin: * ");
$key = $_POST["key"];
$json = "";
if($key != "")
{
define('MEMCACHED_HOST', '127.0.0.1');
define('MEMCACHED_PORT', '11211');
$memcache = new Memcache;
$memcache->connect(MEMCACHED_HOST, MEMCACHED_PORT);
$value = memcache->get($key);
$json_array = array("status" => "done" , "key" => $key, "value" => $value);
$json = json_encode($json_array);
}
else
{
$json_array = array("status" => "empty");
$json = json_encode($json_array);
}
echo $json;
?>
Inserting some lines into the Apache .conf file did it. If someone is interested, these lines can be found here. I still don't know why it didn't worked with the headers in PHP. Maybe I did something wrong with the client. But it's working now :)

How check if succesfull cmd ping in php

how can I check if a php ping returned succesfull or failed using php exec, I have in mind something with a while loop but I'm not sure if ts the best approach, I tried:
exec('ping www.google.com', $output)
but I would have to do a var_dump($output); to see the results, I want for each line the ping command returns to check it
$i = 2;
while(exec('ping www.google.com', $output)) {
if($output) {
echo 'True';
} else {
echo 'False';
}
}
I know this code is WRONG but its kind of what I need, if any of you could give me a head start on how to do it or suggestions I would really appreciate it....THANKS!!
This should do it:
if(exec('ping http://www.google.com')) {
echo 'True';
} else {
echo 'False';
}
I suggest you could use CUrl See Manual but that all depends upon what you are trying to achieve.
Provide more data if needed.
NOTE
You are to use http:// before google.com as that's needed in order to make the ping.
It's probably faster and more efficient and just do it within PHP, instead of exec'ing a shell
$host = '1.2.3.4';
$port = 80;
$waitTimeoutInSeconds = 1;
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds)){
// It worked
} else {
// It didn't work
}
fclose($fp);
Also some servers will have EXEC disabled for security reasons, so your method won't work on every server setup.

Cache using PHP cURL

I'm using PHP cURL to fetch information from another website and insert it into my page. I was wondering if it was possible to have the fetched information cached on my server? For example, when a visitor requests a page, the information is fetched and cached on my server for 24 hours. The page is then entirely served locally for 24 hours. When the 24 hours expire, the information is again fetched and cached when another visitor requests it, in the same way.
The code I am currently using to fetch the information is as follows:
$url = $fullURL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
Is this possible? Thanks.
You need to write or download a php caching library (like extensible php caching library or such) and adjust your current code to first take a look at cache.
Let's say your cache library has 2 functions called:
save_cache($result, $cache_key, $timestamp)
and
get_cache($cache_key, $timestamp)
With save_cache() you will save the $result into the cache and with get_cache() you will retrieve the data.
$cache_key would be md5($fullURL), a unique identifier for the caching library to know what you want to retrieve.
$timestamp is the amount of minutes/hours you want the cache to be valid, depending on what your caching library accepts.
Now on your code you can have a logic like:
$cache_key = md5($fullURL);
$timestamp = 24 // assuming your caching library accept hours as timestamp
$result = get_cache($cache_key, $timestamp);
if(!$result){
echo "This url is NOT cached, let's get it and cache it";
// do the curl and get $result
// save the cache:
save_cache($result, $cache_key, $timestamp);
}
else {
echo "This url is cached";
}
echo $result;
You can cache it using memcache ( a session ) you can cache it using files on your server and you can cache it using a database, like mySQL.
file_put_contents("cache/cachedata.txt",$data);
You will need to set the permissions of the folder you want to write the files to, otherwise you might get some errors.
Then if you want to read from the cache:
if( file_exists("cache/cachedata.txt") )
{ $data = file_get_contents("cache/cachedate.txt"); }
else
{ // curl here, we have no cache
}
Honza's suggestion to use Nette cache worked great for me, and here's the code I wrote to use it. My function returns the HTTP result if it worked, false if not. You'll have to change some path strings.
use Nette\Caching\Cache;
use Nette\Caching\Storages\FileStorage;
Require("/Nette/loader.php");
function cached_httpGet($url) {
$storage = new FileStorage("/nette-cache");
$cache = new Cache($storage);
$result = $cache->load($url);
if ($result) {
echo "Cached: $url";
}
else {
echo "Fetching: $url";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo "ERROR " . curl_error($ch) . " loading: $url";
return false;
} else
$cache->save($url, $result, array(Cache::EXPIRE => '1 day'));
curl_close($ch);
}
return $result;
}
Use Nette Cache. All you need solution, simple to use and of course - thread-safe.
If you've got nothing against file system access, you could just store it in a file. Then maybe use a script on the server that checks the file's timestamp against the current time and deletes it if it's too old.
If you don't have access to all aspects of the server you could just use the above idea and store a timestamp with the info. Every time the page is requested check against the timestamp.
And if you're having problems with the fs bottlenecking, you could use a MySQL database stored entirely in RAM.
I made a pretty cool simple function to store data gotten from your curl for 1 hour or 1 day off Antwan van Houdt's comment (shout out to him) .. firstly create a folder with name "zcache" in public_html and make sure the permission is at "755"
1 hour:
if( file_exists('./zcache/zcache-'.date("Y-m-d-H").'.html') )
{ $result = file_get_contents('./zcache/zcache-'.date("Y-m-d-H").'.html'); }
else
{
// put your curl here
file_put_contents('./zcache/zcache-'.date("Y-m-d-H").'.html',$result);
}
1 day:
if( file_exists('./zcache/zcache-'.date("Y-m-d").'.html') )
{ $result = file_get_contents('./zcache/zcache-'.date("Y-m-d").'.html'); }
else
{
// put your curl here
file_put_contents('./zcache/zcache-'.date("Y-m-d").'.html',$result);
}
you are welcome
The best way to avoid caching is applying the time or any other random element to the url, like this:
$url .= '?ts=' . time();
so for example instead of having
http://example.com/content.php
you would have
http://example.com/content.php?ts=1212434353

Grabbing Twitter Friends Feed Using PHP and cURL

So in keeping with my last question, I'm working on scraping the friends feed from Twitter. I followed a tutorial to get this script written, pretty much step by step, so I'm not really sure what is wrong with it, and I'm not seeing any error messages. I've never really used cURL before save from the shell, and I'm extremely new to PHP so please bear with me.
<html>
<head>
<title>Twitcap</title>
</head>
<body>
<?php
function twitcap()
{
// Set your username and password
$user = 'osoleve';
$pass = '****';
// Set site in handler for cURL to download
$ch = curl_init("https://twitter.com/statuses/friends_timeline.xml");
// Set cURL's option
curl_setopt($ch,CURLOPT_HEADER,1); // We want to see the header
curl_setopt($ch,CURLOPT_TIMEOUT,30); // Set timeout to 30s
curl_setopt($ch,CURLOPT_USERPWD,$user.':'.$pass); // Set uname/pass
curl_setopt($ch,CURLOPT_RETURNTRANSER,1); // Do not send to screen
// For debugging purposes, comment when finished
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
// Execute the cURL command
$result = curl_exec($ch);
// Remove the header
// We only want everything after <?
$data = strstr($result, '<?');
// Return the data
$xml = new SimpleXMLElement($data);
return $xml;
}
$xml = twitcap();
echo $xml->status[0]->text;
?>
</body>
</html>
Wouldn't you actually need everything after "?>" ?
$data = strstr($result,'?>');
Also, are you using a free web host? I once had an issue where my hosting provider blocked access to Twitter due to people spamming it.
note that if you use strstr the returend string will actually include the needle-string. so you have to strip of the first 2 chars from the string
i would rather recommend a combination of the function substr and strpos!
anways, i think simplexml should be able to handle this header meaning i think this step is not necessary!
furthermore if i open the url i don't see the like header! and if strstr doesnt find the string it returns false, so you dont have any data in your current script
instead of $data = strstr($result, '<?'); try this:
if(strpos('?>',$data) !== false) {
$data = strstr($result, '?>');
} else {
$data = $result;
}

Categories