PHP提供一组查找函数,这些函数可以用来检查主机名称、IP地址、邮件交换等信息。例如,如果要创建一个目录站点,例如Yahoo!,当用户提交一个新的URL时,我们可能会自动检查URL所指向的主机和此站点的联系信息是否有效。这样,当一个访问者浏览一个网站并发现此网站不存在或电子邮件无效时,可以节省进一步的操作。
程序清单20-2给出了目录提交的HTML表单。
程序清单20-2 directory_submit.html——提交表单的HTML
<html>
<head>
<title>Submit your site</title>
</head>
<body>
<h1>Submit site</h1>
<form method=post action=/"directory_submit.php/">
URL:<input type=text name=/"url/"size=30 email/'size=23><br/>
<input type=/"submit/"name=/"Submit site/">
</form>
</body>
</html>
这是一个非常简单的表单,图20-2所示的就是带有输入样本数据的表单。
图 20-2 目录提交通常要求提交URL和某些详细的联系信息,这样可以方便目录管理员在添加了站点以后通知我们当点击提交按钮时,我们首先要检查该URL是否对应一台真实的主机,其次,还要检查电子邮件地址的主机部分是否也对应真实的机器。我们已经编写了这些检查脚本,它的输出结果如图20-3所示。
图 20-3 此版本的脚本显示对URL主机名和电子邮件地址的检查结果——一个实际的产品版本可能不会显示这些结果,但看看检查返回的信息是非常有趣的执行这些检查的脚本使用了两个来自PHP网络函数集中的函数——gethostbyname和dns_get_mx。全部脚本如程序清单20-3所示。
程序清单20-3 directory_submit.php——用于检查URL和电子邮件地址的脚本
<html>
<head>
<title>Site submission results</title>
</head>
<body>
<h1>Site submission results</h1>
<?php
//Extract form fields
$url=$_REQUEST[/'url/'];
$email=$_REQUEST[/'email/'];
//Check the URL
$url=parse_url($url);
$host=$url[/'host/'];
if(!($ip=gethostbyname($host)))
{
echo/'Host for URL does not have valid IP/';
exit;
}
echo/"Host is at IP$ip<br>/";
//Check the email address
$email=explode(/'@/',$email);
$emailhost=$email[1];
//note that the dns_get_mxfunction is*not implemented*in
//Windows versions of PHP
if(!dns_get_mx($emailhost,$mxhostsarr))
{
echo/'Email address is not at valid host/';
exit;
}
echo/'Email is delivered via:/';
foreach($mxhostsarr as$mx)
echo/"$mx/";
//If reached here,all ok
echo/'<br>All submitted details are ok.<br>/';
echo/'Thank you for submitting your site.<br>/'
./'It will be visited by one of our staff members soon./'
//In real case,add to db of waiting sites...
?>
</body>
</html>
现在,我们来了解一下这个脚本的有趣部分。
首先,获取URL并将其作为函数parse_url的参数。该函数将返回包含URL不同部分的相关数组。该数组的可用信息部分分别是“模式”、“用户”、“传递”、“主机”、“端口”、“路径”、“查询”和“代码段”(scheme、user、pass、host、port、path、query、fragment)。一般情况下,并不需要所有这些信息。如下所示的例子说明它们是如何组成一个有效的URL。
假设有一个如下所示的URL:http://nobody:[email protected]:80/script.php?variable=value#anchor,数组的每一个元素值分别是:
■scheme:http
■user:nobody
■pass:secret
■host:example.com
■port:80
■path:/script.php
■query:variable=value
■fragment:anchor
在directory_submit.php脚本中,我们只需要主机信息,因此可以按如下操作从数组中取出:
$url=parse_url($url);
$host=$url[/'hos/'];
在完成以上操作后,如果主机是在域名服务(DNS)中,可以获得此主机的IP地址。我们可以通过函数gethostbyname获得一个主机的IP地址。如果主机存在,此函数就返回其IP地址,如果不存在,函数将返回false:
$ip=gethostbyname($host);
也可以使用函数gethostbyaddr来实现,此函数以IP作为参数并返回主机名。如果顺序地调用这个函数,最后获得的主机名将与开始时的主机名不同。这可能意味着网站正在使用一个虚拟主机服务。在这个服务中,一个物理主机和IP地址具有多个域名。
如果URL是有效的,接下来就需要检查电子邮件地址。首先,通过调用函数explode将邮件地址分割成用户名和主机名两部分:
$email=explode(/'@/',$email);
$emailhost=$email[1];
当得到主机部分的地址后,可以通过函数dns_get_mx检查是否有邮件可以到达的确切地方:
dns_get_mx($emailhost,$mxhostsarr);
该函数将返回一个邮件地址的一组邮件交换(Mail Exchange,MX)记录,该地址由数组$mxhostarr提供。
MX记录存储在DNS中,而且其查找方式类似于主机名的查找方式。MX列出的机器不一定是邮件最终到达的机器。相反,它是一台知道邮件发送路由的机器(可能不止一台,因此这个函数返回一个数组而不是一个主机名字符串)。如果DNS中没有MX记录,那么该邮件就没有可发送的目的地。
请注意,在PHP的Windows版本中,并没有实现dns_get_mx函数。如果使用Windows,必须使用PEAR::Net_DNS包(http://pear.php.net/package/NET_DNS),该包包含了具有此功能的函数。
如果这些检查都正确,可以将这个表单的数据输入到数据库,以便工作人员以后复查。
除了刚才已经使用的函数外,我们还可以使用更普通的函数checkdnsrr,这个函数以主机名作为参数,如果在DNS中有其记录,函数将返回true。