662 Chapter 28 Building a Mailing List Manager $list = $HTTP_POST_VARS['list']; $subject = $HTTP_POST_VARS['subject']; if(!db_connect()) { echo '<p>Could not connect to db</p>'; do_html_footer(); exit; } // add mail details to the DB $query = "insert into mail values (NULL, '".$HTTP_SESSION_VARS['admin_user']."', '".$subject."', '".$list."', 'STORED', NULL, NULL)"; $result = mysql_query($query); if(!$result) { do_html_footer(); exit; } //get the id MySQL assigned to this mail $mailid = mysql_insert_id(); if(!$mailid) { do_html_footer(); exit; } // creating directory will fail if this is not the first message archived // that's ok @ mkdir('archive/'.$list, 0700); // it is a problem if creating the specific directory for this mail fails if(!mkdir('archive/'.$list."/$mailid", 0700)) { do_html_footer(); exit; } // iterate through the array of uploaded files $i = 0; Listing 28.16 Continued 34 525x ch28 1/24/03 2:55 PM Page 662 663 Implementing Administrative Functions while ($HTTP_POST_FILES['userfile']['name'][$i]&& $$HTTP_POST_FILES['userfile']['name'][$i]!='none') { echo '<p>Uploading '.$HTTP_POST_FILES['userfile']['name'][$i].' - '; echo $HTTP_POST_FILES['userfile']['size'][$i].' bytes.</p>'; if ($HTTP_POST_FILES['userfile']['size'][$i]==0) { echo 'Problem: '.$HTTP_POST_FILES['userfile']['name'][$i]. ' is zero length'; $i++; continue; } if ($HTTP_POST_FILES['userfile']['size'][$i]>$max_size) { echo 'Problem: '.$HTTP_POST_FILES['userfile']['name'][$i].' is over ' .$max_size.' bytes'; $i++; continue; } // we would like to check that the uploaded image is an image // if getimagesize() can work out its size, it probably is. if($i>1&&!getimagesize($HTTP_POST_FILES['userfile']['tmp_name'][$i])) { echo 'Problem: '.$HTTP_POST_FILES['userfile']['name'][$i]. ' is corrupt, or not a gif, jpeg or png'; $i++; continue; } // file 0 (the text message) and file 1 (the html message) are special cases if($i==0) $destination = "archive/$list/$mailid/text.txt"; else if($i == 1) $destination = "archive/$list/$mailid/index.html"; else { $destination = "archive/$list/$mailid/" .$HTTP_POST_FILES['userfile']['name'][$i]; $query = "insert into images values ($mailid, '".$HTTP_POST_FILES['userfile']['name'][$i]."', '".$HTTP_POST_FILES['userfile']['type'][$i]."')"; $result = mysql_query($query); } Listing 28.16 Continued 34 525x ch28 1/24/03 2:55 PM Page 663 664 Chapter 28 Building a Mailing List Manager //if we are using PHP version >= 4.03 if (!is_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'][$i])) { // possible file upload attack detected echo 'Something funny happening with ' .$HTTP_POST_FILES['userfile']['name'].', not uploading.'; do_html_footer(); exit; } move_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'][$i], $destination); /* // if version <= 4.02 copy ($userfile[$i], $destination); unlink($userfile[$i]); */ $i++; } display_preview_button($list, $mailid, 'preview-html'); display_preview_button($list, $mailid, 'preview-text'); display_button('send', "&id=$mailid"); echo '<br /><br /><br /><br /><br />'; do_html_footer(); ?> Let’s walk through the steps in Listing 28.16. First, we start a session and check that the user is logged in as an administrator—we don’t want to let anybody else upload files. Strictly speaking, we should probably also check the list and mailid variables for unwanted characters, but we have ignored this for the sake of brevity. Next, we set up and send the headers for the page, and validate that the form was filled in correctly.This is important here as it’s quite a complex form for the user to fill out. Then we create an entry for this mail in the database, and set up a directory in the archive for the mail to be stored in. Next comes the main part of the script, which checks and moves each of the uploaded files.This is the part that is different when uploading multiple files.We now have four arrays to deal with.These arrays are called $HTTP_POST_FILES['user- file']['name'], $HTTP_POST_FILES['userfile']['tmp_name'], Listing 28.16 Continued 34 525x ch28 1/24/03 2:55 PM Page 664 665 Implementing Administrative Functions $HTTP_POST_FILES['userfile']['size'] and $HTTP_POST_FILES['userfile']['type'].They correspond to their similarly named equivalents in a single file upload, except that each of them is an array.The first file in the form will be detailed in $HTTP_POST_FILES['userfile']['tmp_name'][0], $HTTP_POST_FILES['userfile']['name'][0], $HTTP_POST_FILES ['userfile']['size'][0],and $HTTP_POST_FILES['userfile']['type'][0]. Given these three arrays, we perform the usual safety checks and move the files into the archive. Finally, we give the administrator some buttons that they can use to preview the newsletter they have uploaded before they send it, and a button to send it.You can see the output from upload.php in Figure 28.13. Figure 28.13 The upload script reports the files uploaded and their sizes. Previewing the Newsletter There are two ways the administrator can preview a newsletter before sending. She can access the preview functions from the upload screen if she wants to preview immediately after upload. She can also click on the View Mail button, which will show her all the unsent newsletters in the system, if she wants to preview and send mail later.The View Mail button activates the view-mail action, which triggers the following code: case 'view-mail' : { 34 525x ch28 1/24/03 2:55 PM Page 665 666 Chapter 28 Building a Mailing List Manager display_items('Unsent Mail', get_unsent_mail(get_email()), 'preview-html', 'preview-text', 'send'); break; } As you can see, this again uses the display_items() function with buttons for the pre- view-html, preview-text,and send actions. One interesting point to note is that the “Preview” buttons do not actually trigger an action, but instead link directly to the newsletter in the archive. If you look back at Listings 28.7 and 28.16, you will see that we use the display_preview_button() func- tion to create these buttons, instead of the usual display_button() function. The display_button() function creates an image link to a script with GET parame- ters where required; the display_preview_button() function gives a plain link into the archive.This link will pop up in a new window, achieved using the target=new attribute of the HTML anchor tag.You can see the result of previewing the HTML version of a newsletter in Figure 28.14. Figure 28.14 A preview of an HTML newsletter, complete with images. Sending the Message Clicking on the Send button for a newsletter activates the send action, which triggers the following code: 34 525x ch28 1/24/03 2:55 PM Page 666 . 'preview-html', 'preview-text', 'send'); break; } As you can see, this again uses the display_items() function with buttons for the pre- view-html, preview-text ,and send. uploaded before they send it, and a button to send it.You can see the output from upload .php in Figure 28.13. Figure 28.13 The upload script reports the files uploaded and their sizes. Previewing. the system, if she wants to preview and send mail later.The View Mail button activates the view-mail action, which triggers the following code: case 'view-mail' : { 34 525x ch28 1/24/03