Zend - The PHP Company




Link Checkers

Add Code


valid link! +cache  

Type: code fragment
Added by: SHARYANTO
Entered: 12/07/2000
Last modified: 08/12/1999
Rating: - (fewer than 3 votes)
Views: 7591
An enhanced form of Idban's valid link!, a PHP script that lets you a test a link for the host's connectivity before displaying it. Enhancements include: cache in session and test for absolute/relative links.

Note that, despite its name, this script does not truely test whether a link is valid. A valid link should return a 200 HTTP status code, which this script does not test. What this script test is whether the web/FTP server of the link is reachable and listening (that is, from server that host the script to the link host, anyway, not from the viewer's computer to the link host :-p). But the script still could be somewhat useful to some of you, I guess.



// 000712, steven@haryan.to

/*

an example of usage:

 <? require "/path/to/this/file"?>
 My validated bookmarks:
 <ul>
 <li><? disp_link("http://slashdot.org""Slashdot"); ?>
 <li><? disp_link("http://www.zope.org""Zope"); ?>
 <li><? disp_link("http://www.python.org""Python"); ?>
 <li><? disp_link("http://www.perl.com""Perl"); ?>
 <li><? disp_link("http://www.php.net""Zend"); ?>
 <li><? disp_link("http://www.perl.com/CPAN-local/"""); ?>
 </ul>

btw, yup, of course this code is under GPL.

 */

$debug = 0;
$timeout = 30; // give up if can't connect within 30 secs.
$check_freq = 5*60; // cache for 5 minutes.

session_register('statuses');
session_register('hostnames');

function flush_disp_link_cache() {
    global $statuses;
    global $hostnames;
    $statuses = array();
    $hostnames = array();
}

function disp_link($url, $text) {
    global $debug;
    global $timeout;
    global $statuses;
    global $hostnames;
    global $check_freq;

    $now = time();
    $e = error_reporting(); error_reporting($e & (255-E_WARNING));

    if (!preg_match('/^(http|https|ftp)://((?:w+.?)+):?(d*)/', $url, $m)) {

        // it's a relative link, or absolute link with unsupported protocol
        // so there's no need to check
        $status = '';
        if ($debug) { $status='DEBUG:UNCHECKED'; }

    } else {

        $proto=$m[1];
        $hostname=strtolower($m[2]);
        $port=$m[3];

        // is the host an IP address?
        if (preg_match('/^d+.d+.d+.d+/', $hostname)) {

            $ip = $hostname;

        } else { // it's not, so we have to resolve it first

            // have we tried to resolve it not so long ago?
            $from_cache=0;
            if (isset($hostnames[$hostname])) {

                if ($debug) {
                    echo "DEBUG: last resolve = ", $hostnames[$hostname][1], "<br>";
                }

                if ($now - $hostnames[$hostname][1] <= $check_freq) {
                    $ip = $hostnames[$hostname];
                    $from_cache=1;
                }

            }

            if (!$from_cache) {
                // we haven't, so resolve it
                $ip = gethostbyname($hostname);

                // if the hostname was not resolvable, gethostbyname returns 
                // its argument unchanged
                if ($ip == $hostname) { $ip=''; }

                // cache this resolve
                $hostnames[$hostname]=array($ip,$now);
            }
            
        }

        if (!$ip) { // was the hostname unresolvable?

            $status = 'HOST NOT FOUND';

        } else {

            // get universal port number defaults, if not specified
            if (!$port) { 
                if ($proto == 'http') { $port = 80; }
                elseif ($proto == 'https') { $port = 443; }
                elseif ($proto == 'ftp') { $port = 21; }
            }

            $key = "$ip:$port";

            // have we checked the site not so long ago?
            $from_cache=0;
            if (isset($statuses[$key])) {

                if ($debug) {
                    echo "DEBUG: last check = ",$statuses[$key][1], "<br>";
                }

                if ($now-$statuses[$key][1] <= $check_freq) {
                    $status = $statuses[$key][0];
                    $from_cache=1;
                }

            }

            if (!$from_cache) {
                // we haven't, so check it

                if ($debug) {
                    echo "DEBUG: checking: proto=$proto, hostname=$hostname, ",
                         "ip=$ip, port=$port...<br>";
                }
                $fp = fsockopen($hostname, $port, &$errno, &$errstr, $timeout);

                if ($debug) {
                    echo "DEBUG: connect result: fp=$fp, errno=$errno, errstr=$errstr<br>"; 
                }

                if ($fp) {
                    $status = "OK";
                } else {
                    if (preg_match('/timed?[- ]?out/i', $errstr)) {
                        $status = "TIMEOUT";
                    } elseif (preg_match('/refused/i', $errstr)) {
                        $status = "OFF";
                    } else {
                        $status = "DOWN?";
                    }
                }

                // cache this check
                $statuses[$key] = array($status, $now);
            }

        }

    }

    echo "<A HREF="$url">", ($text ? $text : htmlentities($url)), "</A>";
    if ($status) { echo " ($status)"; }

    error_reporting($e);
}

?>


Usage Example


See the example


Rate This Script





Search



This Category All Categories