372 Chapter 17 Using Network and Protocol Functions There are two modes for an FTP transfer, ASCII and binary.The ASCII mode is used for transferring text files (that is, files that consist solely of ASCII characters), and the binary mode, used for transferring everything else. PHP’s FTP library comes with two predefined constants, FTP_ASCII and FTP_BINARY, that represent these two modes.You need to decide which mode fits your file type, and pass the corresponding constant to ftp_fget() as the fourth parameter. In this case we are transferring a zip file, and so we have used the FTP_BINARY mode. The ftp_fget() function returns true if all goes well, or false if an error is encountered.We store the result in $success, and let the user know how it went. After the download has been attempted, we close the local file using the fclose() function. As an alternative to ftp_fget(),we could have used ftp_get(), which has the fol- lowing prototype: int ftp_get (int ftp_connection, string localfile_path, string remotefile_path, int mode) This function works in much the same way as ftp_fget(),but does not require the local file to be open.You pass it the system filename of the local file you would like to write to rather than a file handle. Note that there is no equivalent to the FTP command mget, which can be used to download multiple files at a time.You must instead make multiple calls to ftp_fget() or ftp_get(). Closing the Connection After we have finished with the FTP connection, you should close it using the ftp_quit() function: ftp_quit($conn); You should pass this function the handle for the FTP connection. Uploading Files If you want to go the other way, that is, copy files from your server to a remote machine, you can use two functions that are basically the opposite of ftp_fget() and ftp_get(). These functions are called ftp_fput() and ftp_put().They have the following proto- types: int ftp_fput (int ftp_connection, string remotefile_path, int fp, int mode) int ftp_put (int ftp_connection, string remotefile_path, string localfile_path, int mode) The parameters are the same as for the _get equivalents. 22 525x ch17 1/24/03 3:40 PM Page 372 373 Using FTP Avoiding Timeouts One problem you might face when FTPing files is exceeding the maximum execution time.You will know whether this happens because PHP will give you an error message. This is especially likely to occur if your server is running over a slow or congested net- work, or if you are downloading a large file, such as a movie clip. The default value of the maximum execution time for all PHP scripts is defined in the php.ini file. By default, it’s set to 30 seconds.This is designed to catch scripts that are running out of control. However, when you are FTPing files, if your link to the rest of the world is slow, or if the file is large, the file transfer could well take longer than this. Fortunately, we can modify the maximum execution time for a particular script using the set_time_limit() function. Calling this function resets the maximum number of seconds the script is allowed to run, starting from the time the function is called. For example, if you call set_time_limit(90); then the script will be able to run for another 90 seconds from the time the function is called. Using Other FTP Functions There are a number of other useful FTP functions in PHP. The function ftp_size() can tell you the size of a file on a remote server. It has the following prototype: int ftp_size(int ftp_connection, string remotefile_path) This function returns the size of the remote file in bytes, or -1 if there is an error.This is not supported by all FTP servers. One handy use of ftp_size() is to work out the maximum execution time to set for a particular transfer. Given the file size and the speed of your connection, you can take a guess as to how long the transfer ought to take, and use the set_time_limit() function accordingly. You can get and display a list of files in a directory on a remote FTP server with the following code: $listing = ftp_nlist($conn, "$directory_path"); foreach ($listing as $filename) echo "$filename <br />"; This code uses the ftp_nlist() function to get a list of names of files in a particular directory. In terms of other FTP functions, almost anything that you can do from an FTP com- mand line, you can do with the FTP functions.You can find the specific functions corre- sponding to each FTP command in the PHP online manual at http://php.net/ manual/en/ref.ftp.php. 22 525x ch17 1/24/03 3:40 PM Page 373 374 Chapter 17 Using Network and Protocol Functions The exception is mget (multiple get), but you can use ftp_nlist() to get a list of files and then fetch them as required. Generic Network Communications with cURL PHP (from version 4.0.2 onward) has a set of functions that acts as an interface to cURL, the Client URL library functions from libcurl, written by Daniel Stenberg. Previously in this chapter, we looked at using the fopen() function and the file-reading functions to read from a remote file using HTTP.This is pretty much the limit of what you can do with fopen().We’ve also seen how to make FTP connections using the FTP functions. The cURL functions enable you to make connections using FTP, HTTP, HTTPS, Gopher,Telnet, DICT, FILE, and LDAP.You can also use certificates for HTTPS, send HTTP POST and HTTP GET parameters, upload files via FTP upload or HTTP upload, work through proxies, set cookies, and perform simple HTTP user authentica- tion. In other words, just about any kind of network connection that you’d like to make can be done using cURL. To use cURL with PHP, you will need to download libcurl, compile it, and run PHP’s configure script with the with-curl=[path] option.The directory in path should be the one that contains the lib and include directories on your system.You can download the library from http://curl.haxx.se/ Be aware that you will need a version of cURL from 7.0.2-beta onward to work with PHP. There are only a few simple functions to master in order to use the power of cURL. The typical procedure for using it is 1. Set up a cURL session with a call to the curl_init() function. 2. Set any parameters for transfer with calls to the curl_setopt() function.This is where you set options such as the URL to connect to, any parameters to send to that URL, or the destination of the output from the URL. 3. When everything is set up, call curl_exec() to actually make the connection. 4. Close the cURL session by calling curl_close(). The only things that change with the application are the URL that you connect to and the parameters you set with curl_opt().There are a large number of these that can be set. Some typical applications of cURL are n Downloading pages from a server that uses HTTPS (because fopen() can’t be used for this purpose prior to PHP 4.3) 22 525x ch17 1/24/03 3:40 PM Page 374 375 Generic Network Communications with cURL n Connecting to a script that normally expects data from an HTML form using POST n Writing a script to send multiple sets of test data to your scripts and checking the output We will consider the first example—it’s a simple application that can’t be done another way. This example, shown in Listing 17.5, will connect to the Equifax Secure Server via HTTPS, and write the file it finds there to a file on our Web server. Listing 17.5 https-curl.php—Script to Make HTTPS Connections <?php echo '<h1>HTTPS transfer with cURL</h1>'; $outputfile = '/tmp/writable/ssl-download.html'; $fp = fopen($outputfile, 'w+'); echo 'Initializing cURL session <br />'; $ch = curl_init(); echo 'Setting cURL options <br />'; curl_setopt ($ch, CURLOPT_URL, 'https://www.verisign.com/'); curl_setopt ($ch, CURLOPT_FILE, $fp); echo 'Executing cURL session <br />'; curl_exec ($ch); echo 'Ending cURL session <br />'; curl_close ($ch); fclose($fp); echo 'Here is the content of the file:<hr />'; readfile($outputfile); ?> Let’s go through this script.We begin by opening a local file using fopen().This is where we are going to store the page we transfer from the secure connection. When this is done, we need to create a cURL session using the curl_init() function: $ch = curl_init(); This function returns a handle for the cURL session.You can call it like this, with no parameters, or optionally you can pass it a string containing the URL to connect to.You can also set the URL using the curl_setopt() function, which is what we have done in this case: 22 525x ch17 1/24/03 3:40 PM Page 375 376 Chapter 17 Using Network and Protocol Functions curl_setopt ($ch, CURLOPT_URL, 'https://www.equifaxsecure.com'); curl_setopt ($ch, CURLOPT_FILE, $fp); The curl_setopt() function takes three parameters.The first is the session handle, the second is the name of the parameter to set, and the third is the value to which you would like the parameter set. In this case we are setting two options.The first is the URL that we want to connect to.This is the CURLOPT_URL parameter.The second one is the file where we want the data from the connection to go. If you don’t specify a file, the data from the connection will go to standard output—usually the browser. In this case we have specified the file handle of the output file we just opened. When the options are set, we tell cURL to actually make the connection: curl_exec ($ch); Here, this will open a connection to the URL we have specified, download the page, and store it in the file pointed to by $fp. After the connection has been made, we need to close the cURL session, and close the file we wrote to: curl_close ($ch); fclose($fp); That’s it for this simple example. Yo u might find it worthwhile to look at the Snoopy class, available from http://snoopy.sourceforge.net/. This class provides Web client functionality through cURL. Further Reading We ’ve covered a lot of ground in this chapter, and as you might expect, there’s a lot of material out there on these topics. For information on the individual protocols and how they work, you can consult the RFCs at http://www.rfc-editor.org/. You might also find some of the protocol information at the World Wide Web Consortium interesting: http://www.w3.org/Protocols/ You can also try consulting a book on TCP/IP such as Computer Networks by Andrew Tanenbaum. The cURL Web site has some tips on how to use the command line versions of the cURL functions, and these are fairly easily translated into the PHP versions: http://curl.haxx.se/docs/httpscripting.shtml 22 525x ch17 1/24/03 3:40 PM Page 376 . FTP com- mand line, you can do with the FTP functions.You can find the specific functions corre- sponding to each FTP command in the PHP online manual at http:/ /php. net/ manual/en/ref.ftp .php. 22. Equifax Secure Server via HTTPS, and write the file it finds there to a file on our Web server. Listing 17.5 https-curl .php Script to Make HTTPS Connections < ?php echo '<h1>HTTPS. Computer Networks by Andrew Tanenbaum. The cURL Web site has some tips on how to use the command line versions of the cURL functions, and these are fairly easily translated into the PHP versions: http://curl.haxx.se/docs/httpscripting.shtml 22