Chapter 22 How to send email and access other web sites



Similar documents
Initial Setup of Mozilla Thunderbird with IMAP for OS X Lion

WIRIS quizzes web services Getting started with PHP and Java

Contents. 2 Alfresco API Version 1.0

Novell Identity Manager

Script Handbook for Interactive Scientific Website Building

Initial Setup of Microsoft Outlook 2011 with IMAP for OS X Lion

Fortigate SSL VPN 4 With PINsafe Installation Notes

ing from The E2 Shop System address Server Name Server Port, Encryption Protocol, Encryption Type, SMTP User ID SMTP Password

Update Instructions

Website Planning Checklist

Vodafone Hosted Services. Getting your . User guide

1 Login to your CSUF student account and click on the Settings icon ( ) at the far right.

How to Setup your Account -Apple Mail for Mac OS X 1- Open Mail

Migration Manual (For Outlook 2010)

Short notes on webpage programming languages

3. On the Accounts wizard window, select Add a new account, and then click Next.

Web Development 1 A4 Project Description Web Architecture

The Beginner s Guide to G-Lock WPNewsman Plugin for WordPress: Installation and Configuration

Fortigate SSL VPN 3.x With PINsafe Installation Notes

After you've enabled POP/IMAP access in i.mail, you need to configure your client to download i.mail messages.

Initial Setup of Mozilla Thunderbird with IMAP for Windows 7

Mail 8.2 for Apple OSX: Configure IMAP/POP/SMTP

CHARTER BUSINESS custom hosting faqs 2010 INTERNET. Q. How do I access my ? Q. How do I change or reset a password for an account?

Further web design: HTML forms

How to configure your Desktop Computer and Mobile Devices post migrating to Microsoft Office 365

Initial Setup of Mac Mail with IMAP for OS X Lion

Intell-a-Keeper Reporting System Technical Programming Guide. Tracking your Bookings without going Nuts!

This information is provided for informational purposes only.

1. Open Thunderbird. If the Import Wizard window opens, select Don t import anything and click Next and go to step 3.

Configuring Outlook 2016 for Windows

How To Configure Using Different Clients

Configuring your client to connect to your Exchange mailbox

Creating your personal website. Installing necessary programs Creating a website Publishing a website

Mail Programs. Manual

Web Programming with PHP 5. The right tool for the right job.

Configuring Mozilla Thunderbird to Access Your SAS Account

Configuring Your Client: Eudora 5.x

How To Send Mail From A Macbook Access To A Pc Or Ipad With A Password Protected Address (Monroe Access) On A Pc (For Macbook) Or Ipa (For Ipa) On Pc Or Macbook (For

Migration User Guides: The Console Application Setup Guide

Webmail. Setting up your account

Configuring Outlook 2013 For IMAP Connections

CS412 Interactive Lab Creating a Simple Web Form

Exchange Outlook Profile/POP/IMAP/SMTP Setup Guide

WineWeb Account Services

USING YOUR GMAIL ACCOUNT FOR SCRUBBING YOUR REGULAR OF SPAM Beginners Kaffee Klatch Presented by Bill Wilkinson

Protected Trust Journaling Guide. Privacy Security Compliance

BOTTOM UP THINKING SETUP INSTRUCTIONS. Unique businesses require unique solutions CLIENT GUIDE

e- storage Mail Archive

UNI - WINDOWS. How to... Access your University on your Windows Computer. Introduction. Step 1/1 - Setting Up Your Windows Computer

isecur User Guide for iphone

SEEM4540 Open Systems for E-Commerce Lecture 06 Online Payment

BlackBerry Internet Service Using the Browser on Your BlackBerry Smartphone Version: 2.8

ConnectMail Mobile Configuration

Instructions. Outlook (Windows) Mail (Mac) Webmail Windows Live Mail iphone 4, 4S, 5, 5c, 5s Samsung Galaxy S4 BlackBerry

HOW WILL I KNOW THAT I SHOULD USE THE IAS CONTINUITY SERVICE?

User guide. Business

Client configuration and migration Guide Setting up Thunderbird 3.1

Configuring Your Client: Eudora 5.x. Quick Reference

Outlook Express. Make Changes in Red: Open up Outlook Express. From the Menu Bar. Tools to Accounts - Click on. User Information

Set Up Setup with Microsoft Outlook 2007 using POP3

SerialMailer Manual. For SerialMailer 7.2. Copyright Falko Axmann. All rights reserved.

Client Configuration Secure Socket Layer. Information Technology Services 2010

Introduction to XHTML. 2010, Robert K. Moniot 1

Migration Manual (For Outlook Express 6)

Configuring Thunderbird for Flinders Mail at home.

Getting started with IMAP for Aggi What is IMAP?

Outlook Express. Make Changes in Red: Open up Outlook Express. From the Menu Bar. Tools to Accounts - Click on Mail Tab.

RoboMail Mass Mail Software

c. Write a JavaScript statement to print out as an alert box the value of the third Radio button (whether or not selected) in the second form.

Ciphermail for BlackBerry Quick Start Guide

Configuring iplanet 6.0 Web Server For SSL and non-ssl Redirect

How to setup your iphone client

How to Display Weather Data on a Web Page

Outlook 2010 Setup Guide (POP3)

Configuring Thunderbird with UEA Exchange 2007:

Login with Amazon. Getting Started Guide for Websites. Version 1.0

User Guide. Please visit the Helpdesk website for more information:

Configuring Outlook 2010 for Windows

1. Open the preferences screen by opening the Mail menu and selecting Preferences...

How to Set Up LSUS IMAP in Outlook 2013

How to Setup OSX Mail to POP an Exchange Account

Working with forms in PHP

Outlook Start Outlook, and click on mserver.wlu.ca. 2. From the Tools menu, choose Options

THUNDERBIRD SETUP (STEP-BY-STEP)

Webmail Using the Hush Encryption Engine

Configuring Your Suffolk on Outlook Express 6.x

How to set up your Secure in Outlook 2010*

1. Navigate to Control Panel and click on User Accounts and Family Safety. 2. Click on User Accounts

Patriots Outlook Configuration

Steps for: POP (Post Office Protocol) and IMAP (Internet Message Access Protocol) setup on MAC Platforms

Configuring on Mobile Devices

Forms, CGI Objectives. HTML forms. Form example. Form example...

PREMIUM MAIL USER GUIDE

Getting an ipath server running on Linux

Transcription:

Chapter 22 How to send email and access other web sites Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 1

Objectives Applied 1. Install and use the PEAR Mail package to send email messages from your web applications. 2. Use the curl library to work with the data on web sites that provide APIs for doing that. Knowledge 1. Describe the use of the PEAR Mail package, including its static factory method and its mailer object. 2. Describe the use of a helper function for sending email with the PEAR Mail package. 3. Describe the use of the curl library for working with the data on a web site that provides an API for doing that. Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 2

How email is sent Sender Email Client SMTP Server Email server Sender composes message on email client program. Client uses SMTP to send message to sender s email server. Receiver s email client uses POP3 or IMAP to download message from email server. Receiver can then read message. Sender s email server uses SMTP to send message to receiver s email server. SMTP Receiver Email Client POP3 IMAP Server Email server Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 3

Protocols used in sending email SMTP POP3 IMAP Terms email client email server Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 4

Limitations of the built-in PHP mail function You must modify the php.ini file to change email servers. You cannot use an encrypted connection to the email server. You cannot provide a username and password when connecting to the email server. Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 5

How to install the PEAR Mail package in Windows 1. Click the Start menu, select the Programs Accessories group, and click on Command Prompt to open a command prompt window. 2. In the Command Prompt window, type these commands: cd \xampp\php pear install --alldeps Mail exit How to install the PEAR Mail package in Mac OS X 1. In Finder, open the Applications folder, open the Utilities folder, and double click the Terminal icon to open a Terminal window. 2. In the Terminal window, type these commands: cd /Applications/XAMPP/xamppfiles/bin sudo./pear install --alldeps Mail exit Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 6

How to create a Gmail account for email testing 1. If you don t already have a Gmail account, create one. To do that, you can go to www.gmail.com, click on the Create an Account link, and follow the instructions. 2. Login to your Gmail account and go to your Inbox. 3. Click the Settings link at the top of the page. 4. On the Settings page, click the Forwarding and POP/IMAP link. 5. In the POP download section, select the Enable POP for all mail option. 6. Click the Save Changes button. Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 7

Configuration info for a Gmail SMTP server Setting Value Host name smtp.gmail.com Encryption SSL Port number 465 Authentication Yes Username username@gmail.com Password yourgmailpassword Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 8

Step 1: Load the PEAR Mail package require_once 'Mail.php'; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 9

Step 2: Set the parameters for the mailer object Example 1: A simple SMTP server $options = array(); $options['host'] = 'mail.example.com'; Example 2: An SMTP server with authentication $options = array(); $options['host'] = 'mail.example.com'; $options['auth'] = true; $options['username'] = 'sample.user@example.com'; $options['password'] = 'Sup3r*S3cr3+'; Example 3: SMTP server with authentication and SSL encryption $options = array(); $options['host'] = 'ssl://mail.example.com'; $options['port'] = 465; $options['auth'] = true; $options['username'] = 'mail.account@example.com'; $options['password'] = 'Sup3r*S3cr3+'; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 10

Step 3: Create the mailer object $mailer = Mail::factory('smtp', $options); Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 11

Step 4: Send the message // 1. Set the SMTP headers $headers = array(); $headers['from'] = 'sample.user@example.com'; $headers['to'] = 'john.doe@example.com, jane.doe@example.com'; $headers['cc'] = 'fsmith@example.org'; $headers['bcc'] = 'jsmith@example.net'; $headers['subject'] = 'How to use PEAR Mail'; // 2. Set the recipient list $recipients = 'john.doe@example.com, jane.doe@example.com, '; $recipients.= 'fsmith@example.org, jsmith@example.net'; // 3. Set the text for the body of the message $body = "The Murach PHP and MySQL book has a chapter on\n"; $body.= "how to use the PEAR Mail package to send email."; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 12

Step 4: Send the message (continued) // 4. Send the message $result = $mailer->send($recipients, $headers, $body); // 5. Check the result and display an error if one exists if (PEAR::isError($result)) { $error = 'Error sending email: '. $result->getmessage(); echo htmlspecialchars($error); } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 13

How to use HTML formatting in the body of the message // 1. Set the Content-type header $headers['content-type'] = 'text/html'; // 2. Use HTML tags to format the body of the message $body = '<p>the Murach PHP and MySQL book has a chapter on how to use the <a href="http://pear.php.net/mail/"> PEAR Mail package </a> to send email. </p>'; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 14

The message.php file (a helper function) <?php require_once 'Mail.php'; require_once 'Mail/RFC822.php'; function send_email($to, $from, $subject, $body, $is_body_html = false) { if (! valid_email($to)) { throw new Exception('This To address is invalid: '. htmlspecialchars($to)); } if (! valid_email($from)) { throw new Exception('This From address is invalid: '. htmlspecialchars($from)); } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 15

The message.php file (continued) $smtp = array(); // **** You must change the following to match your // **** SMTP server and account information. $smtp['host'] = 'ssl://smtp.gmail.com'; $smtp['port'] = 465; $smtp['auth'] = true; $smtp['username'] = 'example@gmail.com'; $smtp['password'] = 'supersecret'; $mailer = Mail::factory('smtp', $smtp); if (PEAR::isError($mailer)) { throw new Exception('Could not create mailer.'); } // Add the email address to an array of all recipients $recipients = array(); $recipients[] = $to; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 16

The message.php file (continued) // Set the headers $headers = array(); $headers['from'] = $from; $headers['to'] = $to; $headers['subject'] = $subject; if ($is_body_html) { $headers['content-type'] = 'text/html'; } // Send the email $result = $mailer->send($recipients, $headers, $body); } // Check the result and throw an error if one exists if (PEAR::isError($result)) { throw new Exception('Error sending email: '. htmlspecialchars($result->getmessage()) ); } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 17

The message.php file (continued) function valid_email($email) { $emailobjects = Mail_RFC822::parseAddressList($email); if (PEAR::isError($emailObjects)) return false; // Get mailbox and host parts of first email object $mailbox = $emailobjects[0]->mailbox; $host = $emailobjects[0]->host; // Make sure mailbox and host parts aren't too long if (strlen($mailbox) > 64) return false; if (strlen($host) > 255) return false; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 18

The message.php file (continued) // Validate the mailbox $atom = '[[:alnum:]_!#$%&\'*+\/=?^`{ }~-]+'; $dotatom = '(\.'. $atom. ')*'; $address = '(^'. $atom. $dotatom. '$)'; $char = '([^\\\\"])'; $esc = '(\\\\[\\\\"])'; $text = '('. $char. ' '. $esc. ')+'; $quoted = '(^"'. $text. '"$)'; $localpart = '/'. $address. ' '. $quoted. '/'; $localmatch = preg_match($localpart, $mailbox); if ($localmatch === false $localmatch!= 1) { return false; } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 19

The message.php file (continued) // Validate the host $hostname = '([[:alnum:]]([-[:alnum:]]{0,62}[[:alnum:]])?)'; $hostnames = '('. $hostname. '(\.'. $hostname. ')*)'; $top = '\.[[:alnum:]]{2,6}'; $domainpart = '/^'. $hostnames. $top. '$/'; $domainmatch = preg_match($domainpart, $host); if ($domainmatch === false $domainmatch!= 1) { return false; } }?> return true; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 20

How to use the send_email function require_once 'message.php'; $from = 'John Doe <john.doe@example.com>'; $to = 'Jane Doe <jane.doe@example.com>'; $subject = 'How to use PEAR Mail'; $body = '<p>the Murach PHP and MySQL book has a chapter on how to use the <a href="http://pear.php.net/mail/"> PEAR Mail package</a> to send email.</p>'; $is_body_html = true; try { send_email($to, $from, $subject, $body, $is_body_html); } catch (Exception $e) { $error = $e->getmessage(); echo $error; } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 21

How to configure PHP to use the curl library in Windows 1. Open the php.ini file in a text editor. 2. Find the line that contains the text php_curl.dll. 3. Remove the semicolon from the beginning of the line. It should read as follows: extension=php_curl.dll 4. Restart the Apache web server as described in the appendix. Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 22

How to configure PHP to use the curl library in Mac OS X 1. Open the php.ini file in a text editor. 2. Find the line that contains the text curl.so. 3. If necessary, remove the semicolon from the beginning of the line. It should read as follows: extension=curl.so 4. Restart the Apache web server as described in the appendix. Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 23

Common curl functions curl_init($url) curl_setopt($curl, OPTION, $value) curl_exec($curl) curl_close($curl) Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 24

How to use the curl functions // Initialize the curl session $curl = curl_init('http://www.example.com'); // Set the curl options so the session returns data curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Transfer the data and store it $page = curl_exec($curl); // Close the session curl_close($curl); // Process the data $page = nl2br(htmlspecialchars($page)); echo $page; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 25

The URL for the YouTube API documentation http://code.google.com/apis/youtube/2.0/reference.html The base URL for the YouTube Video Search API http://gdata.youtube.com/feeds/api/videos Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 26

Four parameters that you can add to the base URL alt q orderby safesearch Specifies an alternate data format. The default is atom which returns XML data, but you can use json to return data in the JavaScript Object Notation (JSON) format. Specifies the search string. Specifies how to sort the results of the search. The default is relevance ; you can specify other values such as published, viewcount, and rating. Filters videos by removing restricted content. The default value is moderate ; you can specify other values such as none and strict. A URL for a YouTube query http://gdata.youtube.com/feeds/api/videos?alt=json&q=shuttle Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 27

How to use curl to query YouTube // Set up the URL for the query $query = 'space shuttle'; $query = urlencode($query); $base_url = 'http://gdata.youtube.com/feeds/api/videos'; $params = 'alt=json&q='. $query; $url = $base_url. '?'. $params; // Use curl to get data in JSON format $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $json_data = curl_exec($curl); curl_close($curl); // Get an array of videos from the JSON data $data = json_decode($json_data, true); $videos = $data['feed']['entry']; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 28

How to use curl to query YouTube (continued) // Access the data for each video foreach ($videos as $video) { $image_url = $video['media$group']['media$thumbnail'][0]['url']; $video_url = $video['link'][0]['href']; $text = $video['title']['$t']; } // Code to output these values Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 29

Search view Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 30

Email view Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 31

The controller (index.php) <?php require_once 'message.php'; session_start(); function search_youtube($query) { // Set up the URL for the query $query = urlencode($query); $base_url = 'http://gdata.youtube.com/feeds/api/videos'; $params = 'alt=json&q='. $query; $url = $base_url. '?'. $params; // Use curl to get data in JSON format $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $json_data = curl_exec($curl); curl_close($curl); // Get array of videos from the JSON data and return it $data = json_decode($json_data, true); $videos = $data['feed']['entry']; return $videos; } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 32

The controller (continued) if (isset($_post['action'])) { $action = $_POST['action']; } else { $action = 'search'; } if (isset($_post['query'])) { $query = $_POST['query']; $_SESSION['query'] = $query; } else if (isset($_session['query'])) { $query = $_SESSION['query']; } else { $query = ''; } Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 33

The controller (continued) switch ($action) { case 'search': if (!empty($query)) { $videos = search_youtube($query); } include 'search_view.php'; break; case 'display_email_view': $url = $_POST['url']; $text = $_POST['text']; include 'email_view.php'; break; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 34

The controller (continued) case 'send_mail': // Get the data from the Mail View page $from = $_POST['from']; $to = $_POST['to']; $subject = $_POST['subject']; $text = $_POST['text']; $url = $_POST['url']; $message = $_POST['message']; // Create the body $body = $text. "\n\n". $url. "\n\n". $message; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 35

The controller (continued) try { // Send the email send_email($to, $from, $subject, $body); // Display the Search view for the current query $videos = search_youtube($query); include 'search_view.php'; } catch (Exception $e) { $error = $e->getmessage(); include 'email_view.php'; } break; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 36

The controller (continued) }?> default: include 'search_view.php'; break; Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 37

Search view (search_view.php) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0...> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>youtube Search</title> <link rel="stylesheet" type="text/css" href="main.css"/> </head> <body> <div id="page"> <div id="header"><h1>youtube Search</h1></div> <div id="main"> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 38

Search view (continued) <h2>search</h2> <form action="." method="post"> <input type="text" name="query" value="<?php echo $query;?>"/> <input type="submit" value="search"/> </form> <?php if (count($videos)!= 0) :?> <h2>results</h2> <table> <?php foreach ($videos as $video) : $imgsrc = $video['media$group']['media$thumbnail'][0]['url']; $url = $video['link'][0]['href']; $text = $video['title']['$t'];?> <tr> <td> <a href="<?php echo $url;?>"> <img src="<?php echo $imgsrc;?>"> </a> </td> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 39

Search view (continued) <td> <form action="." method="post"> <input type="hidden" name="action" value="display_email_view"/> <input type="hidden" name="url" value="<?php echo $url;?>"/> <input type="hidden" name="text" value="<?php echo $text;?>"/> <input type="submit" value="email this Link"/> </form> <a href="<?php echo $url;?>"> <?php echo $text;?> </a> </td> </tr> <?php endforeach;?> </table> <?php endif;?> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 40

Search view (continued) </div><!-- end main --> </div><!-- end page --> </body> </html> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 41

Email view (mail_view.php) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0...> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>youtube Search</title> <link rel="stylesheet" type="text/css" href="main.css"/> </head> <body> <div id="page"> <div id="header"><h1>youtube Search</h1></div> <div id="main"> <h2>email the YouTube link</h2> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 42

Email view (continued) <?php if (isset($error)) :?> <p>error Sending E-mail: <?php echo $error;?></p> <?php endif;?> <form action="." method="post" id="email_form"> <input type="hidden" name="action" value="send_mail"/> <input type="hidden" name="url" value="<?php echo $url;?>"/> <input type="hidden" name="text" value="<?php echo $text;?>"/> <label>from:</label> <input type="text" name="from"/> Your email address<br /> <label>to:</label> <input type="text" name="to"/> Your friend's email address<br /> <label>subject:</label> <input type="text" name="subject" value="youtube Video Link"/><br /> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 43

Email view (continued) <label>video:</label> <?php echo $text;?><br /> <label>link:</label> <?php echo $url;?><br /> <label>message:</label> <textarea name="message"> I thought you might enjoy this video. </textarea> <br /> <label> </label> <input type="submit" value="send"/> </form> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 44

Email view (continued) <form action="." method="post" id="cancel_form"> <label> </label> <input type="submit" value="cancel"/> </form> </div><!-- end main --> </div><!-- end page --> </body> </html> Murach's PHP and MySQL, C22 2010, Mike Murach & Associates, Inc. Slide 45