Tuesday, July 14, 2009

Beginning PHP and Oracle From Novice to Professional by W. Jason Gilmore and Bob Bryla Chapter 16

You may have turned to this chapter wondering just what PHP could possibly have to offer in regard to networking. After all, aren’t networking tasks largely relegated to languages commonly
used for system administration, such as Perl or Python? While such a stereotype might have once painted a fairly accurate picture, these days, incorporating networking capabilities into a Web appli- cation is commonplace. In fact, Web-based applications are regularly used to monitor and even maintain network infrastructures. Furthermore, with the introduction of the command-line inter- face (CLI) in PHP version 4.2.0, PHP is now increasingly used for system administration among developers who wish to continue using their favorite language for other purposes. The PHP developers, always keen to acknowledge growing needs in the realm of Web application development and to remedy demands by incorporating new features into the language, have put together a rather amazing array of network-specific functionality.
This chapter is divided into sections covering the following topics:

DNS, servers, and services: PHP offers a variety of functions capable of retrieving information about the network internals, DNS, protocols, and Internet addressing schemes. This section introduces these functions and offers several usage examples.

Sending e-mail with PHP: Sending e-mail via a Web application is undoubtedly one of the most commonplace features you can find these days, and for good reason. E-mail remains the Internet’s killer application and offers an amazingly efficient means for communicating and maintaining important data and information. This section explains how to easily send messages via a PHP script. Additionally, you’ll learn how to use the PEAR packages Mail and Mail_Mime to facilitate more complex e-mail dispatches, such as those involving multiple recipients, HTML format- ting, and the inclusion of attachments.

Common networking tasks: In this section, you’ll learn how to use PHP to mimic the tasks commonly carried out by command-line tools, including pinging a network address, tracing a network connection, scanning a server’s open ports, and more.

DNS, Services, and Servers

These days, investigating or troubleshooting a network issue often involves gathering a variety of information pertinent to affected clients, servers, and network internals such as protocols, domain name resolution, and IP addressing schemes. PHP offers a number of functions for retrieving a bevy of information about each subject, each of which is introduced in this section.

287

■Note Several of the functions introduced in this chapter don’t work on Windows. Check out the PEAR package
Net_DNS to emulate their capabilities.

DNS

The Domain Name System (DNS) is what allows you to use domain names (e.g., example.com) in place of the corresponding not-so-user-friendly IP address, such as 192.0.34.166. The domain names and their complementary IP addresses are stored and made available for reference on domain name servers, which are interspersed across the globe. Typically, a domain has several types of records asso- ciated to it, one mapping the IP address to the domain, another for directing e-mail, and another for a domain name alias, for example. Often network administrators and developers require a means to learn more about various DNS records for a given domain. This section introduces a number of stan- dard PHP functions capable of digging up a great deal of information regarding DNS records.

Checking for the Existence of DNS Records

The checkdnsrr() function checks for the existence of DNS records. Its prototype follows:

int checkdnsrr(string host [, string type])

DNS records are checked based on the supplied host value and optional DNS resource record type, returning TRUE if any records are located, and FALSE otherwise. Possible record types include the following:

A: IPv4 Address Record. Responsible for the hostname-to-IPv4 address translation.

AAAA: IPv6 Address Record. Responsible for the hostname-to-IPv6 address translation.

A6: IPv6 Address Record. Used to represent IPv6 addresses. Intended to supplant present use of
AAAA records for IPv6 mappings.

ANY: Looks for any type of record.

CNAME: Canonical Name Record. Maps an alias to the real domain name.

MX: Mail Exchange Record. Determines the name and relative preference of a mail server for the host. This is the default setting.

NAPTR: Naming Authority Pointer. Allows for non-DNS-compliant names, resolving them to new domains using regular expression rewrite rules. For example, an NAPTR might be used to maintain legacy (pre-DNS) services.

NS: Name Server Record. Determines the name server for the host.

PTR: Pointer Record. Maps an IP address to a host.

SOA: Start of Authority Record. Sets global parameters for the host.
SRV: Services Record. Denotes the location of various services for the supplied domain. Consider an example. Suppose you want to verify whether the domain name example.com has
a corresponding DNS record:

<?php
$recordexists = checkdnsrr("example.com", "ANY");
if ($recordexists) echo "The domain name has been reserved. Sorry!";
else echo "The domain name is available!";
?>

This returns the following:

The domain name has been reserved. Sorry!

You can also use this function to verify the existence of a domain of a supplied mail address:

<?php
$email = "ceo@example.com";
$domain = explode("@",$email);

$valid = checkdnsrr($domain[1], "ANY");

if($valid) echo "The domain exists!";
else echo "Cannot locate MX record for $domain[1]!";
?>

This returns the following:

The domain exists!

Keep in mind this isn’t a request for verification of the existence of an MX record. Sometimes network administrators employ other configuration methods to allow for mail resolution without using MX records (because MX records are not mandatory). To err on the side of caution, just check for the existence of the domain, without specifically requesting verification of whether an MX record exists.
Further, this doesn’t verify whether an e-mail address actually exists. The only definitive way to
make this determination is to send that user an e-mail and ask him to verify the address by clicking a one-time URL. You can learn more about one-time URLs in Chapter 14.

Retrieving DNS Resource Records

The dns_get_record() function returns an array consisting of various DNS resource records pertinent to a specific domain. Its prototype follows:

array dns_get_record(string hostname [, int type [, array &authns, array &addtl]])

Although by default dns_get_record() returns all records it can find specific to the supplied domain (hostname), you can streamline the retrieval process by specifying a type, the name of which must be prefaced with DNS. This function supports all the types introduced along with checkdnsrr(), in addition to others that will be introduced in a moment. Finally, if you’re looking for a full-blown description of this hostname’s DNS description, you can pass the authns and addtl parameters in by reference, which specify that information pertinent to the authoritative name servers and additional records also should be returned.

Assuming that the supplied hostname is valid and exists, a call to dns_get_record() returns at least four attributes:

host: Specifies the name of the DNS namespace to which all other attributes correspond.

class: Returns records of class Internet only, so this attribute always reads IN.

type: Determines the record type. Depending upon the returned type, other attributes might also be made available.

ttl: Calculates the record’s original time-to-live minus the amount of time that has passed since the authoritative name server was queried.

In addition to the types introduced in the section on checkdnsrr(), the following domain record types are made available to dns_get_record():

DNS_ALL: Retrieves all available records, even those that might not be recognized when using the recognition capabilities of your particular operating system. Use this when you want to be absolutely sure that all available records have been retrieved.

DNS_ANY: Retrieves all records recognized by your particular operating system.

DNS_HINFO: Specifies the operating system and computer type of the host. Keep in mind that this information is not required.

DNS_NS: Determines whether the name server is the authoritative answer for the given domain, or whether this responsibility is ultimately delegated to another server.

Just remember that the type names must always be prefaced with DNS_.
As an example, suppose you want to learn more about the example.com domain:

<?php
$result = dns_get_record("example.com");
print_r($result);
?>

A sampling of the returned information follows:

Array (
[0] => Array (
[host] => example.com
[type] => NS
[target] => a.iana-servers.net
[class] => IN [ttl] => 110275
)
[1] => Array (
[host] => example.com
[type] => A
[ip] => 192.0.34.166 [class] => IN
[ttl] => 88674
)
)

If you were only interested in the name server records, you could execute the following:

<?php
$result = dns_get_record("example.com","DNS_CNAME");
print_r($result);
?>

This returns the following:

Array ( [0] => Array ( [host] => example.com [type] => NS [target] => a.iana-servers.net [class] => IN [ttl] => 21564 ) [1] => Array ( [host] => example.com [type] => NS
[target] => b.iana-servers.net [class] => IN [ttl] => 21564 ) )
getmxrr()

Retrieving MX Records

The getmxrr() function retrieves the MX records for the domain specified by hostname. Its prototype follows:

boolean getmxrr(string hostname, array &mxhosts [, array &weight])

The MX records for the host specified by hostname are added to the array specified by mxhosts. If the optional input parameter weight is supplied, the corresponding weight values will be placed there, which refer to the hit prevalence assigned to each server identified by record. An example follows:

<?php getmxrr("wjgilmore.com",$mxhosts); print_r($mxhosts);
?>

This returns the following:

Array ( [0] => mail.wjgilmore.com)

Services

Although we often use the word Internet in a generalized sense, referring to it in regard to chatting, reading, or downloading the latest version of some game, what we’re actually referring to is one or several Internet services that collectively define this communication platform. Examples of these services include HTTP, FTP, POP3, IMAP, and SSH. For various reasons (an explanation of which is beyond the scope of this book), each service commonly operates on a particular communications port. For example, HTTP’s default port is 80, and SSH’s default port is 22. These days, the widespread need for firewalls at all levels of a network makes knowledge of such matters quite important. Two PHP functions, getservbyname() and getservbyport(), are available for learning more about services and their corresponding port numbers.

Retrieving a Service’s Port Number

The getservbyname() function returns the port number of a specified service. Its prototype follows:

int getservbyname(string service, string protocol)

The service corresponding to service must be specified using the same name as that found in the /etc/services file. The protocol parameter specifies whether you’re referring to the tcp or udp component of this service. Consider an example:
<?php
echo "HTTP's default port number is: ".getservbyname("http", "tcp");
?>

This returns the following:

HTTP's default port number is: 80

Retrieving a Port Number’s Service Name

The getservbyport() function returns the name of the service corresponding to the supplied port number. Its prototype follows:

string getservbyport(int port, string protocol)

The protocol parameter specifies whether you’re referring to the tcp or the udp component of the service. Consider an example:
<?php
echo "Port 80's default service is: ".getservbyport(80, "tcp");
?>

This returns the following:

Port 80's default service is: http

Establishing Socket Connections

In today’s networked environment, you’ll often want to query services, both local and remote. Often this is done by establishing a socket connection with that service. This section demonstrates how this is accomplished, using the fsockopen() function. Its prototype follows:

resource fsockopen(string target, int port [, int errno [, string errstring
[, float timeout]]])

The fsockopen() function establishes a connection to the resource designated by target on port port, returning error information to the optional parameters errno and errstring. The optional parameter timeout sets a time limit, in seconds, on how long the function will attempt to establish the connection before failing.
The first example shows how to establish a port 80 connection to www.example.com using
fsockopen() and how to output the index page:

<?php

// Establish a port 80 connection with www.example.com
$http = fsockopen("www.example.com",80);

// Send a request to the server
$req = "GET / HTTP/1.1\r\n";
$req .= "Host: www.example.com\r\n";
$req .= "Connection: Close\r\n\r\n";

fputs($http, $req);

// Output the request results while(!feof($http)) {
echo fgets($http, 1024);
}

// Close the connection fclose($http);
?>

This returns the following:

HTTP/1.1 200 OK Date: Mon, 09 Oct 2006 23:33:52 GMT Server: Apache/2.0.54 (Fedora) (Red-Hat/Linux) Last-Modified: Wed, 15 Nov 2005 13:24:10 GMT ETag:
"63ffd-1b6-80bfd280" Accept-Ranges: bytes Content-Length: 438
Connection: close Content-Type: text/html
You have reached this web page by typing "example.com", "example.net", or
"example.org" into your web browser.
These domain names are reserved for use in documentation and are not available for registration. See RFC 2606, Section 3.

The second example, shown in Listing 16-1, demonstrates how to use fsockopen() to build a rudimentary port scanner.

Listing 16-1. Creating a Port Scanner with fsockopen()

<?php

// Give the script enough time to complete the task ini_set("max_execution_time", 120);

// Define scan range
$rangeStart = 0;
$rangeStop = 1024;

// Which server to scan?
$target = "www.example.com";

// Build an array of port values
$range =range($rangeStart, $rangeStop);

echo "<p>Scan results for $target</p>";

// Execute the scan
foreach ($range as $port) {
$result = @fsockopen($target, $port,$errno,$errstr,1);
if ($result) echo "<p>Socket open at port $port</p>";
}

?>

Scanning www.example.com, the following output is returned:

Scan results for www.example.com: Socket open at port 21
Socket open at port 25
Socket open at port 80
Socket open at port 110

A far lazier means for accomplishing the same task involves using a program execution command such as system() and the wonderful free software package Nmap (http://insecure.org/nmap/). This method is demonstrated in the section on common networking tasks.

Mail

This powerful feature of PHP is so darned useful, and needed in so many Web applications, that this section is likely to be one of the more popular sections of this chapter, if not the whole book. In this section, you’ll learn how to send e-mail using PHP’s popular mail() function, including how to control headers, include attachments, and carry out other commonly desired tasks.
This section introduces the relevant configuration directives, describes PHP’s mail() function, and concludes with several examples highlighting this function’s many usage variations.

Configuration Directives

There are five configuration directives pertinent to PHP’s mail() function. Pay close attention to the descriptions because each is platform-specific.

SMTP = string

Scope: PHP_INI_ALL; Default value: localhost
The SMTP directive sets the Mail Transfer Agent (MTA) for PHP’s Windows platform version of the mail function. Note that this is only relevant to the Windows platform because Unix platform implementations of this function are actually just wrappers around that operating system’s mail function. Instead, the Windows implementation depends on a socket connection made to either a local or a remote MTA, defined by this directive.

sendmail_from = string

Scope: PHP_INI_ALL; Default value: NULL
The sendmail_from directive sets the From field of the message header. This parameter is only useful on the Windows platform. If you’re using a Unix platform, you must set this field within the mail function’s addl_headers parameter.

sendmail_path = string

Scope: PHP_INI_SYSTEM; Default value: the default sendmail path
The sendmail_path directive sets the path to the sendmail binary if it’s not in the system path, or if you’d like to pass additional arguments to the binary. By default, this is set to the following:

sendmail -t -i

Keep in mind that this directive only applies to the Unix platform. Windows depends upon establishing a socket connection to an SMTP server specified by the SMTP directive on port smtp_port.

smtp_port = integer

Scope: PHP_INI_ALL; Default value: 25
The smtp_port directive sets the port used to connect to the server specified by the SMTP directive.

mail.force_extra_parameters = string

Scope: PHP_INI_SYSTEM; Default value: NULL
You can use the mail.force_extra_parameters directive to pass additional flags to the sendmail binary. Note that any parameters passed here will replace those passed in via the mail() function’s addl_parameters parameter.
As of PHP 4.2.3, the addl_params parameter is disabled if you’re running in safe mode. However,
any flags passed in via this directive will still be passed in even if safe mode is enabled. In addition, this parameter is irrelevant on the Windows platform.

Sending E-mail Using a PHP Script

E-mail can be sent through a PHP script in amazingly easy fashion, using the mail() function. Its prototype follows:

boolean mail(string to, string subject, string message [, string addl_headers
[, string addl_params]])

The mail() function can send an e-mail with a subject and a message to one or several recipi- ents. You can tailor many of the e-mail properties using the addl_headers parameter, and can even modify your SMTP server’s behavior by passing extra flags via the addl_params parameter.
On the Unix platform, PHP’s mail() function is dependent upon the sendmail MTA. If you’re using an alternative MTA (e.g., qmail), you need to use that MTA’s sendmail wrappers. PHP’s Windows implementation of the function instead depends upon establishing a socket connection to an MTA designated by the SMTP configuration directive, introduced in the previous section.
The remainder of this section is devoted to numerous examples highlighting the many capabilities of this simple yet powerful function.

Sending a Plain-Text E-mail

Sending the simplest of e-mails is trivial using the mail() function, done using just the three required parameters. Here’s an example:

<?php
mail("test@example.com", "This is a subject", "This is the mail body");
?>

Try swapping out the placeholder recipient address with your own and executing this on your
server. The mail should arrive in your inbox within a few moments. If you’ve executed this script on a Windows server, the From field should denote whatever e-mail address you assigned to the sendmail_from configuration directive. However, if you’ve executed this script on a Unix machine, you might have noticed a rather odd From address, likely specifying the user nobody or www. Because of the way PHP’s mail function is implemented on Unix systems, the default sender will appear as the same user under which the server daemon process is operating. You can change this default, as is demonstrated in the next example.

Taking Advantage of PEAR: Mail and Mail_Mime

While it’s possible to use the mail() function to perform more complex operations such as sending to multiple recipients, annoying users with HTML-formatted e-mail, or including attachments, doing so can be a tedious and error-prone process. However, the Mail (http://pear.php.net/package/ Mail) and Mail_Mime (http://pear.php.net/package/Mail_Mime) PEAR packages make such tasks a breeze. These packages work in conjunction with one another: Mail_Mime creates the message, and Mail sends it. This section introduces both packages.

Installing Mail and Mail_Mime

To take advantage of Mail and Mail_Mime, you’ll first need to install both packages. To do so, invoke
PEAR and pass along the following arguments:

%>pear install Mail Mail_Mime

Execute this command and you’ll see output similar to the following:

Starting to download Mail-1.1.13.tgz (17,527 bytes)
......done: 17,527 bytes
downloading Mail_Mime-1.3.1.tgz ...
Starting to download Mail_Mime-1.3.1.tgz (16,481 bytes)
...done: 16,481 bytes
install ok: channel://pear.php.net/Mail_Mime-1.3.1 install ok: channel://pear.php.net/Mail-1.1.13

Sending an E-mail with Multiple Recipients

Using Mime and Mime_Mail to send an e-mail to multiple recipients requires that you identify the appropriate headers in an array. After instantiating the Mail_Mime class you call the headers() method and pass in this array, as is demonstrated in this example:

<?php

// Include the Mail and Mime_Mail Packages include('Mail.php'); include('Mail/mime.php');

// Recipient Name and E-mail Address
$name = "Jason Gilmore";
$recipient = "jason@example.com";

// Sender Address
$from = "bram@example.com";

// CC Address
$cc = "marketing@example.com";

// Message Subject
$subject = "Thank you for your inquiry";

txt;

// E-mail Body
$txt = <<<txt
This is the e-mail message.

// Identify the Relevant Mail Headers
$headers['From'] = $from;
$headers['Cc'] = $subject;
$headers['Subject'] = $subject;

// Instantiate Mail_mime Class
$mimemail = new Mail_mime();

// Set HTML Message
$mimemail->setTxtBody($html);

// Build Message
$message = $mimemail->get();

// Prepare the Headers
$mailheaders = $mimemail->headers($headers);

// Create New Instance of Mail Class
$email =& Mail::factory('mail');

// Send the E-mail!
$email->send($recipient, $mailheaders, $message) or die("Can't send message!");

?>

Sending an HTML-Formatted E-mail

Although many consider HTML-formatted e-mail to rank among the Internet’s greatest annoyances, how to send it is a question that comes up repeatedly. Therefore, it seems prudent to offer an example and hope that no innocent recipients are harmed as a result.
Despite the widespread confusion surrounding this task, sending an HTML-formatted e-mail is actually quite easy. Consider Listing 16-2, which creates and sends an HTML-formatted message.

Listing 16-2. Sending an HTML-Formatted E-mail

<?php

// Include the Mail and Mime_Mail Packages include('Mail.php'); include('Mail/mime.php');

// Recipient Name and E-mail Address
$name = "Jason Gilmore";
$recipient = "jason@example.org";

// Sender Address
$from = "bram@example.com";

// Message Subject
$subject = "Thank you for your inquiry - HTML Format";

// E-mail Body
$html = <<<html
<html><body>

<h3>Example.com Stamp Company</h3>
<p>
Dear $name,<br />
Thank you for your interest in <b>Example.com's</b> fine selection of collectible stamps. Please respond at your convenience with your telephone number and a suggested date and time to chat.
</p>

<p>I look forward to hearing from you.</p>

<p>
Sincerely,<br />
Bram Brownstein<br />
President, Example.com Stamp Supply html;

// Identify the Relevant Mail Headers
$headers['From'] = $from;
$headers['Subject'] = $subject;

// Instantiate Mail_mime Class
$mimemail = new Mail_mime();

// Set HTML Message
$mimemail->setHTMLBody($html);

// Build Message
$message = $mimemail->get();

// Prepare the Headers
$mailheaders = $mimemail->headers($headers);

// Create New Instance of Mail Class
$email =& Mail::factory('mail');

// Send the E-mail Already!
$email->send($recipient, $mailheaders, $message) or die("Can't send message!");

?>

Executing this script results in an e-mail that looks like that shown in Figure 16-1.
Because of the differences in the way HTML-formatted e-mail is handled by the myriad of mail
clients out there, consider sticking with plain-text formatting for such matters.

Figure 16-1. An HTML-formatted e-mail

Sending an Attachment

The question of how to include an attachment with a programmatically created e-mail often comes up. Doing so with Mail_Mime is a trivial matter. Just call the Mail_Mime object’s addAttachment() method, passing in the attachment name and extension, and identifying its content type:

$mimemail->addAttachment('inventory.pdf', 'application/pdf');

Common Networking Tasks

Although various command-line applications have long been capable of performing the networking tasks demonstrated in this section, offering a means for carrying them out via the Web certainly can be useful. For example, at work we host a variety of Web-based applications within our intranet for the IT support department employees to use when they are troubleshooting a networking problem but don’t have an SSH client handy. In addition, these applications can be accessed via Web browsers found on most modern wireless PDAs. Finally, although the command-line counterparts are far more powerful and flexible, viewing such information via the Web is at times simply more conve- nient. Whatever the reason, it’s likely you could put to good use some of the applications found in this section.

■Note Several examples in this section use the system() function. This function is introduced in Chapter 10.

Pinging a Server

Verifying a server’s connectivity is a commonplace administration task. The following example shows you how to do so using PHP:

<?php

// Which server to ping?
$server = "www.example.com";

// Ping the server how many times?
$count = 3;

// Perform the task echo "<pre>";
system("/bin/ping -c $count $server");
echo "</pre>";

// Kill the task system("killall -q ping");

?>

The preceding code should be fairly straightforward except for perhaps the system call to killall.
This is necessary because the command executed by the system call will continue to execute if the user ends the process prematurely. Because ending execution of the script within the browser will not actually stop the process for execution on the server, you need to do it manually.
Sample output follows:

PING www.example.com (192.0.34.166) from 123.456.7.8 : 56(84) bytes of data.
64 bytes from www.example.com (192.0.34.166): icmp_seq=0 ttl=255 time=158 usec
64 bytes from www.example.com (192.0.34.166): icmp_seq=1 ttl=255 time=57 usec
64 bytes from www.example.com (192.0.34.166): icmp_seq=2 ttl=255 time=58 usec

--- www.example.com ping statistics ---
5 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/mdev = 0.048/0.078/0.158/0.041 ms

PHP’s program execution functions are great because they allow you to take advantage of any program installed on the server that has the appropriate permissions assigned.

Creating a Port Scanner

The introduction of fsockopen() earlier in this chapter is accompanied by a demonstration of how to create a port scanner. However, like many of the tasks introduced in this section, this can be accomplished much more easily using one of PHP’s program execution functions. The following example uses PHP’s system() function and the Nmap (network mapper) tool:

<?php

$target = "www.example.com"; echo "<pre>"; system("/usr/bin/nmap $target"); echo "</pre>";

// Kill the task system("killall -q nmap");

?>

A snippet of the sample output follows:

Starting nmap V. 4.11 ( www.insecure.org/nmap/ ) Interesting ports on (209.51.142.155):
(The 1500 ports scanned but not shown below are in state: closed)
Port State Service
22/tcp open ssh
80/tcp open http
110/tcp open pop-3
111/tcp filtered sunrpc

Creating a Subnet Converter

You’ve probably at one time scratched your head trying to figure out some obscure network config- uration issue. Most commonly, the culprit for such woes seems to center on a faulty or an unplugged network cable. Perhaps the second most common problem is a mistake made when calculating the necessary basic network ingredients: IP addressing, subnet mask, broadcast address, network address, and the like. To remedy this, a few PHP functions and bitwise operations can be coaxed into doing the calculations for you. When provided an IP address and a bitmask, Listing 16-3 calculates several of these components.

Listing 16-3. A Subnet Converter

<form action="listing16-3.php" method="post">
<p>
IP Address:<br />
<input type="text" name="ip[]" size="3" maxlength="3" value="" />.
<input type="text" name="ip[]" size="3" maxlength="3" value="" />.
<input type="text" name="ip[]" size="3" maxlength="3" value="" />.
<input type="text" name="ip[]" size="3" maxlength="3" value="" />
</p>

<p>
Subnet Mask:<br />
<input type="text" name="sm[]" size="3" maxlength="3" value="" />.
<input type="text" name="sm[]" size="3" maxlength="3" value="" />.
<input type="text" name="sm[]" size="3" maxlength="3" value="" />.
<input type="text" name="sm[]" size="3" maxlength="3" value="" />
</p>

<input type="submit" name="submit" value="Calculate" />

</form>

<?php
if (isset($_POST['submit'])) {
// Concatenate the IP form components and convert to IPv4 format
$ip = implode('.', $_POST['ip']);
$ip = ip2long($ip);

// Concatenate the netmask form components and convert to IPv4 format
$netmask = implode('.', $_POST['sm']);
$netmask = ip2long($netmask);

// Calculate the network address
$na = ($ip & $netmask);
// Calculate the broadcast address
$ba = $na | (~$netmask);

// Convert the addresses back to the dot-format representation and display echo "Addressing Information: <br />";
echo "<ul>";
echo "<li>IP Address: ". long2ip($ip)."</li>";
echo "<li>Subnet Mask: ". long2ip($netmask)."</li>"; echo "<li>Network Address: ". long2ip($na)."</li>"; echo "<li>Broadcast Address: ". long2ip($ba)."</li>";
echo "<li>Total Available Hosts: ".($ba - $na - 1)."</li>";
echo "<li>Host Range: ". long2ip($na + 1)." - ". long2ip($ba - 1)."</li>";
echo "</ul>";
}
?>

Consider an example. If you supply 192.168.1.101 as the IP address and 255.255.255.0 as the subnet mask, you should see the output shown in Figure 16-2.

Figure 16-2. Calculating network addressing

Testing User Bandwidth

Although various forms of bandwidth-intensive media are commonly used on today’s Web sites, keep in mind that not all users have the convenience of a high-speed network connection at their disposal. You can automatically test a user’s network speed with PHP by sending the user a relatively large amount of data and then noting the time it takes for transmission to complete.
To do this, create the datafile that will be transmitted to the user. This can be anything, really,
because the user will never actually see the file. Consider creating it by generating a large amount of text and writing it to a file. For example, this script will generate a text file that is roughly 1.5MB in size:

<?php
// Create a new file, creatively named "textfile.txt"
$fh = fopen("textfile.txt","w");

// Write the word "bandwidth" repeatedly to the file. for ($x=0;$x<170400;$x++) fwrite($fh,"bandwidth");

// Close the file fclose($fh);
?>

Now you’ll write the script that will calculate the network speed. This script is shown in Listing 16-4.

Listing 16-4. Calculating Network Bandwidth

<?php

// Retrieve the data to send to the user
$data = file_get_contents("textfile.txt");

// Determine the data's total size, in Kilobytes
$fsize = filesize("textfile.txt") / 1024;

// Define the start time
$start = time();

// Send the data to the user echo "<!-- $data -->";

// Define the stop time
$stop = time();

// Calculate the time taken to send the data
$duration = $stop - $start;

// Divide the file size by the number of seconds taken to transmit it
$speed = round($fsize / $duration,2);

// Display the calculated speed in Kilobytes per second echo "Your network speed: $speed KB/sec.";

?>

Executing this script produces output similar to the following:

Your network speed: 59.91 KB/sec.

Summary

Many of PHP’s networking capabilities won’t soon replace those tools already offered on the command line or other well-established clients. Nonetheless, as PHP’s command-line capabilities continue to gain traction, it’s likely you’ll quickly find a use for some of the material presented in this chapter, perhaps the e-mail dispatch capabilities if nothing else.
The next chapter introduces one of the most powerful examples of how to use PHP effectively
with other enterprise technologies, showing you just how easy it is to interact with your preferred directory server using PHP’s LDAP extension.

0 comments: